diff --git a/CHANGELOG.md b/CHANGELOG.md index 108a56d..84ca76b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,17 @@ +v 1.21.0 [12-oct-2018] +---------------------- + - Error #287 + - Mejora: Complemento de pago con datos de cuentas + +* IMPORTANTE: Es necesario realizar una migración, despues de actualizar. + + v 1.20.0 [08-oct-2018] ---------------------- - Error #295 - Mejora: Cuentas de banco para clientes -* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal. +* IMPORTANTE: Es necesario realizar una migración, despues de actualizar. v 1.19.1 [03-oct-2018] diff --git a/VERSION b/VERSION index 3989355..3500250 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.20.0 +1.21.0 diff --git a/docs/empresalibre/docs/administracion.md b/docs/empresalibre/docs/administracion.md index e49eadc..21cea3f 100644 --- a/docs/empresalibre/docs/administracion.md +++ b/docs/empresalibre/docs/administracion.md @@ -19,6 +19,20 @@ a usar, esto se hace en ***Catalogos SAT***, pestaña ***Bancos***. Por default veras primero los bancos ya seleccionados. Marca la casilla de verificación de cada banco que deses tener disponible al agregar las cuentas bancarias. Usa la barra de desplazamiento de la tabla o la rueda de tu ratón para ver más bancos. +Cada banco que selecciones, también estará disponible en la sección ***Clientes +y Proveedores***. + +
+
TIP: + Si vas a agregar los datos bancarios en las ***Facturas de pago***, es + necesario capturar el RFC de cada banco seleccionado. +
+ +
+Para editar el RFC, solo da clic en la celda correspondiente y captura +correctamente el RFC del banco, para guardar presionas ***Enter***. El sistema +solo válida que sea un RFC válido, por lo que **asegurate de que sea el RFC +correcto para cada banco**. ![Seleccionar bancos](img/02/admin_002.png) diff --git a/docs/empresalibre/docs/bancos.md b/docs/empresalibre/docs/bancos.md index 2b9e78e..848b996 100644 --- a/docs/empresalibre/docs/bancos.md +++ b/docs/empresalibre/docs/bancos.md @@ -175,8 +175,11 @@ elimina un movimiento, no importa si es retiro o depósito, el saldo de la cuent se actualiza a partir de la fecha del movimiento eliminado y hasta el más reciente. -* Si es un depósito y tiene facturas relacionadas, las mismas estarán de nuevo marcadas como **Por pagar** y disponibles para relacionarse con otro depósito. -* **No podrás eliminar** un depósito si este ya tiene generada una Factura de Pago. **Siempre, asegurate de que todo este correcto antes de generar una Factura de Pago**. +* Si es un depósito y tiene facturas relacionadas, las mismas estarán de nuevo +marcadas como **Por pagar** y disponibles para relacionarse con otro depósito. +* Puedes eliminar un depósito aún si este tiene generada una Factura de Pago. La +misma quedará ***huerfana***, pero disponible desde el listado de Facturas de +Pago elaboradas. ![Cancelar movimiento](img/03/bancos_017.png) @@ -185,8 +188,8 @@ reciente. ### Generar Factura de Pago Para usar esta herramienta, debe estar activado el uso del [complemento de pago][2] -dentro de administración. Si no ves en ***Bancos*** el botón de comando ***Factura -de Pago***, solicita a un administrador que lo active. +dentro de administración. Si no ves en ***Bancos*** el botón de comando ***Generar +Factura de Pago***, solicita a un administrador que lo active. ![Factura de pago](img/03/bancos_018.png) @@ -198,8 +201,9 @@ de Pago***, solicita a un administrador que lo active.
-* Solo puedes generar ***Facturas de pago*** de movimientos de depósito que tengan facturas relacionadas. -* Selecciona el depósito correcto y presiona el botón de comando ***Factura de Pago***. +* Solo puedes generar ***Facturas de pago*** de movimientos de depósito que tengan +facturas relacionadas. +* Selecciona el depósito correcto y presiona el botón de comando ***Generar Factura de Pago***. En la siguiente pantalla, **verifica una vez más que todos los datos con correctos**. En este momento puedes cerrar e incluso cancelar el movimiento para hacer cualquier @@ -221,7 +225,7 @@ de Pago***. ![Factura de pago](img/03/bancos_021.png) -Con un clic en el icono ***PDF***, puedes generarl el PDF respectivo de esta +Con un clic en el icono ***PDF***, puedes generar el PDF respectivo de esta ***Factura de Pago***. Como con las plantillas de las facturas, puedes personalizar completamente esta plantilla. @@ -243,9 +247,14 @@ documento. Los siguientes pasos **son importantes y en este orden**, los campos que debes de modificar en la tabla ***Facturas a pagar en este depósito*** son: -* **Este pago**: Si el valor pagado es el total de la factura, no lo modifiques, si es parcial, captura el valor pagado **en la moneda del documento**, en este ejemplo, en UDS. Este valor se usa para el estado de cuenta de la factura. -* **Este Pago MXM**: Captura el valor pagado en moneda nacional de este documento. En este ejemplo, sería el valor **real** del depósito. Este valor se usará para la ***Factura de pago***, para el estado de cuenta y para el saldo del cliente. -* **T.C.**: Al capturar correctamente los dos valores anteriores, el sistema te calculará el tipo de cambio (***T.C***) usado, si no es correcto, puedes editarlo libremente. Este valor se usa para la ***Factura de pago***. +* **Este pago**: Si el valor pagado es el total de la factura, no lo modifiques, +si es parcial, captura el valor pagado **en la moneda del documento**, en este +ejemplo, en UDS. Este valor se usa para el estado de cuenta de la factura. +* **Este Pago MXM**: Captura el valor pagado en moneda nacional de este documento. +En este ejemplo, sería el valor **real** del depósito. Este valor se usará para +la ***Factura de pago***, para el estado de cuenta y para el saldo del cliente. +* **T.C.**: Al capturar correctamente los dos valores anteriores, el sistema te +calculará el tipo de cambio (***T.C***) usado. Este valor se usa para la ***Factura de pago***. Ahora, nuestros datos deben verse así: diff --git a/docs/empresalibre/docs/img/02/admin_002.png b/docs/empresalibre/docs/img/02/admin_002.png index 82740d5..60cb1ef 100644 Binary files a/docs/empresalibre/docs/img/02/admin_002.png and b/docs/empresalibre/docs/img/02/admin_002.png differ diff --git a/docs/empresalibre/docs/img/03/bancos_018.png b/docs/empresalibre/docs/img/03/bancos_018.png index 439aa34..4404aa4 100644 Binary files a/docs/empresalibre/docs/img/03/bancos_018.png and b/docs/empresalibre/docs/img/03/bancos_018.png differ diff --git a/docs/empresalibre/docs/index.md b/docs/empresalibre/docs/index.md index f09a9b9..55a89f1 100644 --- a/docs/empresalibre/docs/index.md +++ b/docs/empresalibre/docs/index.md @@ -13,11 +13,12 @@ existe una relación humana. diseñado para la legislación mexicana. **Empresa Libre** es totalmente [software libre][1]. -### Índice +### Contenido 1. [Instalación y configuración](instalacion.md) 1. [Administración del sistema](administracion.md) 1. [Guía de usuario](guiadeusuario.md) + 1. [Bancos](bancos.md) 1. [Preguntas más frecuentes](preguntas.md) diff --git a/docs/empresalibre/docs/instalacion.md b/docs/empresalibre/docs/instalacion.md index d825091..9e519ab 100644 --- a/docs/empresalibre/docs/instalacion.md +++ b/docs/empresalibre/docs/instalacion.md @@ -24,6 +24,12 @@ la brevedad. ![Versión del sistema](img/01/install_001.png) +
+
TIP: + Para todas las instrucciones siguientes, se asume que son para nuestra + maquina virtual (MV), las rutas pueden cambiar si has personalizado tu + propia MV o estas ejecutando Empresa Libre en un servidor propio. +

