Merge branch 'develop'

Descuentos
This commit is contained in:
Mauricio Baeza 2017-11-13 00:36:28 -06:00
commit 26913d260f
15 changed files with 979 additions and 72 deletions

View File

@ -238,6 +238,23 @@ class AppEmisor(object):
resp.status = falcon.HTTP_204
class AppCuentasBanco(object):
def __init__(self, db):
self._db = db
def on_get(self, req, resp):
values = req.params
session = req.env['beaker.session']
#~ req.context['result'] = self._db.get_emisor(session['rfc'])
resp.status = falcon.HTTP_200
def on_post(self, req, resp):
values = req.params
req.context['result'] = self._db.cuentasbanco(values)
resp.status = falcon.HTTP_200
class AppFolios(object):
def __init__(self, db):

View File

@ -729,7 +729,9 @@ class LIBO(object):
#~ Si no se encuentra, copia las celdas hacia abajo de
#~ {subtotal.titulo} y {subtotal}
print (data['descuento'])
if 'descuento' in data:
self._copy_cell(cell_title)
self._copy_cell(cell_value)
cell_title = self._set_cell(v='Descuento', cell=cell_title)

View File

@ -15,7 +15,7 @@ from models.db import StorageEngine
from controllers.main import (
AppLogin, AppLogout, AppAdmin, AppEmisor, AppConfig,
AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios,
AppDocumentos, AppFiles, AppPreInvoices
AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco
)
from settings import DEBUG
@ -45,6 +45,7 @@ api.add_route('/partners', AppPartners(db))
api.add_route('/products', AppProducts(db))
api.add_route('/invoices', AppInvoices(db))
api.add_route('/preinvoices', AppPreInvoices(db))
api.add_route('/cuentasbanco', AppCuentasBanco(db))
if DEBUG:

View File

@ -91,12 +91,27 @@ class StorageEngine(object):
def _get_allcurrencies(self, values):
return main.SATMonedas.get_()
def _get_allbancos(self, values):
return main.SATBancos.get_()
def _get_allunidades(self, values):
return main.SATUnidades.get_()
def _get_taxupdate(self, values):
return main.SATImpuestos.actualizar(values)
def _get_currencyupdate(self, values):
return main.SATMonedas.actualizar(values)
def _get_bancoupdate(self, values):
return main.SATBancos.actualizar(values)
def _get_unidadupdate(self, values):
return main.SATUnidades.actualizar(values)
def _get_emisorcuentasbanco(self, values):
return main.CuentasBanco.emisor()
def _get_satkey(self, values):
return main.get_sat_key(values['key'])
@ -106,11 +121,17 @@ class StorageEngine(object):
def _get_monedas(self, values):
return main.SATMonedas.get_activos()
def _get_monedasid(self, values):
return main.SATMonedas.get_activos_by_id()
def _get_bancosid(self, values):
return main.SATBancos.get_activos_by_id()
def _get_regimenes(self, values):
return main.Emisor.get_regimenes()
def _get_usocfdi(self, values):
return main.SATUsoCfdi.get_activos(values)
return main.SATUsoCfdi.get_activos()
def delete(self, table, id):
if table == 'partner':
@ -170,12 +191,18 @@ class StorageEngine(object):
def _get_timbrar(self, values):
return main.Facturas.timbrar(int(values['id']))
def _get_anticipoegreso(self, values):
return main.Facturas.anticipo_egreso(int(values['id']))
def get_emisor(self, rfc):
return main.Emisor.get_(rfc)
def emisor(self, values):
return main.Emisor.add(values)
def cuentasbanco(self, values):
return main.CuentasBanco.add(values)
def get_folios(self):
return main.Folios.get_()

View File