Ya dentro del sistema, el proceso para actualizar es: diff --git a/docs/empresalibre/docs/notas.md b/docs/empresalibre/docs/notas.md index a16e9e0..36a8f00 100644 --- a/docs/empresalibre/docs/notas.md +++ b/docs/empresalibre/docs/notas.md @@ -6,11 +6,18 @@ siempre actualizado.** Solo se da soporte sobre la ultima versión de **Empresa Libre**. +### 1.21.0 [12-oct-2018] +- Error [#287](https://gitlab.com/mauriciobaeza/empresa-libre/issues/287) +- Mejora: Complemento de pago con datos de cuentas + +* IMPORTANTE: Es necesario realizar una migración, despues de actualizar. + + ### 1.20.0 [08-oct-2018] - Error [#295](https://gitlab.com/mauriciobaeza/empresa-libre/issues/295) - Mejora - Cuentas de banco para clientes -* IMPORTANTE: Es necesario realizar una migración, despues de actualizar la rama principal. +* IMPORTANTE: Es necesario realizar una migración, despues de actualizar. ### 1.19.1 [03-oct-2018] diff --git a/docs/empresalibre/docs/preguntas.md b/docs/empresalibre/docs/preguntas.md index 93c1321..e24507f 100644 --- a/docs/empresalibre/docs/preguntas.md +++ b/docs/empresalibre/docs/preguntas.md @@ -40,7 +40,7 @@ Finkok, el mejor PAC de México, puedes [timbrar gratuitamente en su página][2] No, no se incluye ningún tipo de soporte técnico. Dado que **Empresa Libre** es [software libre][1] y se ofrece sin **ningún costo para todos**, el soporte técnico es parte de los ingresos indispensables para poder seguir desarrollando y -manteniendo el sistema. Esto incluye cualquier tontería que se le ocurra al SAT. +manteniendo el sistema. Esto incluye cualquier estulticia que se le ocurra al SAT. Por eso, por favor, **no pidas soporte técnico gratis**. @@ -73,8 +73,18 @@ acceso al sistema de pruebas son: * **Usuario**: admin * **Contraseña**: salgueiro3.3 -Toma en cuenta que este sitio esta en constante actualización, los datos generados -se limpian de forma regular. +Toma en cuenta que este sitio esta en constante actualización y desarrollo, los +datos generados se limpian de forma regular. + + +
+### ¿Dondé descargar los archivos necesarios? + +Todos los archivos necesarios para probar localmente **Empresa Libre** en tu +equipo, los puedes descargar desde nuestra carpeta compartida, donde también +puedes descargar todas las plantillas necesarias para el sistema + +[Carpeta pública de Empresa Libre][7]
@@ -92,3 +102,4 @@ tu pantalla, en la mayoría de los navegadores con la combinación de teclas [4]: https://gitlab.com/mauriciobaeza/empresa-libre/issues [5]: [6]: https://universolibre.org/hacemos/ +[7]: https://doc.elmau.net/d/dbb11c9186684457beb6/ diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 41a169c..353f7ad 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -552,12 +552,28 @@ class AppSATBancos(object): def on_get(self, req, resp): values = req.params - req.context['result'] = self._db.get_satbancos(values) + req.context['result'] = self._db.get_sat_bancos(values) resp.status = falcon.HTTP_200 def on_post(self, req, resp): values = req.params - req.context['result'] = self._db.satbancos(values) + req.context['result'] = self._db.sat_bancos(values) + resp.status = falcon.HTTP_200 + + +class AppSATFormaPago(object): + + def __init__(self, db): + self._db = db + + def on_get(self, req, resp): + values = req.params + req.context['result'] = self._db.get_sat_forma_pago(values) + resp.status = falcon.HTTP_200 + + def on_post(self, req, resp): + values = req.params + req.context['result'] = self._db.sat_forma_pago(values) resp.status = falcon.HTTP_200 diff --git a/source/app/main.py b/source/app/main.py index 66298f2..ec12f0c 100644 --- a/source/app/main.py +++ b/source/app/main.py @@ -17,7 +17,8 @@ from controllers.main import (AppEmpresas, AppMain, AppValues, AppPartners, AppProducts, AppInvoices, AppFolios, AppDocumentos, AppFiles, AppPreInvoices, AppCuentasBanco, AppMovimientosBanco, AppTickets, AppStudents, AppEmployees, AppNomina, - AppInvoicePay, AppCfdiPay, AppSATBancos, AppSociosCuentasBanco + AppInvoicePay, AppCfdiPay, AppSATBancos, AppSociosCuentasBanco, + AppSATFormaPago ) @@ -59,6 +60,7 @@ api.add_route('/nomina', AppNomina(db)) api.add_route('/invoicepay', AppInvoicePay(db)) api.add_route('/cfdipay', AppCfdiPay(db)) api.add_route('/satbancos', AppSATBancos(db)) +api.add_route('/satformapago', AppSATFormaPago(db)) api.add_route('/socioscb', AppSociosCuentasBanco(db)) diff --git a/source/app/models/db.py b/source/app/models/db.py index 45a8108..a3de267 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -436,9 +436,12 @@ class StorageEngine(object): def get_cfdipay(self, values): return main.CfdiPagos.get_values(values) - def get_satbancos(self, values): + def get_sat_bancos(self, values): return main.SATBancos.get_values(values) + def get_sat_forma_pago(self, values): + return main.SATFormaPago.get_values(values) + def get_partners_accounts_bank(self, values): return main.SociosCuentasBanco.get_values(values) @@ -448,8 +451,11 @@ class StorageEngine(object): def bankmovement(self, values): return main.MovimientosBanco.post(values) - def satbancos(self, values): + def sat_bancos(self, values): return main.SATBancos.post(values) + def sat_forma_pago(self, values): + return main.SATFormaPago.post(values) + def partners_accounts_bank(self, values): return main.SociosCuentasBanco.post(values) diff --git a/source/app/models/main.py b/source/app/models/main.py index 7a9153f..7e94bd6 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -45,6 +45,7 @@ FORMAT6 = '{0:.6f}' FORMAT_TAX = FORMAT4 FORMAT_PRECIO = FORMAT4 RFC_PUBLICO = 'XAXX010101000' +RFC_EXTRANJERO = 'XEXX010101000' database_proxy = Proxy() @@ -241,7 +242,8 @@ def config_main(): 'nomina': nomina, 'timbres': 0, 'decimales_precios': DECIMALES, - 'pagos': Configuracion.get_bool('chk_config_pagos') + 'pagos': Configuracion.get_bool('chk_config_pagos'), + 'pays_data_bank': Configuracion.get_bool('chk_cfg_pays_data_bank') } dp = Configuracion.get_bool('chk_config_decimales_precios') if dp: @@ -320,6 +322,28 @@ class Configuracion(BaseModel): values = {r.clave: util.get_bool(r.valor) for r in data} return values + def _get_complements(self): + fields = ( + 'chk_config_ine', + 'chk_config_edu', + 'chk_config_pagos', + 'chk_cfg_pays_data_bank', + ) + data = (Configuracion + .select() + .where(Configuracion.clave.in_(fields)) + ) + values = {r.clave: util.get_bool(r.valor) for r in data} + + fields = ( + 'txt_config_cfdipay_serie', + 'txt_config_cfdipay_folio', + ) + for f in fields: + values[f] = Configuracion.get_(f) + + return values + @classmethod def get_(cls, keys): if isinstance(keys, str): @@ -331,7 +355,7 @@ class Configuracion(BaseModel): return data[0].valor return '' - options = ('partners',) + options = ('partners', 'complements') opt = keys['fields'] if opt in options: return getattr(cls, '_get_{}'.format(opt))(cls) @@ -388,9 +412,6 @@ class Configuracion(BaseModel): 'chk_config_codigo_barras', 'chk_config_precio_con_impuestos', 'chk_llevar_inventario', - 'chk_config_ine', - 'chk_config_edu', - 'chk_config_pagos', 'chk_usar_punto_de_venta', 'chk_ticket_pdf_show', 'chk_ticket_direct_print', @@ -1244,6 +1265,31 @@ class SATFormaPago(BaseModel): def __str__(self): return 'Forma de pago: ({}) {}'.format(self.key, self.name) + @classmethod + def get_values(cls, values): + opt = values.pop('opt') + return getattr(cls, '_get_{}'.format(opt))(cls, values) + + def _get_active_by_id(self, values): + rows = (SATFormaPago + .select( + SATFormaPago.id, + SATFormaPago.name.alias('value')) + .where(SATFormaPago.activo==True) + .dicts() + ) + return tuple(rows) + + def _get_active_by_key(self, values): + rows = (SATFormaPago + .select( + SATFormaPago.key.alias('id'), + SATFormaPago.name.alias('value')) + .where(SATFormaPago.activo==True) + .dicts() + ) + return tuple(rows) + @classmethod def get_(self): rows = SATFormaPago.select().dicts() @@ -1878,218 +1924,6 @@ class CuentasBanco(BaseModel): return data -class MovimientosBanco(BaseModel): - cuenta = ForeignKeyField(CuentasBanco) - fecha = DateTimeField(default=util.now, formats=['%Y-%m-%d %H:%M:%S']) - descripcion = TextField(default='') - forma_pago = ForeignKeyField(SATFormaPago) - retiro = DecimalField(default=0.0, max_digits=20, decimal_places=6, - auto_round=True) - deposito = 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) - cancelado = BooleanField(default=False) - conciliado = BooleanField(default=False) - moneda = TextField(default='MXN') # Complemento de pagos - tipo_cambio = DecimalField(default=1.0, max_digits=15, decimal_places=6, - auto_round=True) - numero_operacion = TextField(default='') - origen_rfc = TextField(default='') - origen_nombre = TextField(default='') - origen_cuenta = TextField(default='') - destino_rfc = TextField(default='') - destino_cuenta = TextField(default='') - tipo_cadena_pago = TextField(default='') - certificado_pago = TextField(default='') - cadena_pago = TextField(default='') - sello_pago = TextField(default='') - - class Meta: - order_by = ('fecha', 'id') - - def _ultimo_saldo(self, cuenta, fecha): - query = (MovimientosBanco - .select() - .where( - (MovimientosBanco.cuenta==cuenta) & - (MovimientosBanco.fecha<=fecha) & - (MovimientosBanco.cancelado==False))[-1] - ) - return round(float(query.saldo), DECIMALES) - - def _movimiento_anterior(self, cuenta, fecha): - query = (MovimientosBanco - .select() - .where( - (MovimientosBanco.cuenta==cuenta) & - (MovimientosBanco.fecharow.fecha) & - (MovimientosBanco.cancelado==False)) - ) - - saldo = round(Decimal(row.saldo), DECIMALES) - for mov in query: - mov.saldo = saldo + mov.deposito - mov.retiro - mov.save() - saldo = mov.saldo - CuentasBanco.actualizar_saldo(row.cuenta, saldo) - return saldo - - @classmethod - def post(cls, values): - opt = values.pop('opt') - return getattr(cls, '_{}'.format(opt))(cls, values) - - def _add(self, values): - ids = values.pop('ids', '') - - if ids and not Facturas.validate_count_partners(util.loads(ids)): - msg = 'Facturas relacionadas a diferentes clientes' - data = {'ok': False, 'msg': msg} - return data - - actualizar = False - if 'saldo' in values: - saldo = values['saldo'] - else: - actualizar = True - hora = values.pop('hora') - account = CuentasBanco.get(CuentasBanco.id==int(values['cuenta'])) - values['fecha'] = '{}T{}'.format(values['fecha'][:10], hora) - values['cuenta'] = account - values['moneda'] = account.moneda.key - values['retiro'] = util.get_float(values['retiro']) - values['deposito'] = util.get_float(values['deposito']) - values['tipo_cambio'] = util.get_float( - values.get('tipo_cambio', 1.00), True) - values['forma_pago'] = int(values['forma_pago']) - - ultimo_saldo = self._ultimo_saldo( - self, values['cuenta'], values['fecha']) - values['saldo'] = \ - ultimo_saldo - values['retiro'] + values['deposito'] - - with database_proxy.transaction(): - try: - obj = MovimientosBanco.create(**values) - except IntegrityError: - msg = 'Este movimiento ya existe' - return {'ok': False, 'msg': msg} - - if actualizar: - saldo = self._actualizar_saldos(self, obj) - if ids: - FacturasPagos.add(obj, util.loads(ids)) - - return {'ok': True, 'saldo': saldo} - - def _cancel(self, values): - id = int(values['id']) - try: - obj = MovimientosBanco.get(MovimientosBanco.id==id) - except MovimientosBanco.DoesNotExist: - msg = 'No se encontró el movimiento' - return {'ok': False, 'msg': msg} - - if obj.cancelado: - msg = 'El movimiento ya esta cancelado' - return {'ok': False, 'msg': msg} - - if obj.conciliado: - msg = 'El movimiento esta conciliado, no se puede cancelar' - return {'ok': False, 'msg': msg} - - # ~ filters = (CfdiPagos.movimiento==obj) - # ~ cp = CfdiPagos.select().where(filters).count() - # ~ if cp > 0: - # ~ msg = 'El movimiento tiene Factura de Pago, no se puede cancelar' - # ~ return {'ok': False, 'msg': msg} - - with database_proxy.transaction(): - obj.cancelado = True - obj.save() - FacturasPagos.cancelar(obj) - - obj = self._movimiento_anterior(self, obj.cuenta, obj.fecha) - self._actualizar_saldos(self, obj) - - balance = CuentasBanco.get_saldo(obj.cuenta.id) - - msg = 'Movimiento cancelado correctamente' - return {'ok': True, 'msg': msg, 'balance': balance} - - @classmethod - def con(cls, id): - cant = (MovimientosBanco - .select(MovimientosBanco.id) - .where(MovimientosBanco.cuenta==id) - .count() - ) - if cant > 2: - return {'ok': True} - - return {'ok': False} - - - @classmethod - def get_(cls, values): - cuenta = int(values['cuenta']) - if 'fechas' in values: - rango = util.loads(values['fechas']) - fd = (MovimientosBanco.fecha.between( - util.get_date(rango['start']), - util.get_date(rango['end'], True))) - filtros = (fd & - (MovimientosBanco.cuenta==cuenta) & - (MovimientosBanco.cancelado==False) - ) - else: - year = int(values['year']) - mes = int(values['mes']) - if year == -1: - fy = (MovimientosBanco.fecha.year > 0) - else: - fy = (MovimientosBanco.fecha.year == year) - if mes == -1: - fm = (MovimientosBanco.fecha.month > 0) - else: - fm = (MovimientosBanco.fecha.month == mes) - filtros = (fy & fm & - (MovimientosBanco.cuenta==cuenta) & - (MovimientosBanco.cancelado==False) - ) - - rows = tuple(MovimientosBanco.select( - MovimientosBanco.id, - MovimientosBanco.fecha, - MovimientosBanco.numero_operacion, - SATFormaPago.name.alias('way_payment'), - MovimientosBanco.descripcion, - MovimientosBanco.retiro, - MovimientosBanco.deposito, - MovimientosBanco.saldo, - fn.COUNT(CfdiPagos.id).alias('invoice') - ) - .join(SATFormaPago).switch(MovimientosBanco) - .join(CfdiPagos, JOIN.LEFT_OUTER).switch(MovimientosBanco) - .where(filtros) - .group_by(MovimientosBanco.id, SATFormaPago.name) - .dicts() - ) - - return {'ok': True, 'rows': rows} - - class SATUsoCfdi(BaseModel): key = TextField(index=True, unique=True) name = TextField(default='', index=True) @@ -2655,6 +2489,7 @@ class Socios(BaseModel): @classmethod def add(cls, values): + accounts = util.loads(values.pop('accounts', '[]')) fields = cls._clean(cls, values) try: obj = Socios.create(**fields) @@ -2665,6 +2500,19 @@ class Socios(BaseModel): #~ ToDo Agregar tags + for account in accounts: + try: + bank = SATBancos.get_by_name(account['banco']) + fields = { + 'socio': obj, + 'banco': bank, + 'cuenta': account['cuenta'], + 'clabe': account['clabe'], + } + o = SociosCuentasBanco.create(**fields) + except IntegrityError: + pass + row = { 'id': obj.id, 'rfc': obj.rfc, @@ -2704,15 +2552,11 @@ class Socios(BaseModel): if count: return False + q = SociosCuentasBanco.delete().where(SociosCuentasBanco.socio==id) + q.execute() q = Socios.delete().where(Socios.id==id) return bool(q.execute()) - # ~ def _reset_saldo(self, id): - # ~ obj = Socios.get(Socios.id==id) - # ~ obj.saldo_cliente = 0.0 - # ~ obj.save() - # ~ return {'ok': True} - @classmethod def opt(cls, args): opt = args.get('opt', '') @@ -2724,6 +2568,7 @@ class Socios(BaseModel): class SociosCuentasBanco(BaseModel): socio = ForeignKeyField(Socios) + activa = BooleanField(default=True) banco = ForeignKeyField(SATBancos) cuenta = TextField(default='') clabe = TextField(default='') @@ -2738,10 +2583,15 @@ class SociosCuentasBanco(BaseModel): def __str__(self): return '{} ({})'.format(self.banco.name, self.cuenta[-4:]) - @classmethod - def get_values(cls, values): - opt = values.pop('opt') - return getattr(cls, '_get_{}'.format(opt))(cls, values) + def _get_by_name(self, values): + name = values['name'] + query = (SociosCuentasBanco + .select() + .where(SociosCuentasBanco.activa==True, Socios.nombre==name) + .join(Socios).switch(SociosCuentasBanco) + ) + rows = tuple([{'id': q.id, 'value': str(q)} for q in query]) + return {'ok': True, 'values': rows} def _get_by_partner(self, values): id = int(values['id_partner']) @@ -2756,6 +2606,11 @@ class SociosCuentasBanco(BaseModel): .dicts()) return tuple(rows) + @classmethod + def get_values(cls, values): + opt = values.pop('opt') + return getattr(cls, '_get_{}'.format(opt))(cls, values) + @classmethod def post(cls, values): opt = values.pop('opt') @@ -2789,6 +2644,13 @@ class SociosCuentasBanco(BaseModel): msg = 'Cuenta borrada correctamente' return {'ok': result, 'msg': msg} + @classmethod + def validate_partner_account(cls, id, invoices): + id_invoice = int(tuple(invoices.keys())[0]) + account = SociosCuentasBanco.get(SociosCuentasBanco.id==id) + invoice = Facturas.get(Facturas.id==id_invoice) + return account.socio == invoice.cliente + class Contactos(BaseModel): socio = ForeignKeyField(Socios) @@ -2843,6 +2705,226 @@ class ContactoCorreos(BaseModel): ) +class MovimientosBanco(BaseModel): + cuenta = ForeignKeyField(CuentasBanco) + fecha = DateTimeField(default=util.now, formats=['%Y-%m-%d %H:%M:%S']) + descripcion = TextField(default='') + forma_pago = ForeignKeyField(SATFormaPago) + retiro = DecimalField(default=0.0, max_digits=20, decimal_places=6, + auto_round=True) + deposito = 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) + cancelado = BooleanField(default=False) + conciliado = BooleanField(default=False) + moneda = TextField(default='MXN') # Complemento de pagos + tipo_cambio = DecimalField(default=1.0, max_digits=15, decimal_places=6, + auto_round=True) + numero_operacion = TextField(default='') + cuenta_socio = ForeignKeyField(SociosCuentasBanco, null=True) + tipo_cadena_pago = TextField(default='') + certificado_pago = TextField(default='') + cadena_pago = TextField(default='') + sello_pago = TextField(default='') + + class Meta: + order_by = ('fecha', 'id') + + def _ultimo_saldo(self, cuenta, fecha): + query = (MovimientosBanco + .select() + .where( + (MovimientosBanco.cuenta==cuenta) & + (MovimientosBanco.fecha<=fecha) & + (MovimientosBanco.cancelado==False))[-1] + ) + return round(float(query.saldo), DECIMALES) + + def _movimiento_anterior(self, cuenta, fecha): + query = (MovimientosBanco + .select() + .where( + (MovimientosBanco.cuenta==cuenta) & + (MovimientosBanco.fecharow.fecha) & + (MovimientosBanco.cancelado==False)) + ) + + saldo = round(Decimal(row.saldo), DECIMALES) + for mov in query: + mov.saldo = saldo + mov.deposito - mov.retiro + mov.save() + saldo = mov.saldo + CuentasBanco.actualizar_saldo(row.cuenta, saldo) + return saldo + + @classmethod + def post(cls, values): + opt = values.pop('opt') + return getattr(cls, '_{}'.format(opt))(cls, values) + + def _add(self, values): + ids = values.pop('ids', '') + + cuenta_socio = values.get('cuenta_socio', None) + if not ids: + cuenta_socio = None + + if ids and cuenta_socio and \ + not SociosCuentasBanco.validate_partner_account(cuenta_socio, util.loads(ids)): + msg = 'La cuenta seleccionada no corresponde al cliente' + data = {'ok': False, 'msg': msg} + return data + + if ids and not Facturas.validate_count_partners(util.loads(ids)): + msg = 'Facturas relacionadas a diferentes clientes' + data = {'ok': False, 'msg': msg} + return data + + actualizar = False + if 'saldo' in values: + saldo = values['saldo'] + else: + actualizar = True + hora = values.pop('hora') + account = CuentasBanco.get(CuentasBanco.id==int(values['cuenta'])) + values['fecha'] = '{}T{}'.format(values['fecha'][:10], hora) + values['cuenta'] = account + values['cuenta_socio'] = cuenta_socio + values['moneda'] = account.moneda.key + values['retiro'] = util.get_float(values['retiro']) + values['deposito'] = util.get_float(values['deposito']) + values['tipo_cambio'] = util.get_float( + values.get('tipo_cambio', 1.00), True) + values['forma_pago'] = int(values['forma_pago']) + + ultimo_saldo = self._ultimo_saldo( + self, values['cuenta'], values['fecha']) + + values['saldo'] = \ + ultimo_saldo - values['retiro'] + values['deposito'] + + with database_proxy.transaction(): + try: + obj = MovimientosBanco.create(**values) + except IntegrityError: + msg = 'Error al agregar el movimiento' + return {'ok': False, 'msg': msg} + + if actualizar: + saldo = self._actualizar_saldos(self, obj) + if ids: + FacturasPagos.add(obj, util.loads(ids)) + + return {'ok': True, 'saldo': saldo} + + def _cancel(self, values): + id = int(values['id']) + try: + obj = MovimientosBanco.get(MovimientosBanco.id==id) + except MovimientosBanco.DoesNotExist: + msg = 'No se encontró el movimiento' + return {'ok': False, 'msg': msg} + + if obj.cancelado: + msg = 'El movimiento ya esta cancelado' + return {'ok': False, 'msg': msg} + + if obj.conciliado: + msg = 'El movimiento esta conciliado, no se puede cancelar' + return {'ok': False, 'msg': msg} + + # ~ filters = (CfdiPagos.movimiento==obj) + # ~ cp = CfdiPagos.select().where(filters).count() + # ~ if cp > 0: + # ~ msg = 'El movimiento tiene Factura de Pago, no se puede cancelar' + # ~ return {'ok': False, 'msg': msg} + + with database_proxy.transaction(): + obj.cancelado = True + obj.save() + FacturasPagos.cancelar(obj) + + obj = self._movimiento_anterior(self, obj.cuenta, obj.fecha) + self._actualizar_saldos(self, obj) + + balance = CuentasBanco.get_saldo(obj.cuenta.id) + + msg = 'Movimiento cancelado correctamente' + return {'ok': True, 'msg': msg, 'balance': balance} + + @classmethod + def con(cls, id): + cant = (MovimientosBanco + .select(MovimientosBanco.id) + .where(MovimientosBanco.cuenta==id) + .count() + ) + if cant > 2: + return {'ok': True} + + return {'ok': False} + + + @classmethod + def get_(cls, values): + cuenta = int(values['cuenta']) + if 'fechas' in values: + rango = util.loads(values['fechas']) + fd = (MovimientosBanco.fecha.between( + util.get_date(rango['start']), + util.get_date(rango['end'], True))) + filtros = (fd & + (MovimientosBanco.cuenta==cuenta) & + (MovimientosBanco.cancelado==False) + ) + else: + year = int(values['year']) + mes = int(values['mes']) + if year == -1: + fy = (MovimientosBanco.fecha.year > 0) + else: + fy = (MovimientosBanco.fecha.year == year) + if mes == -1: + fm = (MovimientosBanco.fecha.month > 0) + else: + fm = (MovimientosBanco.fecha.month == mes) + filtros = (fy & fm & + (MovimientosBanco.cuenta==cuenta) & + (MovimientosBanco.cancelado==False) + ) + + rows = tuple(MovimientosBanco.select( + MovimientosBanco.id, + MovimientosBanco.fecha, + MovimientosBanco.numero_operacion, + SATFormaPago.name.alias('way_payment'), + MovimientosBanco.descripcion, + MovimientosBanco.retiro, + MovimientosBanco.deposito, + MovimientosBanco.saldo, + fn.COUNT(CfdiPagos.id).alias('invoice') + ) + .join(SATFormaPago).switch(MovimientosBanco) + .join(CfdiPagos, JOIN.LEFT_OUTER).switch(MovimientosBanco) + .where(filtros) + .group_by(MovimientosBanco.id, SATFormaPago.name) + .dicts() + ) + + return {'ok': True, 'rows': rows} + + class Alumnos(BaseModel): rfc = TextField(null=True) curp = TextField(index=True, unique=True) @@ -3424,13 +3506,6 @@ class Facturas(BaseModel): @classmethod def validate_count_partners(cls, ids): filters = (Facturas.id.in_(tuple(ids.keys()))) - # ~ partners = (Facturas.select(fn.COUNT(Facturas.cliente)) - # ~ .where(filters) - # ~ .group_by(Facturas.cliente) - # ~ .order_by(Facturas.cliente).tuples()) - # ~ if len(partners) > 1: - # ~ return False - # ~ return True partners = (Facturas.select(fn.COUNT(Socios.rfc)) .where(filters) .join(Socios).switch(Facturas) @@ -5763,6 +5838,7 @@ class CfdiPagos(BaseModel): def _generate_xml(self, invoice, auth): emisor = Emisor.select()[0] cert = Certificado.get_cert() + used_data_bank = Configuracion.get_bool('chk_cfg_pays_data_bank') cfdi = {} related = {} @@ -5812,7 +5888,6 @@ class CfdiPagos(BaseModel): impuestos = {} mov = invoice.movimiento - # ~ currency = mov.cuenta.moneda.key currency = mov.moneda related_docs = self._get_related_xml(self, invoice.movimiento, currency) pagos = { @@ -5822,6 +5897,20 @@ class CfdiPagos(BaseModel): 'Monto': FORMAT.format(mov.deposito), 'relacionados': related_docs, } + if mov.numero_operacion: + pagos['NumOperacion'] = mov.numero_operacion + + if used_data_bank and mov.cuenta_socio: + if mov.cuenta_socio.banco.rfc: + pagos['RfcEmisorCtaOrd'] = mov.cuenta_socio.banco.rfc + if mov.cuenta_socio.banco.rfc == RFC_EXTRANJERO: + pagos['NomBancoOrdExt'] = mov.cuenta_socio.banco.name + pagos['CtaOrdenante'] = mov.cuenta_socio.cuenta + if mov.cuenta.banco.rfc: + pagos['RfcEmisorCtaBen'] = mov.cuenta.banco.rfc + pagos['CtaBeneficiario'] = mov.cuenta.cuenta + + if currency != CURRENCY_MN: pagos['TipoCambioP'] = FORMAT_TAX.format(mov.tipo_cambio) @@ -8382,6 +8471,23 @@ def _migrate_tables(rfc=''): fecha_cancelacion = DateTimeField(null=True) migrations.append(migrator.add_column('cfdipagos', 'fecha_cancelacion', fecha_cancelacion)) + table = 'movimientosbanco' + columns = [c.name for c in database_proxy.get_columns(table)] + if not 'cuenta_socio_id' in columns: + cuenta_socio = ForeignKeyField(SociosCuentasBanco, null=True, to_field=SociosCuentasBanco.id) + migrations.append(migrator.add_column(table, 'cuenta_socio_id', cuenta_socio)) + migrations.append(migrator.drop_column(table, 'origen_rfc')) + migrations.append(migrator.drop_column(table, 'origen_nombre')) + migrations.append(migrator.drop_column(table, 'origen_cuenta')) + migrations.append(migrator.drop_column(table, 'destino_rfc')) + migrations.append(migrator.drop_column(table, 'destino_cuenta')) + + table = 'socioscuentasbanco' + columns = [c.name for c in database_proxy.get_columns(table)] + if not 'activa' in columns: + activa = BooleanField(default=True) + migrations.append(migrator.add_column(table, 'activa', activa)) + if migrations: with database_proxy.atomic() as txn: migrate(*migrations) diff --git a/source/app/settings.py b/source/app/settings.py index 764f9e9..fc4d0e9 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -47,7 +47,7 @@ except ImportError: DEBUG = DEBUG -VERSION = '1.20.0' +VERSION = '1.21.0' EMAIL_SUPPORT = ('soporte@empresalibre.net',) TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION) diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index d9b2a75..9569a3c 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -92,6 +92,7 @@ var controllers = { $$('chk_config_ine').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_edu').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_pagos').attachEvent('onItemClick', chk_config_item_click) + $$('chk_cfg_pays_data_bank').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_cuenta_predial').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_codigo_barras').attachEvent('onItemClick', chk_config_item_click) $$('chk_config_precio_con_impuestos').attachEvent('onItemClick', chk_config_item_click) @@ -1133,6 +1134,7 @@ function tab_options_change(nv, ov){ var cv = { tab_admin_templates: 'templates', tab_admin_partners: 'partners', + tab_admin_complements: 'complements', tab_admin_otros: 'configotros', } get_config_values(cv[nv]) diff --git a/source/static/js/controller/bancos.js b/source/static/js/controller/bancos.js index db6e78e..30f6f07 100644 --- a/source/static/js/controller/bancos.js +++ b/source/static/js/controller/bancos.js @@ -37,8 +37,12 @@ function init_config_bank(){ g3.showColumn('total') g3.showColumn('currency') } - show('cmd_complemento_pago', get_config('used_cfdi_pays')) - show('cmd_show_invoice_pay', get_config('used_cfdi_pays')) + var used_cfdi_pays = get_config('used_cfdi_pays') + show('cmd_complemento_pago', used_cfdi_pays) + show('cmd_show_invoice_pay', used_cfdi_pays) + if(used_cfdi_pays){ + show_column('grid_cuentabanco', 'invoice') + } set_year_month() } @@ -69,6 +73,7 @@ var bancos_controllers = { $$('cmd_pay_delete').attachEvent('onItemClick', cmd_pay_delete_click) $$('grid_cfdi_pay').attachEvent('onItemClick', grid_cfdi_pay_click) $$('grid_cfdi_por_pagar').attachEvent('onItemDblClick', grid_cfdi_por_pagar_double_click) + $$('grid_cfdi_por_pagar').attachEvent('onAfterFilter', grid_cfdi_por_pagar_on_after_filter) $$('grid_cfdi_este_deposito').attachEvent('onItemDblClick', grid_cfdi_este_deposito_double_click) $$('cmd_show_invoice_pay').attachEvent('onItemClick', cmd_show_invoice_pay_click) $$('filter_invoice_pay_year').attachEvent('onChange', filter_invoice_pay_change) @@ -206,18 +211,18 @@ function lst_cuentas_banco_change(nv, ov){ } -function get_bancos_forma_pago(retiro){ - var values = table_waypayment.chain().find({'id': { '$ne' : '99' }}).data() - if(retiro){ - lst = $$('lst_retiro_forma_pago') - }else{ - lst = $$('lst_deposito_forma_pago') - } - lst.getList().parse(values) - if(current_way_payment){ - lst.setValue(current_way_payment) - } -} +//~ function get_bancos_forma_pago(retiro){ + //~ var values = table_waypayment.chain().find({'id': { '$ne' : '99' }}).data() + //~ if(retiro){ + //~ lst = $$('lst_retiro_forma_pago') + //~ }else{ + //~ lst = $$('lst_deposito_forma_pago') + //~ } + //~ lst.getList().parse(values) + //~ if(current_way_payment){ + //~ lst.setValue(current_way_payment) + //~ } +//~ } function get_facturas_por_pagar(){ @@ -246,7 +251,7 @@ function get_facturas_por_pagar(){ function cmd_agregar_retiro_click(){ - get_bancos_forma_pago(true) + set_way_payment('lst_retiro_forma_pago', true, current_way_payment) var title = 'Agregar retiro de banco a la cuenta ' + $$('lst_cuentas_banco').getText() + ' en ' + $$('txt_cuenta_moneda').getValue() $$('title_bank_retiro').setValue(title) $$('multi_bancos').setValue('banco_retiro') @@ -255,13 +260,17 @@ function cmd_agregar_retiro_click(){ function cmd_agregar_deposito_click(){ msg_importe = '' - get_bancos_forma_pago(false) + get_facturas_por_pagar() + set_way_payment('lst_deposito_forma_pago', true, current_way_payment) var g = $$('grid_cfdi_este_deposito') g.config.columns[g.getColumnIndex('importe')].header = 'Este Pago ' + current_currency g.refreshColumns() + show('deposit_type_change', current_currency!=CURRENCY_MN) + var pays = get_config('used_cfdi_pays') && get_config('pays_data_bank') + show('lst_partner_account_bank', pays) var title = 'Agregar depósito de banco a la cuenta ' + $$('lst_cuentas_banco').getText() + ' en ' + $$('txt_cuenta_moneda').getValue() $$('title_bank_deposit').setValue(title) @@ -666,6 +675,7 @@ function guardar_deposito(values){ data['tipo_cambio'] = values.deposit_type_change.to_float4() data['retiro'] = 0.0 data['descripcion'] = values.deposito_descripcion + data['cuenta_socio'] = values.partner_account_bank current_way_payment = data['forma_pago'] @@ -716,41 +726,40 @@ function cmd_guardar_deposito_click(){ return } + msg = 'Todos los datos son correctos.

' + if(!grid.count()){ - msg = 'Todos los datos son correctos
br>' - msg = 'El depósito no tiene facturas relacionadas

¿Estás ' - msg += ' seguro de guardar el depósito sin facturas relacionadas?' - webix.confirm({ - title: 'Guardar depósito', - ok: 'Si', - cancel: 'No', - type: 'confirm-error', - text: msg, - callback:function(result){ - if(result){ - guardar_deposito(values) - } - } - }) + msg += 'El depósito no tiene facturas relacionadas
¿Estás ' + msg += ' seguro de guardar el depósito sin facturas relacionadas?

' }else{ if(!msg_importe){ - msg_importe = 'Se van a relacionar ' + grid.count() + ' facturas.' - } - msg = 'Todos los datos son correctos.

' + msg_importe + '

' - msg += '¿Deseas agregar este depósito?' - webix.confirm({ - title: 'Guardar depósito', - ok: 'Si', - cancel: 'No', - type: 'confirm-error', - text: msg, - callback:function(result){ - if(result){ - guardar_deposito(values) - } + if(grid.count()==1){ + msg += 'Se va a relacionar 1 factura.

' + }else{ + msg += 'Se van a relacionar ' + grid.count() + ' facturas.

' } - }) + } } + + if(get_config('pays_data_bank') && grid.count() && !values.partner_account_bank){ + msg += 'NO seleccionaste cuenta origen.