@ -15,7 +15,7 @@ if __name__ == '__main__':
from controllers import util
from settings import log, VERSION, PATH_CP, COMPANIES, PRE, CURRENT_CFDI, \
INIT_VALUES
INIT_VALUES, DEFAULT_PASSWORD
FORMAT = '{0:.2f}'
@ -574,6 +574,32 @@ class SATUnidades(BaseModel):
(('key', 'name'), True),
)
@classmethod
def get_(self):
rows = SATUnidades.select().dicts()
return tuple(rows)
@classmethod
def actualizar(self, values):
id = int(values['id'])
if values['field'] == 'activo':
v = {'0': False, '1': True}
q = (SATUnidades
.update(**{'activo': v[values['value']]})
.where(SATUnidades.id==id))
result = bool(q.execute())
elif values['field'] == 'default':
q = SATUnidades.update(**{'default': False})
q.execute()
v = {'false': False, 'true': True}
q = (SATUnidades
.update(**{'default': v[values['value']]})
.where(SATUnidades.id==id))
result = bool(q.execute())
return {'ok': result}
@classmethod
def get_activos(cls):
rows = (SATUnidades
@ -658,6 +684,17 @@ class SATMonedas(BaseModel):
)
return tuple(rows)
@classmethod
def get_activos_by_id(cls):
rows = (SATMonedas
.select(
SATMonedas.id,
SATMonedas.name.alias('value'))
.where(SATMonedas.activo==True)
.dicts()
)
return tuple(rows)
@classmethod
def actualizar(self, values):
id = int(values['id'])
@ -756,6 +793,127 @@ class SATTipoRelacion(BaseModel):
class SATBancos(BaseModel):
key = TextField(index=True, unique=True)
name = TextField(index=True)
razon_social = TextField(default='')
rfc = TextField(default='')
activo = BooleanField(default=False)
class Meta:
order_by = ('-activo', 'name')
indexes = (
(('key', 'name'), True),
)
def __str__(self):
return 'Banco: {} ({})'.format(self.name, self.key)
@classmethod
def get_(cls):
rows = SATBancos.select().dicts()
return tuple(rows)
@classmethod
def get_activos_by_id(cls):
rows = (SATBancos
.select(
SATBancos.id,
SATBancos.name.alias('value'))
.where(SATBancos.activo==True)
.dicts()
)
return tuple(rows)
@classmethod
def actualizar(cls, values):
id = int(values['id'])
if values['field'] == 'activo':
v = {'0': False, '1': True}
q = (SATBancos
.update(**{'activo': v[values['value']]})
.where(SATBancos.id==id))
result = bool(q.execute())
return {'ok': result}
class CuentasBanco(BaseModel):
de_emisor = BooleanField(default=False)
activa = BooleanField(default=True)
nombre = TextField()
banco = ForeignKeyField(SATBancos)
fecha_apertura = DateField(null=True)
cuenta = TextField(default='')
clabe = TextField(default='')
moneda = ForeignKeyField(SATMonedas)
saldo_inicial = DecimalField(default=0.0, max_digits=20, decimal_places=6,
auto_round=True)
saldo = DecimalField(default=0.0, max_digits=20, decimal_places=6,
auto_round=True)
class Meta:
order_by = ('nombre',)
indexes = (
(('banco', 'cuenta'), True),
)
def __str__(self):
return '{} ({})'.format(self.banco.name, self.cuenta[-4:])
@classmethod
def emisor(cls):
rows = (CuentasBanco
.select(
CuentasBanco.id,
CuentasBanco.activa,
CuentasBanco.nombre,
SATBancos.name.alias('banco'),
CuentasBanco.fecha_apertura,
CuentasBanco.cuenta,
CuentasBanco.clabe,
SATMonedas.name.alias('moneda'),
CuentasBanco.saldo
)
.join(SATBancos).switch(CuentasBanco)
.join(SATMonedas).switch(CuentasBanco)
.where(CuentasBanco.de_emisor==True).dicts()
)
return tuple(rows)
@classmethod
def add(cls, values):
w = '37137137137137137'
dv = str(
10 -
sum([(int(v) * int(values['clabe'][i])) % 10 for i, v in enumerate(w)])
% 10)
if dv != values['clabe'][-1]:
msg = 'Digito de control de la CLABE es incorrecto'
return {'ok': False, 'msg': msg}
with database_proxy.transaction():
obj = CuentasBanco.create(**values)
rows = (CuentasBanco
.select(
CuentasBanco.id,
CuentasBanco.activa,
CuentasBanco.nombre,
SATBancos.name.alias('banco'),
CuentasBanco.fecha_apertura,
CuentasBanco.cuenta,
CuentasBanco.clabe,
SATMonedas.name.alias('moneda'),
CuentasBanco.saldo
)
.join(SATBancos).switch(CuentasBanco)
.join(SATMonedas).switch(CuentasBanco)
.where(CuentasBanco.id==obj.id).dicts()
)
data = {'ok': True, 'row': rows[0]}
return data
class SATUsoCfdi(BaseModel):
key = TextField(index=True, unique=True)
name = TextField(default='', index=True)
@ -774,13 +932,16 @@ class SATUsoCfdi(BaseModel):
return 'Uso del CFDI: {} ({})'.format(self.name, self.key)
@classmethod
def get_activos(cls, values):
field = SATUsoCfdi.id
if values:
field = SATUsoCfdi.key.alias('id')
def get_id(self, key):
if key is None:
return
return SATUsoCfdi.get(SATUsoCfdi.key==key).id
@classmethod
def get_activos(cls):
rows = (SATUsoCfdi
.select(
field,
SATUsoCfdi.key.alias('id'),
SATUsoCfdi.name.alias('value'),
SATUsoCfdi.fisica,
SATUsoCfdi.moral,
@ -791,6 +952,15 @@ class SATUsoCfdi(BaseModel):
return tuple(rows)
class TipoCambio(BaseModel):
dia = DateField(default=util.now)
moneda = ForeignKeyField(SATMonedas)
tipo_cambio = DecimalField(max_digits=15, decimal_places=6, auto_round=True)
class Meta:
order_by = ('-dia',)
class Addendas(BaseModel):
nombre = TextField(unique=True)
addenda = TextField()
@ -851,7 +1021,8 @@ class Socios(BaseModel):
fields['rfc'] = fields['rfc'].upper()
fields['nombre'] = util.spaces(fields['nombre'])
fields['slug'] = util.to_slug(fields['nombre'])
fields['uso_cfdi'] = fields.pop('uso_cfdi_socio', None)
uso_cfdi = fields.pop('uso_cfdi_socio', None)
fields['uso_cfdi'] = SATUsoCfdi.get_id(uso_cfdi)
fields['condicion_pago'] = \
CondicionesPago.get_or(fields.get('condicion_pago', None))
@ -872,7 +1043,14 @@ class Socios(BaseModel):
str(CondicionesPago.get(id=row['condicion_pago']))
return row
rows = Socios.select(Socios.id, Socios.rfc, Socios.nombre).dicts()
rows = (Socios
.select(
Socios.id,
Socios.rfc,
Socios.nombre,
Socios.saldo_cliente)
.dicts()
)
return {'ok': True, 'rows': tuple(rows)}
@classmethod
@ -889,7 +1067,6 @@ class Socios(BaseModel):
.where((Socios.id==id) & (Socios.es_cliente==True))
.dicts()
)
#~ print (id, row)
if len(row):
return {'ok': True, 'row': row[0]}
return {'ok': False}
@ -919,12 +1096,13 @@ class Socios(BaseModel):
data = {'ok': False, 'row': {}, 'new': True, 'msg': msg}
return data
#~ ToDo Agregar Condicion de pago y tags
#~ ToDo Agregar tags
row = {
'id': obj.id,
'rfc': obj.rfc,
'nombre': obj.nombre,
'saldo_cliente': obj.saldo_cliente,
}
data = {'ok': True, 'row': row, 'new': True}
return data
@ -933,7 +1111,6 @@ class Socios(BaseModel):
def actualizar(cls, values, id):
fields = cls._clean(cls, values)
try:
#~ print (fields)
q = Socios.update(**fields).where(Socios.id==id)
q.execute()
except IntegrityError:
@ -1005,8 +1182,13 @@ class Productos(BaseModel):
id = int(values.get('id', 0))
if id:
row = (Productos
.select(Productos.id, Productos.clave, Productos.descripcion,
SATUnidades.name.alias('unidad'), Productos.valor_unitario)
.select(
Productos.id,
Productos.clave,
Productos.descripcion,
SATUnidades.name.alias('unidad'),
Productos.valor_unitario,
Productos.descuento)
.join(SATUnidades).switch(Productos)
.where(Productos.id==id).dicts())
if len(row):
@ -1162,7 +1344,8 @@ class Facturas(BaseModel):
descuento = DecimalField(default=0.0, max_digits=20, decimal_places=6,
auto_round=True)
moneda = TextField(default='MXN')
tipo_cambio = DecimalField(default=1.0, decimal_places=6, auto_round=True)
tipo_cambio = DecimalField(default=1.0, max_digits=15, decimal_places=6,
auto_round=True)
total = DecimalField(default=0.0, max_digits=20, decimal_places=6,
auto_round=True)
total_mn = DecimalField(default=0.0, max_digits=20, decimal_places=6,
@ -1187,6 +1370,8 @@ class Facturas(BaseModel):
fecha_cancelacion = DateTimeField(null=True)
acuse = TextField(default='')
donativo = BooleanField(default=False)
anticipo = BooleanField(default=False)
egreso_anticipo = BooleanField(default=False)
tipo_relacion = TextField(default='')
error = TextField(default='')
@ -1313,8 +1498,6 @@ class Facturas(BaseModel):
obj = SATTipoRelacion.get(SATTipoRelacion.key==invoice.tipo_relacion)
values['tiporelacion'] = str(obj)
print ('\nTR', invoice.tipo_relacion)
return values
@classmethod
@ -1352,6 +1535,21 @@ class Facturas(BaseModel):
def _send(self, id, rfc):
return Facturas.send(id, rfc)
@util.run_in_thread
def _actualizar_saldo_cliente(self, invoice):
if invoice.tipo_comprobante == 'T':
return
importe = invoice.total_mn
if invoice.tipo_comprobante == 'E':
importe *= -1
q = (Socios
.update(saldo_cliente=Socios.saldo_cliente + importe)
.where(Socios.id==invoice.cliente.id)
)
return bool(q.execute())
@classmethod
def send(cls, id, rfc):
values = Configuracion.get_({'fields': 'correo'})
@ -1440,12 +1638,14 @@ class Facturas(BaseModel):
else:
f_ids = (Facturas.id > 0)
filters = (fy & fm & cliente & f_ids)
if folios:
filters = (fy & fm & folios & cliente & f_ids)
filters = filters & folios
elif uuid:
filters = (fy & fm & f_uuid & cliente & f_ids)
else:
filters = (fy & fm & cliente & f_ids)
filters = filters & f_uuid
if values['anticipo'] == '1':
filters = filters & (Facturas.anticipo == True)
rows = tuple(Facturas
.select(Facturas.id, Facturas.serie, Facturas.folio,
@ -1521,6 +1721,7 @@ class Facturas(BaseModel):
def _calculate_totals(self, invoice, products):
subtotal = 0
descuento_cfdi = 0
totals_tax = {}
total_trasladados = None
total_retenciones = None
@ -1529,29 +1730,44 @@ class Facturas(BaseModel):
for product in products:
id_product = product.pop('id')
p = Productos.get(Productos.id==id_product)
#~ product['descripcion'] = p.descripcion
product['unidad'] = p.unidad.key
product['clave'] = p.clave
product['clave_sat'] = p.clave_sat
product['factura'] = invoice.id
product['producto'] = id_product
product['importe'] = round(
float(product['cantidad']) * float(product['valor_unitario']), 2)
subtotal += product['importe']
cantidad = float(product['cantidad'])
valor_unitario = float(product['valor_unitario'])
descuento = float(product['descuento'])
precio_final = valor_unitario - descuento
importe = round(cantidad * precio_final, 2)
product['cantidad'] = cantidad
product['valor_unitario'] = valor_unitario
product['descuento'] = descuento
product['precio_final'] = precio_final
product['importe'] = round(cantidad * valor_unitario, 2)
descuento_cfdi += descuento
subtotal += importe
FacturasDetalle.create(**product)
for tax in p.impuestos:
if tax.id in totals_tax:
totals_tax[tax.id].importe += product['importe']
#~ totals_tax[tax.id].importe += product['importe']
totals_tax[tax.id].importe += importe
else:
tax.importe = product['importe']
#~ tax.importe = product['importe']
tax.importe = importe
totals_tax[tax.id] = tax
#~ totals_tax[tax.id]['importe'] = product['importe']
for tax in totals_tax.values():
if tax.tipo == 'E' or tax.tipo == 'R':
continue
import_tax = round(float(tax.tasa) * tax.importe, 2)
total_trasladados = (total_trasladados or 0) + import_tax
if tax.name == 'IVA':
@ -1585,7 +1801,8 @@ class Facturas(BaseModel):
total = subtotal + (total_trasladados or 0) - (total_retenciones or 0)
total_mn = round(total * invoice.tipo_cambio, 2)
data = {
'subtotal': subtotal,
'subtotal': subtotal + descuento,
'descuento': descuento_cfdi,
'total': total,
'total_mn': total_mn,
'total_trasladados': total_trasladados,
@ -1611,12 +1828,14 @@ class Facturas(BaseModel):
values['folio'] = cls._get_folio(cls, values['serie'])
values['tipo_cambio'] = float(values['tipo_cambio'])
values['lugar_expedicion'] = emisor.cp_expedicion or emisor.codigo_postal
values['anticipo'] = util.get_bool(values['anticipo'])
with database_proxy.atomic() as txn:
obj = Facturas.create(**values)
totals = cls._calculate_totals(cls, obj, productos)
cls._guardar_relacionados(cls, obj, relacionados)
obj.subtotal = totals['subtotal']
obj.descuento = totals['descuento']
obj.total_trasladados = totals['total_trasladados']
obj.total_retenciones = totals['total_retenciones']
obj.total = totals['total']
@ -1664,6 +1883,9 @@ class Facturas(BaseModel):
comprobante['TipoDeComprobante'] = invoice.tipo_comprobante
comprobante['MetodoPago'] = invoice.metodo_pago
comprobante['LugarExpedicion'] = invoice.lugar_expedicion
if invoice.descuento:
comprobante['Descuento'] = FORMAT.format(invoice.descuento)
if invoice.tipo_relacion:
relacionados = {
'tipo': invoice.tipo_relacion,
@ -1682,6 +1904,7 @@ class Facturas(BaseModel):
'UsoCFDI': invoice.uso_cfdi,
}
#~ descuento = 0
conceptos = []
rows = FacturasDetalle.select().where(FacturasDetalle.factura==invoice)
for row in rows:
@ -1695,6 +1918,9 @@ class Facturas(BaseModel):
'ValorUnitario': FORMAT.format(row.valor_unitario),
'Importe': FORMAT.format(row.importe),
}
if row.descuento:
concepto['Descuento'] = FORMAT.format(row.descuento)
#~ descuento += row.descuento
taxes = {}
traslados = []
@ -1703,12 +1929,13 @@ class Facturas(BaseModel):
for impuesto in row.producto.impuestos:
if impuesto.tipo == 'E':
continue
import_tax = round(impuesto.tasa * row.importe, 2)
base = row.importe - row.descuento
import_tax = round(impuesto.tasa * base, 2)
tipo_factor = 'Tasa'
if impuesto.factor != 'T':
tipo_factor = 'Cuota'
tax = {
"Base": FORMAT.format(row.importe),
"Base": FORMAT.format(base),
"Impuesto": impuesto.key,
"TipoFactor": tipo_factor,
"TasaOCuota": str(impuesto.tasa),
@ -1726,6 +1953,9 @@ class Facturas(BaseModel):
concepto['impuestos'] = taxes
conceptos.append(concepto)
#~ if descuento:
#~ comprobante['Descuento'] = FORMAT.format(descuento)
impuestos = {}
traslados = []
retenciones = []
@ -1778,6 +2008,42 @@ class Facturas(BaseModel):
obj.save()
return obj.estatus_sat
@classmethod
def anticipo_egreso(cls, id):
origen = Facturas.get(Facturas.id == id)
relacionadas = (FacturasRelacionadas
.select(FacturasRelacionadas.factura_origen)
.where(FacturasRelacionadas.factura==origen))
conceptos = (FacturasDetalle
.select()
.where(FacturasDetalle.factura==origen))
impuestos = (FacturasImpuestos
.select()
.where(FacturasImpuestos.factura==origen))
#~ egreso_anticipo = BooleanField(default=False)
serie = Folios.get_egreso(origen.serie)
nueva = {
'cliente': origen.cliente,
'tipo_comprobante': 'E',
'forma_pago': '30',
'serie': serie,
'folio': cls._get_folio(cls, serie),
'tipo_relacion': '07',
'pagada': True,
'lugar_expedicion': origen.lugar_expedicion,
'uso_cfdi': origen.uso_cfdi,
'moneda': origen.moneda,
'tipo_cambio': origen.tipo_cambio,
'regimen_fiscal': origen.regimen_fiscal,
'subtotal': origen.subtotal,
'total': origen.total,
'total_trasladados': origen.total_trasladados,
'total_retenciones': origen.total_retenciones,
}
return
@classmethod
def timbrar(cls, id):
obj = Facturas.get(Facturas.id == id)
@ -1788,6 +2054,7 @@ class Facturas(BaseModel):
enviar_correo = util.get_bool(Configuracion.get_('correo_directo'))
auth = Emisor.get_auth()
anticipo = False
msg = 'Factura timbrada correctamente'
result = util.timbra_xml(obj.xml, auth)
if result['ok']:
@ -1800,6 +2067,9 @@ class Facturas(BaseModel):
row = {'uuid': obj.uuid, 'estatus': 'Timbrada'}
if enviar_correo:
cls._send(cls, id, auth['RFC'])
if obj.tipo_comprobante == 'I' and obj.tipo_relacion == '07':
anticipo = True
cls._actualizar_saldo_cliente(cls, obj)
else:
msg = result['error']
obj.estatus = 'Error'
@ -1807,7 +2077,14 @@ class Facturas(BaseModel):
obj.save()
row = {'estatus': 'Error'}
return {'ok': result['ok'], 'msg': msg, 'row': row}
result = {
'ok': result['ok'],
'msg': msg,
'row': row,
'anticipo': anticipo
}
return result
class PreFacturas(BaseModel):
@ -1954,6 +2231,9 @@ class PreFacturas(BaseModel):
data['totales']['subtotal'] = str(data['comprobante']['subtotal'])
data['totales']['total'] = str(data['comprobante']['total'])
if obj['descuento']:
data['totales']['descuento'] = float(obj['descuento'])
taxes = PreFacturasImpuestos.get_(id)
data['totales']['traslados'] = taxes['traslados']
data['totales']['retenciones'] = taxes['retenciones']
@ -2040,6 +2320,7 @@ class PreFacturas(BaseModel):
def _calculate_totals(self, invoice, products):
subtotal = 0
descuento_cfdi = 0
totals_tax = {}
total_trasladados = None
total_retenciones = None
@ -2048,25 +2329,36 @@ class PreFacturas(BaseModel):
for product in products:
id_product = product.pop('id')
p = Productos.get(Productos.id==id_product)
#~ product['descripcion'] = p.descripcion
product['unidad'] = p.unidad.key
product['clave'] = p.clave
product['clave_sat'] = p.clave_sat
product['factura'] = invoice.id
product['producto'] = id_product
product['importe'] = round(
float(product['cantidad']) * float(product['valor_unitario']), 2)
subtotal += product['importe']
cantidad = float(product['cantidad'])
valor_unitario = float(product['valor_unitario'])
descuento = float(product['descuento'])
precio_final = valor_unitario - descuento
importe = round(cantidad * precio_final, 2)
product['cantidad'] = cantidad
product['valor_unitario'] = valor_unitario
product['descuento'] = descuento
product['precio_final'] = precio_final
product['importe'] = round(cantidad * valor_unitario, 2)
descuento_cfdi += descuento
subtotal += importe
PreFacturasDetalle.create(**product)
for tax in p.impuestos:
if tax.id in totals_tax:
totals_tax[tax.id].importe += product['importe']
totals_tax[tax.id].importe += importe
else:
tax.importe = product['importe']
tax.importe = importe
totals_tax[tax.id] = tax
#~ totals_tax[tax.id]['importe'] = product['importe']
for tax in totals_tax.values():
if tax.tipo == 'E' or tax.tipo == 'R':
@ -2104,7 +2396,8 @@ class PreFacturas(BaseModel):
total = subtotal + (total_trasladados or 0) - (total_retenciones or 0)
total_mn = round(total * invoice.tipo_cambio, 2)
data = {
'subtotal': subtotal,
'subtotal': subtotal + descuento,
'descuento': descuento_cfdi,
'total': total,
'total_mn': total_mn,
'total_trasladados': total_trasladados,
@ -2114,7 +2407,6 @@ class PreFacturas(BaseModel):
@classmethod
def add(cls, values):
print ('VALUES', values)
productos = util.loads(values.pop('productos'))
emisor = Emisor.select()[0]
@ -2127,6 +2419,7 @@ class PreFacturas(BaseModel):
obj = PreFacturas.create(**values)
totals = cls._calculate_totals(cls, obj, productos)
obj.subtotal = totals['subtotal']
obj.descuento = totals['descuento']
obj.total_trasladados = totals['total_trasladados']
obj.total_retenciones = totals['total_retenciones']
obj.total = totals['total']
@ -2450,8 +2743,8 @@ def _crear_tablas(rfc):
PreFacturas, PreFacturasDetalle, PreFacturasImpuestos,
PreFacturasRelacionadas,
SATAduanas, SATFormaPago, SATImpuestos, SATMonedas, SATRegimenes,
SATTipoRelacion, SATUnidades, SATUsoCfdi,
Socios, Tags, Usuarios,
SATTipoRelacion, SATUnidades, SATUsoCfdi, SATBancos,
Socios, Tags, Usuarios, CuentasBanco, TipoCambio,
Emisor.regimenes.get_through_model(),
Socios.tags.get_through_model(),
Productos.impuestos.get_through_model(),
@ -2461,10 +2754,10 @@ def _crear_tablas(rfc):
database_proxy.create_tables(tablas, True)
log.info('Tablas creadas correctamente...')
contraseña = 'blades3.3'
usuarios = (
{'usuario': 'superadmin', 'contraseña': contraseña, 'es_superusuario': True},
{'usuario': 'admin', 'contraseña': contraseña, 'es_admin': True},
{'usuario': 'superadmin', 'contraseña': DEFAULT_PASSWORD,
'es_superusuario': True},
{'usuario': 'admin', 'contraseña': DEFAULT_PASSWORD, 'es_admin': True},
)
for usuario in usuarios:

View File

@ -91,3 +91,4 @@ PRE = {
}
CURRENT_CFDI = '3.3'
DEFAULT_PASSWORD = 'blades3.3'

View File

@ -99,6 +99,104 @@
{"key": "615", "name": "Régimen de los ingresos por obtención de premios", "fisica": true, "activo": false}
]
},
{
"tabla": "SATBancos",
"datos": [
{"key": "002", "name": "BANAMEX", "razon_social": "Banco Nacional de México, S.A., Institución de Banca Múltiple, Grupo Financiero Banamex"},
{"key": "006", "name": "BANCOMEXT", "razon_social": "Banco Nacional de Comercio Exterior, Sociedad Nacional de Crédito, Institución de Banca de Desarrollo"},
{"key": "009", "name": "BANOBRAS", "razon_social": "Banco Nacional de Obras y Servicios Públicos, Sociedad Nacional de Crédito, Institución de Banca de Desarrollo"},
{"key": "012", "name": "BBVABANCOMER", "razon_social": "BBVA Bancomer, S.A., Institución de Banca Múltiple, Grupo Financiero BBVA Bancomer"},
{"key": "014", "name": "SANTANDER", "razon_social": "Banco Santander (México), S.A., Institución de Banca Múltiple, Grupo Financiero Santander"},
{"key": "019", "name": "BANJERCITO", "razon_social": "Banco Nacional del Ejército, Fuerza Aérea y Armada, Sociedad Nacional de Crédito, Institución de Banca de Desarrollo"},
{"key": "021", "name": "HSBC", "razon_social": "HSBC México, S.A., institución De Banca Múltiple, Grupo Financiero HSBC"},
{"key": "030", "name": "BAJIO", "razon_social": "Banco del Bajío, S.A., Institución de Banca Múltiple"},
{"key": "106", "name": "BAMSA", "razon_social": "Bank of America México, S.A., Institución de Banca Múltiple, Grupo Financiero Bank of America"},
{"key": "032", "name": "IXE", "razon_social": "IXE Banco, S.A., Institución de Banca Múltiple, IXE Grupo Financiero"},
{"key": "036", "name": "INBURSA", "razon_social": "Banco Inbursa, S.A., Institución de Banca Múltiple, Grupo Financiero Inbursa"},
{"key": "037", "name": "INTERACCIONES", "razon_social": "Banco Interacciones, S.A., Institución de Banca Múltiple"},
{"key": "042", "name": "MIFEL", "razon_social": "Banca Mifel, S.A., Institución de Banca Múltiple, Grupo Financiero Mifel"},
{"key": "044", "name": "SCOTIABANK", "razon_social": "Scotiabank Inverlat, S.A."},
{"key": "059", "name": "INVEX", "razon_social": "Banco Invex, S.A., Institución de Banca Múltiple, Invex Grupo Financiero"},
{"key": "058", "name": "BANREGIO", "razon_social": "Banco Regional de Monterrey, S.A., Institución de Banca Múltiple, Banregio Grupo Financiero"},
{"key": "060", "name": "BANSI", "razon_social": "Bansi, S.A., Institución de Banca Múltiple"},
{"key": "062", "name": "AFIRME", "razon_social": "Banca Afirme, S.A., Institución de Banca Múltiple"},
{"key": "072", "name": "BANORTE", "razon_social": "Banco Mercantil del Norte, S.A., Institución de Banca Múltiple, Grupo Financiero Banorte"},
{"key": "102", "name": "THE ROYAL BANK", "razon_social": "The Royal Bank of Scotland México, S.A., Institución de Banca Múltiple"},
{"key": "103", "name": "AMERICAN EXPRESS", "razon_social": "American Express Bank (México), S.A., Institución de Banca Múltiple"},
{"key": "108", "name": "TOKYO", "razon_social": "Bank of Tokyo-Mitsubishi UFJ (México), S.A."},
{"key": "110", "name": "JP MORGAN", "razon_social": "Banco J.P. Morgan, S.A., Institución de Banca Múltiple, J.P. Morgan Grupo Financiero"},
{"key": "112", "name": "BMONEX", "razon_social": "Banco Monex, S.A., Institución de Banca Múltiple"},
{"key": "113", "name": "VE POR MAS", "razon_social": "Banco Ve Por Mas, S.A. Institución de Banca Múltiple"},
{"key": "116", "name": "ING", "razon_social": "ING Bank (México), S.A., Institución de Banca Múltiple, ING Grupo Financiero"},
{"key": "124", "name": "DEUTSCHE", "razon_social": "Deutsche Bank México, S.A., Institución de Banca Múltiple"},
{"key": "126", "name": "CREDIT SUISSE", "razon_social": "Banco Credit Suisse (México), S.A. Institución de Banca Múltiple, Grupo Financiero Credit Suisse (México)"},
{"key": "127", "name": "AZTECA", "razon_social": "Banco Azteca, S.A. Institución de Banca Múltiple."},
{"key": "128", "name": "AUTOFIN", "razon_social": "Banco Autofin México, S.A. Institución de Banca Múltiple"},
{"key": "129", "name": "BARCLAYS", "razon_social": "Barclays Bank México, S.A., Institución de Banca Múltiple, Grupo Financiero Barclays México"},
{"key": "130", "name": "COMPARTAMOS", "razon_social": "Banco Compartamos, S.A., Institución de Banca Múltiple"},
{"key": "131", "name": "BANCO FAMSA", "razon_social": "Banco Ahorro Famsa, S.A., Institución de Banca Múltiple"},
{"key": "132", "name": "BMULTIVA", "razon_social": "Banco Multiva, S.A., Institución de Banca Múltiple, Multivalores Grupo Financiero"},
{"key": "133", "name": "ACTINVER", "razon_social": "Banco Actinver, S.A. Institución de Banca Múltiple, Grupo Financiero Actinver"},
{"key": "134", "name": "WAL-MART", "razon_social": "Banco Wal-Mart de México Adelante, S.A., Institución de Banca Múltiple"},
{"key": "135", "name": "NAFIN", "razon_social": "Nacional Financiera, Sociedad Nacional de Crédito, Institución de Banca de Desarrollo"},
{"key": "136", "name": "INTERBANCO", "razon_social": "Inter Banco, S.A. Institución de Banca Múltiple"},
{"key": "137", "name": "BANCOPPEL", "razon_social": "BanCoppel, S.A., Institución de Banca Múltiple"},
{"key": "138", "name": "ABC CAPITAL", "razon_social": "ABC Capital, S.A., Institución de Banca Múltiple"},
{"key": "139", "name": "UBS BANK", "razon_social": "UBS Bank México, S.A., Institución de Banca Múltiple, UBS Grupo Financiero"},
{"key": "140", "name": "CONSUBANCO", "razon_social": "Consubanco, S.A. Institución de Banca Múltiple"},
{"key": "141", "name": "VOLKSWAGEN", "razon_social": "Volkswagen Bank, S.A., Institución de Banca Múltiple"},
{"key": "143", "name": "CIBANCO", "razon_social": "CIBanco, S.A."},
{"key": "145", "name": "BBASE", "razon_social": "Banco Base, S.A., Institución de Banca Múltiple"},
{"key": "166", "name": "BANSEFI", "razon_social": "Banco del Ahorro Nacional y Servicios Financieros, Sociedad Nacional de Crédito, Institución de Banca de Desarrollo"},
{"key": "168", "name": "HIPOTECARIA FEDERAL", "razon_social": "Sociedad Hipotecaria Federal, Sociedad Nacional de Crédito, Institución de Banca de Desarrollo"},
{"key": "600", "name": "MONEXCB", "razon_social": "Monex Casa de Bolsa, S.A. de C.V. Monex Grupo Financiero"},
{"key": "601", "name": "GBM", "razon_social": "GBM Grupo Bursátil Mexicano, S.A. de C.V. Casa de Bolsa"},
{"key": "602", "name": "MASARI", "razon_social": "Masari Casa de Bolsa, S.A."},
{"key": "605", "name": "VALUE", "razon_social": "Value, S.A. de C.V. Casa de Bolsa"},
{"key": "606", "name": "ESTRUCTURADORES", "razon_social": "Estructuradores del Mercado de Valores Casa de Bolsa, S.A. de C.V."},
{"key": "607", "name": "TIBER", "razon_social": "Casa de Cambio Tiber, S.A. de C.V."},
{"key": "608", "name": "VECTOR", "razon_social": "Vector Casa de Bolsa, S.A. de C.V."},
{"key": "610", "name": "B&B", "razon_social": "B y B, Casa de Cambio, S.A. de C.V."},
{"key": "614", "name": "ACCIVAL", "razon_social": "Acciones y Valores Banamex, S.A. de C.V., Casa de Bolsa"},
{"key": "615", "name": "MERRILL LYNCH", "razon_social": "Merrill Lynch México, S.A. de C.V. Casa de Bolsa"},
{"key": "616", "name": "FINAMEX", "razon_social": "Casa de Bolsa Finamex, S.A. de C.V."},
{"key": "617", "name": "VALMEX", "razon_social": "Valores Mexicanos Casa de Bolsa, S.A. de C.V."},
{"key": "618", "name": "UNICA", "razon_social": "Unica Casa de Cambio, S.A. de C.V."},
{"key": "619", "name": "MAPFRE", "razon_social": "MAPFRE Tepeyac, S.A."},
{"key": "620", "name": "PROFUTURO", "razon_social": "Profuturo G.N.P., S.A. de C.V., Afore"},
{"key": "621", "name": "CB ACTINVER", "razon_social": "Actinver Casa de Bolsa, S.A. de C.V."},
{"key": "622", "name": "OACTIN", "razon_social": "OPERADORA ACTINVER, S.A. DE C.V."},
{"key": "623", "name": "SKANDIA", "razon_social": "Skandia Vida, S.A. de C.V."},
{"key": "626", "name": "CBDEUTSCHE", "razon_social": "Deutsche Securities, S.A. de C.V. CASA DE BOLSA"},
{"key": "627", "name": "ZURICH", "razon_social": "Zurich Compañía de Seguros, S.A."},
{"key": "628", "name": "ZURICHVI", "razon_social": "Zurich Vida, Compañía de Seguros, S.A."},
{"key": "629", "name": "SU CASITA", "razon_social": "Hipotecaria Su Casita, S.A. de C.V. SOFOM ENR"},
{"key": "630", "name": "CB INTERCAM", "razon_social": "Intercam Casa de Bolsa, S.A. de C.V."},
{"key": "631", "name": "CI BOLSA", "razon_social": "CI Casa de Bolsa, S.A. de C.V."},
{"key": "632", "name": "BULLTICK CB", "razon_social": "Bulltick Casa de Bolsa, S.A., de C.V."},
{"key": "633", "name": "STERLING", "razon_social": "Sterling Casa de Cambio, S.A. de C.V."},
{"key": "634", "name": "FINCOMUN", "razon_social": "Fincomún, Servicios Financieros Comunitarios, S.A. de C.V."},
{"key": "636", "name": "HDI SEGUROS", "razon_social": "HDI Seguros, S.A. de C.V."},
{"key": "637", "name": "ORDER", "razon_social": "Order Express Casa de Cambio, S.A. de C.V"},
{"key": "638", "name": "AKALA", "razon_social": "Akala, S.A. de C.V., Sociedad Financiera Popular"},
{"key": "640", "name": "CB JPMORGAN", "razon_social": "J.P. Morgan Casa de Bolsa, S.A. de C.V. J.P. Morgan Grupo Financiero"},
{"key": "642", "name": "REFORMA", "razon_social": "Operadora de Recursos Reforma, S.A. de C.V., S.F.P."},
{"key": "646", "name": "STP", "razon_social": "Sistema de Transferencias y Pagos STP, S.A. de C.V.SOFOM ENR"},
{"key": "647", "name": "TELECOMM", "razon_social": "Telecomunicaciones de México"},
{"key": "648", "name": "EVERCORE", "razon_social": "Evercore Casa de Bolsa, S.A. de C.V."},
{"key": "649", "name": "SKANDIA", "razon_social": "Skandia Operadora de Fondos, S.A. de C.V."},
{"key": "651", "name": "SEGMTY", "razon_social": "Seguros Monterrey New York Life, S.A de C.V"},
{"key": "652", "name": "ASEA", "razon_social": "Solución Asea, S.A. de C.V., Sociedad Financiera Popular"},
{"key": "653", "name": "KUSPIT", "razon_social": "Kuspit Casa de Bolsa, S.A. de C.V."},
{"key": "655", "name": "SOFIEXPRESS", "razon_social": "J.P. SOFIEXPRESS, S.A. de C.V., S.F.P."},
{"key": "656", "name": "UNAGRA", "razon_social": "UNAGRA, S.A. de C.V., S.F.P."},
{"key": "659", "name": "OPCIONES EMPRESARIALES DEL NOROESTE", "razon_social": "OPCIONES EMPRESARIALES DEL NORESTE, S.A. DE C.V., S.F.P."},
{"key": "670", "name": "LIBERTAD", "razon_social": "Libertad Servicios Financieros, S.A. De C.V."},
{"key": "901", "name": "CLS", "razon_social": "Cls Bank International"},
{"key": "902", "name": "INDEVAL", "razon_social": "SD. Indeval, S.A. de C.V."},
{"key": "999", "name": "N/A"}
]
},
{
"tabla": "SATUsoCfdi",
"datos": [

View File

@ -21,11 +21,15 @@ var controllers = {
$$('cmd_probar_correo').attachEvent('onItemClick', cmd_probar_correo_click)
$$('cmd_guardar_correo').attachEvent('onItemClick', cmd_guardar_correo_click)
$$('emisor_logo').attachEvent('onItemClick', emisor_logo_click)
$$('cmd_emisor_agregar_cuenta').attachEvent('onItemClick', cmd_emisor_agregar_cuenta_click)
$$('emisor_cuenta_saldo_inicial').attachEvent('onChange', emisor_cuenta_saldo_inicial_change)
//~ SAT
tb_sat = $$('tab_sat').getTabbar()
tb_sat.attachEvent('onChange', tab_sat_change)
$$('grid_admin_taxes').attachEvent('onCheck', grid_admin_taxes_on_check)
$$('grid_admin_monedas').attachEvent('onCheck', grid_admin_monedas_on_check)
$$('grid_admin_bancos').attachEvent('onCheck', grid_admin_bancos_on_check)
$$('grid_admin_unidades').attachEvent('onCheck', grid_admin_unidades_on_check)
//~ Opciones
tb_options = $$('tab_options').getTabbar()
tb_options.attachEvent('onChange', tab_options_change)
@ -177,6 +181,38 @@ function get_certificado(){
}
function get_cuentas_banco(){
webix.ajax().get('/values/monedasid', function(text, data){
var values = data.json()
pre = values[0]
$$('lst_emisor_cuenta_moneda').getList().parse(values)
$$('lst_emisor_cuenta_moneda').setValue(pre.id)
})
webix.ajax().get('/values/bancosid', function(text, data){
var values = data.json()
pre = values[0]
$$('lst_emisor_banco').getList().parse(values)
if(values.length == 1){
$$('lst_emisor_banco').setValue(pre.id)
}
})
webix.ajax().get('/values/emisorcuentasbanco', {}, {
error: function(text, data, xhr) {
msg = 'Error al consultar'
msg_error(msg)
},
success: function(text, data, xhr) {
var values = data.json()
$$('grid_emisor_cuentas_banco').parse(values)
}
})
}
function get_table_folios(){
webix.ajax().get("/folios", {}, {
error: function(text, data, xhr) {
@ -217,6 +253,7 @@ function get_admin_impuestos(){
})
}
function get_admin_monedas(){
webix.ajax().sync().get('/values/allcurrencies', function(text, data){
var values = data.json()
@ -226,6 +263,24 @@ function get_admin_monedas(){
}
function get_admin_bancos(){
webix.ajax().sync().get('/values/allbancos', function(text, data){
var values = data.json()
$$('grid_admin_bancos').clearAll()
$$('grid_admin_bancos').parse(values, 'json')
})
}
function get_admin_unidades(){
webix.ajax().sync().get('/values/allunidades', function(text, data){
var values = data.json()
$$('grid_admin_unidades').clearAll()
$$('grid_admin_unidades').parse(values, 'json')
})
}
function get_config_values(opt){
if(opt == undefined){
return
@ -252,6 +307,7 @@ function multi_admin_change(prevID, nextID){
$$('tab_emisor').setValue('Datos Fiscales')
get_emisor()
get_certificado()
get_cuentas_banco()
return
}
@ -754,10 +810,12 @@ function tab_options_change(nv, ov){
function tab_sat_change(nv, ov){
//~ show(nv)
if(nv = 'Monedas'){
if(nv == 'Monedas'){
get_admin_monedas()
return
}else if(nv == 'Bancos'){
get_admin_bancos()
}else if(nv == 'Unidades'){
get_admin_unidades()
}
}
@ -792,3 +850,136 @@ function grid_admin_monedas_on_check(row, column, state){
}
})
}
function grid_admin_bancos_on_check(row, column, state){
var values = {
id: row,
field: column,
value: state,
}
webix.ajax().get('/values/bancoupdate', values, {
error: function(text, data, xhr) {
},
success: function(text, data, xhr) {
}
})
}
function grid_admin_unidades_on_check(row, column, state){
var values = {
id: row,
field: column,
value: state,
}
webix.ajax().get('/values/unidadupdate', values, {
error: function(text, data, xhr) {
},
success: function(text, data, xhr) {
}
})
}
function emisor_cuenta_saldo_inicial_change(new_value, old_value){
if(!isFinite(new_value)){
this.config.value = old_value
this.refresh()
}
}
function cmd_emisor_agregar_cuenta_click(){
var form = $$('form_emisor_cuenta_banco')
if (!form.validate()){
msg = 'Valores inválidos'
msg_error(msg)
return
}
var values = form.getValues()
var si = parseFloat(values.emisor_cuenta_saldo_inicial.replace('$', '').replace(',', ''))
var cuenta = {
de_emisor: true,
activa: true,
nombre: values.emisor_cuenta_nombre.trim(),
banco: values.emisor_banco,
fecha_apertura: values.emisor_cuenta_fecha,
cuenta: values.emisor_cuenta.trim(),
clabe: values.emisor_clabe.trim(),
moneda: values.emisor_cuenta_moneda,
saldo_inicial: si
}
if(!cuenta.nombre){
msg = 'El nombre de la cuenta es requerido'
msg_error(msg)
return
}
if(!cuenta.cuenta){
msg = 'La cuenta es requerida'
msg_error(msg)
return
}
if(!cuenta.cuenta.is_number()){
msg = 'Solo digitos en la cuenta'
msg_error(msg)
return
}
if(cuenta.cuenta.length < 9){
msg = 'Longitud incorrecta de la cuenta'
msg_error(msg)
return
}
if(!cuenta.clabe){
msg = 'La CLABE es requerida'
msg_error(msg)
return
}
if(cuenta.clabe.length != 18){
msg = 'La CLABE debe ser de 18 digitos'
msg_error(msg)
return
}
if(!cuenta.clabe.is_number()){
msg = 'Solo digitos en la CLABE'
msg_error(msg)
return
}
//~ if(!isFinite(cuenta.saldo_inicial)){
if(cuenta.saldo_inicial <= 0){
msg = 'El saldo inicial no puede ser negativo o cero'
msg_error(msg)
return
}
cuenta.saldo = cuenta.saldo_inicial
webix.ajax().post('/cuentasbanco', cuenta, {
error:function(text, data, XmlHttpRequest){
msg = 'Ocurrio un error, consulta a soporte técnico'
msg_error(msg)
},
success:function(text, data, XmlHttpRequest){
var values = data.json()
if(values.ok){
$$('grid_emisor_cuentas_banco').add(values.row)
}else{
msg_error(values.msg)
}
}
})
}

View File

@ -3,6 +3,7 @@ var grid = null
var msg = ''
var result = false
var tipo_relacion = ''
var anticipo = false
function get_condicion_pago(){
@ -244,6 +245,29 @@ function validate_invoice(values){
return false
}
anticipo = $$('chk_cfdi_anticipo').getValue()
if(anticipo){
var mp = $$('lst_metodo_pago').getValue()
if(mp != 'PUE'){
msg = 'En anticipos, el método de pago debe ser: Pago en una sola exhibición'
msg_error(msg)
return false
}
if(grid.count() != 1){
msg = 'Los anticipos solo llevan un concepto'
msg_error(msg)
return false
}
query = table_relaciones.chain().data()
if(query.length > 0){
msg = 'Los anticipos no deben llevar CFDI relacionados'
msg_error(msg)
return false
}
}
return true
}
@ -256,12 +280,54 @@ function update_grid_invoices(values){
}
}
function send_anticipo_egreso(id){
webix.ajax().get('/values/anticipoegreso', {id: id}, function(text, data){
var values = data.json()
if(values.ok){
msg_sucess(values.msg)
gi.add(values.row)
}else{
webix.alert({
title: 'Error al Timbrar',
text: values.msg,
type: 'alert-error'
})
}
})
}
function generar_anticipo_egreso(id){
msg = 'La factura tiene un CFDI de anticipo relacionado<BR><BR>'
msg += '¿Deseas generar la factura de egreso correspondiente?'
webix.confirm({
title: 'Generar Egreso',
ok: 'Si',
cancel: 'No',
type: 'confirm-error',
text: msg,
callback:function(result){
if(result){
send_anticipo_egreso(id)
}
}
})
}
function send_timbrar(id){
webix.ajax().get('/values/timbrar', {id: id}, function(text, data){
var values = data.json()
if(values.ok){
msg_sucess(values.msg)
gi.updateItem(id, values.row)
if(values.anticipo){
//~ generar_anticipo_egreso(id)
//~ show('Generar egreso de anticipo')
}
}else{
webix.alert({
title: 'Error al Timbrar',
@ -356,6 +422,7 @@ function guardar_y_timbrar(values){
delete rows[i]['unidad']
delete rows[i]['importe']
rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario'])
rows[i]['descuento'] = parseFloat(rows[i]['descuento'])
}
var data = new Object()
@ -373,6 +440,7 @@ function guardar_y_timbrar(values){
data['regimen_fiscal'] = $$('lst_regimen_fiscal').getValue()
data['relacionados'] = ids
data['tipo_relacion'] = tipo_relacion
data['anticipo'] = anticipo
if(!save_invoice(data)){
return
@ -380,6 +448,9 @@ function guardar_y_timbrar(values){
table_relaciones.clear()
tipo_relacion = ''
anticipo = false
$$('chk_cfdi_anticipo').setValue(0)
$$('form_invoice').setValues({id_partner: 0, lbl_partner: 'Ninguno'})
$$('multi_invoices').setValue('invoices_home')
@ -404,6 +475,9 @@ function cmd_timbrar_click(id, e, node){
if(query.length > 0){
msg += 'La factura tiene CFDI relacionados<BR><BR>'
}
if(anticipo){
msg += 'La factura es Anticipo<BR><BR>'
}
msg += '¿Estás seguro de timbrar esta factura?'
webix.confirm({
@ -614,7 +688,7 @@ function search_product_id_key_press(code, e){
function grid_details_before_edit_start(id){
var columns = ['', 'descripcion', 'cantidad', 'valor_unitario']
var columns = ['', 'descripcion', 'cantidad', 'valor_unitario', 'descuento']
if(!columns.indexOf(id.column)){
return !this.getItem(id.row)[id.column]
}
@ -649,7 +723,8 @@ function grid_details_before_edit_stop(state, editor){
grid.unblockEvent()
return true
}
var valor_unitario = row['valor_unitario']
var valor_unitario = parseFloat(row['valor_unitario'])
var descuento = parseFloat(row['descuento'])
}
if(editor.column == 'valor_unitario'){
@ -663,10 +738,28 @@ function grid_details_before_edit_stop(state, editor){
grid.unblockEvent()
return true
}
var cantidad = row['cantidad']
var cantidad = parseFloat(row['cantidad'])
var descuento = parseFloat(row['descuento'])
}
row['importe'] = (cantidad * valor_unitario).round(DECIMALES)
if(editor.column == 'descuento'){
var descuento = parseFloat(state.value)
if(isNaN(descuento)){
msg = 'El descuento debe ser un número'
webix.message({type:'error', text: msg})
grid.blockEvent()
state.value = state.old
grid.editCancel()
grid.unblockEvent()
return true
}
var cantidad = parseFloat(row['cantidad'])
var valor_unitario = parseFloat(row['valor_unitario'])
}
var precio_final = valor_unitario - descuento
row['importe'] = (cantidad * precio_final).round(DECIMALES)
grid.refresh()
calculate_taxes()
}
@ -952,6 +1045,7 @@ function cmd_prefactura_click(){
delete rows[i]['unidad']
delete rows[i]['importe']
rows[i]['valor_unitario'] = parseFloat(rows[i]['valor_unitario'])
rows[i]['descuento'] = parseFloat(rows[i]['descuento'])
}
var data = new Object()
@ -1201,6 +1295,7 @@ function get_facturas_por_cliente(){
'month': m,
'id_cliente': id,
'cfdis': ids,
'anticipo': $$('chk_relacionados_anticipo').getValue(),
'folio': $$('filter_cfdi_folio').getValue(),
'uuid': $$('filter_cfdi_uuid').getValue(),
'opt': 'relacionados'
@ -1321,5 +1416,27 @@ function filter_cfdi_month_change(nv, ov){
}
function lst_tipo_relacion_change(nv, ov){
$$('chk_relacionados_anticipo').setValue(0)
$$('chk_relacionados_anticipo').disable()
if(nv=='07'){
$$('chk_relacionados_anticipo').enable()
$$('chk_relacionados_anticipo').setValue(1)
cmd_filter_relacionados_click()
}
}
function lst_serie_change(nv, ov){
query = table_series.chain().find({id: nv}).data()[0]
if(query.usarcon){
$$('lst_tipo_comprobante').setValue(query.usarcon)
$$('lst_tipo_comprobante').config.readonly = true
}else{
$$('lst_tipo_comprobante').setValue('I')
$$('lst_tipo_comprobante').config.readonly = false
}
$$('lst_tipo_comprobante').refresh()
}

View File

@ -54,6 +54,7 @@ var controllers = {
$$('cmd_prefactura').attachEvent('onItemClick', cmd_prefactura_click)
$$('cmd_cfdi_relacionados').attachEvent('onItemClick', cmd_cfdi_relacionados_click)
$$('lst_metodo_pago').attachEvent('onChange', lst_metodo_pago_change)
$$('lst_serie').attachEvent('onChange', lst_serie_change)
var tb_invoice = $$('tv_invoice').getTabbar()
tb_invoice.attachEvent('onChange', tb_invoice_change)
@ -66,8 +67,8 @@ var controllers = {
}
function get_uso_cfdi_to_table(args){
webix.ajax().sync().get('/values/usocfdi', args, function(text, data){
function get_uso_cfdi_to_table(){
webix.ajax().sync().get('/values/usocfdi', function(text, data){
var values = data.json()
table_usocfdi.clear()
table_usocfdi.insert(values)

View File

@ -22,7 +22,7 @@ function cmd_new_partner_click(id, e, node){
$$('multi_partners').setValue('partners_new')
$$('tab_partner').setValue('Datos Fiscales')
get_uso_cfdi_to_table({})
get_uso_cfdi_to_table()
query = table_usocfdi.chain().find({fisica: true}).data()
$$('lst_uso_cfdi_socio').getList().parse(query)
}
@ -54,7 +54,7 @@ function cmd_edit_partner_click(id, e, node){
$$('form_partner').setValues(values)
$$('forma_pago').getList().load('/values/formapago')
get_uso_cfdi_to_table({})
get_uso_cfdi_to_table()
if(values.tipo_persona == 1){
query = table_usocfdi.chain().find({fisica: true}).data()
}else if(values.tipo_persona == 2){
@ -339,6 +339,6 @@ function rfc_lost_focus(prev_view){
function multi_partners_change(prevID, nextID){
webix.message(prevID)
webix.message(nextID)
//~ webix.message(prevID)
//~ webix.message(nextID)
}

View File

@ -35,6 +35,11 @@ Number.prototype.round = function(decimals){
}
String.prototype.is_number = function(){
return /^\d+$/.test(this)
}
webix.protoUI({
$cssName: "text",
name: "currency",

View File

@ -132,6 +132,78 @@ var emisor_certificado = [
]
var grid_emisor_cuentas_banco_cols = [
{id: 'id', header: 'ID', hidden: true},
{id: 'activa', header: 'Activa', template: '{common.checkbox()}',
editor: 'checkbox', width: 50},
{id: 'nombre', header: 'Nombre', fillspace: 1},
{id: 'banco', header: 'Banco', fillspace: 1},
{id: 'fecha_apertura', header: 'Fecha de Apertura', fillspace: 1},
{id: 'cuenta', header: 'Cuenta', fillspace: 1},
{id: 'clabe', header: 'CLABE', fillspace: 1},
{id: 'moneda', header: 'Moneda', fillspace: 1},
{id: 'saldo', header: 'Saldo', width: 150, format: webix.i18n.priceFormat,
css: 'right'},
]
var grid_emisor_cuentas_banco = {
view: 'datatable',
id: 'grid_emisor_cuentas_banco',
select: 'row',
adjust: true,
autoheight: true,
headermenu: true,
columns: grid_emisor_cuentas_banco_cols
}
var emisor_cuentas_banco = [
{template: 'Agregar cuenta de banco', type: 'section'},
{view: 'form', id: 'form_emisor_cuenta_banco', rows: [
{cols: [
{view: 'text', id: 'emisor_cuenta_nombre', name: 'emisor_cuenta_nombre',
label: 'Nombre: ', required: true}, {}]},
{cols: [
{view: 'richselect', id: 'lst_emisor_banco', name: 'emisor_banco',
label: 'Banco: ', required: true, options: []},
{view: 'datepicker', id: 'emisor_cuenta_fecha', format: '%d-%M-%Y',
name: 'emisor_cuenta_fecha', label: 'Fecha de apertura: ',
required: true},
]},
{cols: [
{view: 'text', id: 'emisor_cuenta', name: 'emisor_cuenta',
label: 'Cuenta: ', required: true},
{view: 'text', id: 'emisor_clabe', name: 'emisor_clabe',
label: 'CLABE: ', required: true},
]},
{cols: [
{view: 'richselect', id: 'lst_emisor_cuenta_moneda',
name: 'emisor_cuenta_moneda', label: 'Moneda: ', required: true,
options: []},
{view: 'currency', type: 'text', id: 'emisor_cuenta_saldo_inicial',
name: 'emisor_cuenta_saldo_inicial', label: 'Saldo inicial',
required: true, invalidMessage: 'Captura un valor númerico',
inputAlign: 'right', value: ''},
]},
{minHeight: 10},
{cols: [{}, {view: 'button', id: 'cmd_emisor_agregar_cuenta',
label: 'Agregar cuenta'}, {}]},
],
rules: {
emisor_cuenta_saldo_inicial: function(value){return value.trim() != "$";},
}
},
{minHeight: 20},
{template: 'Cuentas de banco existentes', type: 'section'},
grid_emisor_cuentas_banco,
{minHeight: 50},
]
var controls_emisor = [
{
view: 'tabview',
@ -139,13 +211,14 @@ var controls_emisor = [
tabbar: {options: [
'Datos Fiscales',
'Otros Datos',
'Certificado']},
'Certificado',
'Cuentas de Banco']},
animate: true,
cells: [
{id: 'Datos Fiscales', rows: emisor_datos_fiscales},
{id: 'Otros Datos', rows: emisor_otros_datos},
{id: 'Certificado', rows: emisor_certificado},
{},
{id: 'Cuentas de Banco', rows: emisor_cuentas_banco}
]
}
]
@ -388,6 +461,26 @@ var grid_admin_monedas_cols = [
]
var grid_admin_bancos_cols = [
{id: 'id', header: 'ID', hidden: true},
{id: 'key', header: 'Clave', footer: {content: 'rowCount', css: 'right'}},
{id: 'name', header: 'Nombre', adjust: 'data', footer: 'Bancos'},
{id: 'activo', header: 'Activo', template: '{common.checkbox()}',
editor: 'checkbox'},
]
var grid_admin_unidades_cols = [
{id: 'id', header: 'ID', hidden: true},
{id: 'key', header: 'Clave'},
{id: 'name', header: 'Nombre', adjust: 'data'},
{id: 'activo', header: 'Activa', template: '{common.checkbox()}',
editor: 'checkbox'},
{id: 'default', header: 'Predeterminada', template: '{common.radio()}',
adjust: 'header'},
]
var grid_admin_taxes = {
view: 'datatable',
id: 'grid_admin_taxes',
@ -414,6 +507,33 @@ var grid_admin_monedas = {
}
var grid_admin_bancos = {
view: 'datatable',
id: 'grid_admin_bancos',
select: 'cell',
multiselect: true,
adjust: true,
autowidth: true,
headermenu: true,
footer: true,
columns: grid_admin_bancos_cols
}
var grid_admin_unidades = {
view: 'datatable',
id: 'grid_admin_unidades',
select: 'cell',
multiselect: true,
adjust: true,
autowidth: true,
autoheight: true,
headermenu: true,
footer: true,
columns: grid_admin_unidades_cols
}
var msg_tax = 'Activa los impuestos que uses. El predeterminado se muestra primero'
var sat_impuestos = [
{maxHeight: 20},
@ -422,6 +542,7 @@ var sat_impuestos = [
{cols: [{maxWidth: 15}, grid_admin_taxes, {}]},
{}]
var msg_moneda = 'Activa las monedas que uses. La predeterminada se muestra primero'
var sat_monedas = [
{maxHeight: 20},
@ -431,6 +552,26 @@ var sat_monedas = [
{}]
var msg_bancos = 'Activar los bancos necesarios'
var sat_bancos = [
{maxHeight: 20},
{cols: [{maxWidth: 15}, {view: 'label', label: msg_bancos}, {}]},
{maxHeight: 20},
{cols: [{maxWidth: 15}, grid_admin_bancos, {}]},
{maxHeight: 20},
]
var msg_unidades = 'Activar las unidades necesarias'
var sat_unidades = [
{maxHeight: 20},
{cols: [{maxWidth: 15}, {view: 'label', label: msg_unidades}, {}]},
{maxHeight: 20},
{cols: [{maxWidth: 15}, grid_admin_unidades, {}]},
{},
]
var tab_sat = {
view: 'tabview',
id: 'tab_sat',
@ -438,13 +579,15 @@ var tab_sat = {
tabbar: {options: [
'Impuestos',
'Monedas',
'Unidades']},
'Bancos',
'Unidades'
]},
animate: true,
cells: [
{id: 'Impuestos', rows: sat_impuestos},
{id: 'Monedas', rows: sat_monedas},
{id: 'Unidades', rows: [{}]},
{},
{id: 'Bancos', rows: sat_bancos},
{id: 'Unidades', rows: sat_unidades},
]
}
@ -545,7 +688,6 @@ var ui_admin = {
{view: 'toolbar', padding: 3, elements: [
{view: 'button', type: 'icon', icon: 'bars',
width: 37, align: 'left', css: 'app_button', click: function(){
//~ $$('$sidebar1').toggle()
$$('sidebar_admin').toggle()
}
},

View File

@ -97,8 +97,11 @@ var body_cfdi_relacionados = {rows: [
{view: 'label', id: 'lbl_cfdi_title', label: 'Cliente: ',
autowidth: true},
{view: 'label', id: 'lbl_cfdi_cliente', label: '', align: 'left'}]},
{view: 'richselect', id: 'lst_tipo_relacion', label: 'Tipo de Relación',
labelWidth: 150, required: true, options: []},
{cols: [
{view: 'richselect', id: 'lst_tipo_relacion', label: 'Tipo de Relación',
labelWidth: 140, required: true, options: []},
{view: 'checkbox', id: 'chk_relacionados_anticipo',
labelRight: 'Solo Anticipos', width: 200, disabled: true}]},
{minHeight: 10, maxHeight: 10},
{cols: [
{view: 'richselect', id: 'filter_cfdi_year', label: 'Año', width: 100,
@ -145,7 +148,8 @@ var ui_invoice = {
$$('cmd_guardar_relacionados').attachEvent('onItemClick', cmd_guardar_relacionados_click)
$$('cmd_limpiar_relacionados').attachEvent('onItemClick', cmd_limpiar_relacionados_click)
$$('cmd_filter_relacionados').attachEvent('onItemClick', cmd_filter_relacionados_click)
$$('filter_cfdi_year').attachEvent('onChange', filter_cfdi_year_change)
$$('lst_tipo_relacion').attachEvent('onChange', lst_tipo_relacion_change)
$$('filter_cfdi_month').attachEvent('onChange', filter_cfdi_month_change)
$$('filter_cfdi_month').attachEvent('onChange', filter_cfdi_month_change)
}}
@ -175,6 +179,7 @@ var toolbar_invoices_util = [
var toolbar_invoices_generate = {view: 'toolbar', elements: [{},
{view: 'button', id: 'cmd_cfdi_relacionados', label: 'CFDI Relacionados',
type: 'iconButton', autowidth: true, icon: 'file-o'},
{view: 'checkbox', id: 'chk_cfdi_anticipo', label: 'Es Anticipo', width: 100},
]}
@ -249,9 +254,14 @@ var grid_details_cols = [
{id: "unidad", header:{text: 'Unidad', css: 'center'}, width: 100},
{id: 'cantidad', header: {text: 'Cantidad', css: 'center'}, width: 100,
format: webix.i18n.numberFormat, css:'right', editor: 'text'},
{id: "valor_unitario", header:{text: 'Valor Unitario', css: 'center'}, width: 100,
format: webix.i18n.priceFormat, css:'right', editor: 'text'},
{id: "importe", header:{text: 'Importe', css: 'center'}, width: 150, format: webix.i18n.priceFormat, css:'right'},
{id: "valor_unitario", header:{text: 'Valor Unitario', css: 'center'},
width: 100, format: webix.i18n.priceFormat, css:'right', editor: 'text'},
{id: 'descuento', header:{text: 'Descuento', css: 'center'},
width: 80, format: webix.i18n.priceFormat, css:'right', editor: 'text'},
{id: 'precio_final', hidden: true, header: 'precio_final', width: 80,
format: webix.i18n.priceFormat, css:'right'},
{id: "importe", header:{text: 'Importe', css: 'center'}, width: 150,
format: webix.i18n.priceFormat, css:'right'},
]

View File

@ -18,6 +18,8 @@ var grid_partners_cols = [
sort: 'string', footer: {text: 'Clientes y Proveedores', colspan: 2}},
{id: 'nombre', header: ['Razón Social', {content: 'textFilter'}],
fillspace:true, sort: 'string'},
{id: 'saldo_cliente', header: ['Saldo Cliente', {content: 'numberFilter'}],
width: 150, sort: 'int', format: webix.i18n.priceFormat, css: 'right'},
]