' + } + + msg += '¿Deseas agregar este depósito?' + + webix.confirm({ + title: 'Guardar depósito', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + guardar_deposito(values) + } + } + }) + } @@ -1259,3 +1268,28 @@ function get_invoices_pay(rango){ } }) } + + +function grid_cfdi_por_pagar_on_after_filter(){ + var partner = $$('grid_cfdi_por_pagar').getFilter('cliente').value + var lst = $$('lst_partner_account_bank') + + lst_clear(lst) + if(partner){ + var args = {opt: 'by_name', name: partner} + webix.ajax().get('/socioscb', args, { + error:function(text, data, XmlHttpRequest){ + msg = 'Ocurrio un error, consulta a soporte técnico' + msg_error(msg) + }, + success:function(text, data, XmlHttpRequest){ + var result = data.json() + if (result.ok){ + lst_parse(lst, result.values) + }else{ + msg_error(result.msg) + } + } + }) + } +} diff --git a/source/static/js/controller/main.js b/source/static/js/controller/main.js index 06632bd..a1bf37e 100644 --- a/source/static/js/controller/main.js +++ b/source/static/js/controller/main.js @@ -39,6 +39,7 @@ function configuracion_inicial(){ add_config({'key': 'decimales_precios', 'value': values.decimales_precios}) add_config({'key': 'used_cfdi_pays', 'value': values.pagos}) add_config({'key': 'multi_currency', 'value': values.multi_currency}) + add_config({'key': 'pays_data_bank', 'value': values.pays_data_bank}) }) diff --git a/source/static/js/controller/partners.js b/source/static/js/controller/partners.js index 611f275..e6dd2ab 100644 --- a/source/static/js/controller/partners.js +++ b/source/static/js/controller/partners.js @@ -78,6 +78,8 @@ function get_condicion_pago(){ function cmd_new_partner_click(id, e, node){ $$('form_partner').clearValidation() + $$('form_partner_account_bank').clearValidation() + $$('form_partner').setValues({ id: 0, pais: 'México', tipo_persona: 1, es_activo: true, partner_balance: 0.00}) @@ -106,6 +108,8 @@ function cmd_edit_partner_click(){ var msg = '' var row = $$('grid_partners').getSelectedItem() + $$('form_partner_account_bank').clearValidation() + if (row == undefined){ msg = 'Selecciona un Socio de Negocio' msg_error(msg) @@ -235,6 +239,8 @@ function cmd_save_partner_click(id, e, node){ } } + values['accounts'] = $$('grid_partner_account_bank').data.getRange() + webix.ajax().post('/partners', values, { error:function(text, data, XmlHttpRequest){ msg = 'Ocurrio un error, consulta a soporte técnico'; @@ -482,7 +488,7 @@ function cmd_partner_add_account_bank_click(){ return } - if(account.cuenta.length < 9){ + if(account.cuenta.length < 10){ msg = 'Longitud incorrecta de la cuenta' msg_error(msg) return @@ -570,6 +576,8 @@ function grid_partner_account_bank_click(id, e, node){ if(id.column != 'delete'){ return } + var id_partner = $$('form_partner').getValues().id + var grid = $$('grid_partner_account_bank') var msg = '¿Estás seguro de eliminar la cuenta de banco seleccionada?

' msg += 'ESTA ACCION NO SE PUEDE DESHACER' @@ -581,7 +589,11 @@ function grid_partner_account_bank_click(id, e, node){ text: msg, callback:function(result){ if (result){ - partner_delete_account_bank(id.row) + if(id_partner){ + partner_delete_account_bank(id.row) + }else{ + grid.remove(id.row) + } } } }) diff --git a/source/static/js/controller/util.js b/source/static/js/controller/util.js index 921a933..bae66bd 100644 --- a/source/static/js/controller/util.js +++ b/source/static/js/controller/util.js @@ -112,6 +112,11 @@ function show(nombre, value){ } +function show_column(table, column){ + $$(table).showColumn(column) +} + + function enable(nombre, value){ if(value == '0'){ value = false @@ -502,7 +507,7 @@ function get_forma_pago(control){ function get_way_payment(){ - webix.ajax().get('/values/formapago', {key: true}, function(text, data){ + webix.ajax().get('/satformapago', {opt: 'active_by_id'}, function(text, data){ var values = data.json() table_waypayment.clear() table_waypayment.insert(values) @@ -510,9 +515,16 @@ function get_way_payment(){ } -function set_way_payment(control){ - var values = table_waypayment.chain().data() +function set_way_payment(control, filter99=false, current_way_payment=''){ + if(filter99){ + var values = table_waypayment.chain().find({'value': { '$ne' : 'Por definir' }}).data() + }else{ + var values = table_waypayment.chain().data() + } $$(control).getList().parse(values) + if(current_way_payment){ + $$(control).setValue(current_way_payment) + } } @@ -553,5 +565,16 @@ function pause(milliseconds) { } + //~ Revisado +function lst_clear(lst){ + lst.setValue('') + lst.define('options', []) + lst.refresh() +} + + +function lst_parse(lst, values){ + lst.getList().parse(values) +} diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index 756bd86..30fd7e7 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -667,22 +667,6 @@ var options_admin_otros = [ labelRight: 'Mostrar inventario'}, ]}, {maxHeight: 20}, - {template: 'Complementos', type: 'section'}, - {cols: [{maxWidth: 15}, - {view: 'checkbox', id: 'chk_config_ine', labelWidth: 0, - labelRight: 'Usar el complemento INE'}, - {view: 'checkbox', id: 'chk_config_edu', labelWidth: 0, - labelRight: 'Usar el complemento EDU'}, - {}]}, - {cols: [{maxWidth: 15}, - {view: 'checkbox', id: 'chk_config_pagos', labelWidth: 0, - labelRight: 'Usar complemento de pagos'}, - {view: 'text', id: 'txt_config_cfdipay_serie', name: 'txt_config_cfdipay_serie', - label: 'Serie', labelWidth: 50, labelAlign: 'right'}, - {view: 'text', id: 'txt_config_cfdipay_folio', name: 'txt_config_cfdipay_serie', - label: 'Folio', labelWidth: 50, labelAlign: 'right'}, - {}]}, - {maxHeight: 20}, {template: 'Punto de venta', type: 'section'}, {cols: [{maxWidth: 15}, {view: 'checkbox', id: 'chk_usar_punto_de_venta', labelWidth: 0, @@ -723,6 +707,29 @@ var options_admin_partners = [ ] +var options_admin_complements = [ + {maxHeight: 20}, + {cols: [{maxWidth: 15}, + {view: 'checkbox', id: 'chk_config_ine', labelWidth: 0, + labelRight: 'Usar el complemento INE'}, + {view: 'checkbox', id: 'chk_config_edu', labelWidth: 0, + labelRight: 'Usar el complemento EDU'}, + {}]}, + {maxHeight: 20}, + {template: 'Complemento de Pagos', type: 'section'}, + {cols: [{maxWidth: 15}, + {view: 'checkbox', id: 'chk_config_pagos', labelWidth: 0, + labelRight: 'Usar complemento de pagos'}, + {view: 'checkbox', id: 'chk_cfg_pays_data_bank', labelWidth: 0, + labelRight: 'Usar datos bancarios'}, + {view: 'text', id: 'txt_config_cfdipay_serie', name: 'txt_config_cfdipay_serie', + label: 'Serie', labelWidth: 50, labelAlign: 'right'}, + {view: 'text', id: 'txt_config_cfdipay_folio', name: 'txt_config_cfdipay_serie', + label: 'Folio', labelWidth: 50, labelAlign: 'right'}, + {maxWidth: 15}]}, +] + + var tab_options = { view: 'tabview', id: 'tab_options', @@ -732,6 +739,8 @@ var tab_options = { rows: options_templates}}, {header: 'Clientes y Proveedores', body: {id: 'tab_admin_partners', view: 'scrollview', body: {rows: options_admin_partners}}}, + {header: 'Complementos', body: {id: 'tab_admin_complements', + view: 'scrollview', body: {rows: options_admin_complements}}}, {header: 'Otros', body: {id: 'tab_admin_otros', view: 'scrollview', body: {rows: options_admin_otros}}}, ], diff --git a/source/static/js/ui/bancos.js b/source/static/js/ui/bancos.js index 2f804ae..d5aa289 100644 --- a/source/static/js/ui/bancos.js +++ b/source/static/js/ui/bancos.js @@ -64,7 +64,7 @@ var grid_cuentabanco_cols = [ width: 125, format: webix.i18n.priceFormat, css: 'right'}, {id: 'saldo', header: ['Saldo'], width: 125, format: webix.i18n.priceFormat, css: 'right'}, - {id: 'invoice', header: ['FP'], width: 40, css: 'center'}, + {id: 'invoice', header: ['FP'], width: 40, css: 'center', hidden: true}, ] @@ -438,6 +438,10 @@ var controls_banco_deposito = [ ]}, {cols: [ {view: 'label', label: 'Facturas por pagar: '}, + {view: 'richselect', id: 'lst_partner_account_bank', hidden: true, + name: 'partner_account_bank', label: 'Cuenta Origen', required: false, + options: [], labelWidth: 125, labelAlign: 'right'}, + {}, {view: 'button', id: 'cmd_invoice_payed', label: 'Solo marcar pagada', type: 'iconButton', autowidth: true, icon: 'check-circle', tooltip: 'No afecta a saldos'},