diff --git a/source/app/models/main.py b/source/app/models/main.py index 2e78e77..8dca3cd 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -837,68 +837,6 @@ class TipoMovimientoAlmacen(BaseModel): return self.nombre -class Sucursales(BaseModel): - nombre = TextField(default='') - direccion = TextField(default='') - serie_facturas = TextField(default='') - serie_tickets = TextField(default='') - - class Meta: - order_by = ('nombre',) - - @classmethod - def _get_for_admin(cls, args): - rows = (Sucursales - .select( - Sucursales.id, - Sucursales.nombre.alias('name'), - Sucursales.serie_facturas.alias('serie_invoice'), - Sucursales.serie_tickets, - ) - .dicts() - ) - return tuple(rows) - - @classmethod - def get_data(cls, values): - opt = values['opt'] - return getattr(cls, f'_get_{opt}')(values) - - @classmethod - def _create(cls, args): - try: - values = utils.loads(args) - Sucursales.create(**values) - result = {'ok': True} - except Exception as e: - log.error(e) - msg = 'Ocurrio un error al agregar la sucursal' - result = {'ok': False, 'msg': msg} - - return result - - @classmethod - def _delete(cls, args): - values = utils.loads(args) - id = values['id'] - - try: - q = Sucursales.delete().where(Sucursales.id==id) - r = bool(q.execute()) - result = {'ok': r} - except Exception as e: - log.error(e) - result = {'ok': False, 'msg': 'Ocurrio un error al intentar eliminar'} - - return result - - @classmethod - def post(cls, values): - opt = values['opt'] - args = values['values'] - return getattr(cls, f'_{opt}')(args) - - class Roles(BaseModel): nombre = TextField(default='') @@ -922,105 +860,6 @@ class Permisos(BaseModel): ) -class Usuarios(BaseModel): - usuario = TextField(unique=True) - nombre = TextField(default='') - apellidos = TextField(default='') - correo = TextField(default='') - contraseña = PasswordField() - es_superusuario = BooleanField(default=False) - es_admin = BooleanField(default=False) - es_activo = BooleanField(default=True) - fecha_ingreso = DateTimeField(default=util.now) - ultimo_ingreso = DateTimeField(null=True) - sucursal = ForeignKeyField(Sucursales, null=True) - rol = ForeignKeyField(Roles, null=True) - - def __str__(self): - t = '{} {} ({})' - return t.format(self.nombre, self.apellidos, self.usuario) - - class Meta: - order_by = ('nombre', 'apellidos') - - def _get_is_admin(self, filters, user): - return {'is_admin': user.es_admin} - - @classmethod - def get_data(cls, filters, user): - method = f"_get_{filters['opt']}" - return getattr(cls, method)(cls, filters, user) - - @classmethod - def add(cls, values): - values['contraseña'] = values.pop('contra') - try: - Usuarios.create(**values) - return {'ok': True} - except Exception as e: - log.error(e) - msg = 'Ocurrio un error, consulta a soporte técnico' - return {'ok': False, 'msg': msg} - - @classmethod - def remove(cls, id): - q = Usuarios.delete().where(Usuarios.id==int(id)) - return bool(q.execute()) - - @classmethod - def edit(self, values): - # ~ print (values) - id = int(values.pop('id')) - try: - if 'contra' in values: - values['contraseña'] = values.pop('contra') - q = Usuarios.update(**values).where(Usuarios.id==id) - result = {'ok': bool(q.execute())} - except IntegrityError: - msg = 'El usuario ya existe' - result = {'ok': False, 'msg': msg} - - return result - - @classmethod - def actualizar(self, values, user): - id = int(values['id']) - v = {'0': False, '1': True} - - if values['field'] == 'es_superusuario' and not user.es_superusuario: - msg = 'Solo un super usuario puede hacer este cambio' - return {'ok': False, 'msg': msg} - - if values['field'] == 'es_activo': - q = (Usuarios - .update(**{'es_activo': v[values['value']]}) - .where(Usuarios.id==id)) - result = bool(q.execute()) - elif values['field'] == 'es_admin': - q = (Usuarios - .update(**{'es_admin': v[values['value']]}) - .where(Usuarios.id==id)) - result = bool(q.execute()) - elif values['field'] == 'es_superusuario': - q = (Usuarios - .update(**{'es_superusuario': v[values['value']]}) - .where(Usuarios.id==id)) - result = bool(q.execute()) - - return {'ok': result} - - @classmethod - def get_(cls, user): - if user.es_superusuario: - rows = Usuarios.select().dicts() - else: - filters = (Usuarios.es_superusuario == False) - rows = Usuarios.select().where(filters).dicts() - for row in rows: - del row['contraseña'] - return tuple(rows) - - class Registro(BaseModel): usuario = TextField() accion = TextField(default='') @@ -3540,15 +3379,177 @@ class ParienteCorreos(BaseModel): class Almacenes(BaseModel): - nombre = TextField(default='') + name = TextField(unique=True) ubicacion = TextField(default='') + class Meta: + order_by = ('name',) + + +class Sucursales(BaseModel): + wharehouse = ForeignKeyField(Almacenes, null=True) + nombre = TextField(default='') + direccion = TextField(default='') + serie_facturas = TextField(default='') + serie_tickets = TextField(default='') + class Meta: order_by = ('nombre',) + @classmethod + def _get_for_admin(cls, args): + rows = (Sucursales + .select( + Sucursales.id, + Sucursales.nombre.alias('name'), + Sucursales.serie_facturas.alias('serie_invoice'), + Sucursales.serie_tickets, + ) + .dicts() + ) + return tuple(rows) + + @classmethod + def get_data(cls, values): + opt = values['opt'] + return getattr(cls, f'_get_{opt}')(values) + + @classmethod + def _create(cls, args): + try: + values = utils.loads(args) + Sucursales.create(**values) + result = {'ok': True} + except Exception as e: + log.error(e) + msg = 'Ocurrio un error al agregar la sucursal' + result = {'ok': False, 'msg': msg} + + return result + + @classmethod + def _delete(cls, args): + values = utils.loads(args) + id = values['id'] + + try: + q = Sucursales.delete().where(Sucursales.id==id) + r = bool(q.execute()) + result = {'ok': r} + except Exception as e: + log.error(e) + result = {'ok': False, 'msg': 'Ocurrio un error al intentar eliminar'} + + return result + + @classmethod + def post(cls, values): + opt = values['opt'] + args = values['values'] + return getattr(cls, f'_{opt}')(args) + + +class Usuarios(BaseModel): + usuario = TextField(unique=True) + nombre = TextField(default='') + apellidos = TextField(default='') + correo = TextField(default='') + contraseña = PasswordField() + es_superusuario = BooleanField(default=False) + es_admin = BooleanField(default=False) + es_activo = BooleanField(default=True) + fecha_ingreso = DateTimeField(default=util.now) + ultimo_ingreso = DateTimeField(null=True) + sucursal = ForeignKeyField(Sucursales, null=True) + rol = ForeignKeyField(Roles, null=True) + + def __str__(self): + t = '{} {} ({})' + return t.format(self.nombre, self.apellidos, self.usuario) + + class Meta: + order_by = ('nombre', 'apellidos') + + def _get_is_admin(self, filters, user): + return {'is_admin': user.es_admin} + + @classmethod + def get_data(cls, filters, user): + method = f"_get_{filters['opt']}" + return getattr(cls, method)(cls, filters, user) + + @classmethod + def add(cls, values): + values['contraseña'] = values.pop('contra') + try: + Usuarios.create(**values) + return {'ok': True} + except Exception as e: + log.error(e) + msg = 'Ocurrio un error, consulta a soporte técnico' + return {'ok': False, 'msg': msg} + + @classmethod + def remove(cls, id): + q = Usuarios.delete().where(Usuarios.id==int(id)) + return bool(q.execute()) + + @classmethod + def edit(self, values): + # ~ print (values) + id = int(values.pop('id')) + try: + if 'contra' in values: + values['contraseña'] = values.pop('contra') + q = Usuarios.update(**values).where(Usuarios.id==id) + result = {'ok': bool(q.execute())} + except IntegrityError: + msg = 'El usuario ya existe' + result = {'ok': False, 'msg': msg} + + return result + + @classmethod + def actualizar(self, values, user): + id = int(values['id']) + v = {'0': False, '1': True} + + if values['field'] == 'es_superusuario' and not user.es_superusuario: + msg = 'Solo un super usuario puede hacer este cambio' + return {'ok': False, 'msg': msg} + + if values['field'] == 'es_activo': + q = (Usuarios + .update(**{'es_activo': v[values['value']]}) + .where(Usuarios.id==id)) + result = bool(q.execute()) + elif values['field'] == 'es_admin': + q = (Usuarios + .update(**{'es_admin': v[values['value']]}) + .where(Usuarios.id==id)) + result = bool(q.execute()) + elif values['field'] == 'es_superusuario': + q = (Usuarios + .update(**{'es_superusuario': v[values['value']]}) + .where(Usuarios.id==id)) + result = bool(q.execute()) + + return {'ok': result} + + @classmethod + def get_(cls, user): + if user.es_superusuario: + rows = Usuarios.select().dicts() + else: + filters = (Usuarios.es_superusuario == False) + rows = Usuarios.select().where(filters).dicts() + for row in rows: + del row['contraseña'] + return tuple(rows) + class Productos(BaseModel): - almacen = ForeignKeyField(Almacenes, null=True) + # ~ almacen = ForeignKeyField(Almacenes, null=True) categoria = ForeignKeyField(Categorias, null=True) clave = TextField(unique=True, index=True) clave_sat = TextField(default='') @@ -3903,6 +3904,18 @@ class Productos(BaseModel): return bool(q.execute()) +class WhareHouseProduct(BaseModel): + wharehouse = ForeignKeyField(Almacenes) + product = ForeignKeyField(Productos) + exists = DecimalField(default=0.0, max_digits=18, decimal_places=2, + auto_round=True) + + class Meta: + indexes = ( + (('wharehouse', 'product'), True), + ) + + class RangosPrecios(BaseModel): producto = ForeignKeyField(Productos) descripcion = TextField(default='') @@ -9806,6 +9819,7 @@ def _crear_tablas(rfc): PartnerProducts, InventoryEntries, PartnerInvoices, + WhareHouseProduct, ] log.info('Creando tablas...') database_proxy.create_tables(tablas, True) @@ -9862,6 +9876,7 @@ def _migrate_tables(rfc=''): PartnerProducts, InventoryEntries, PartnerInvoices, + WhareHouseProduct, ] log.info('Creando tablas nuevas...') database_proxy.create_tables(tablas, True) @@ -9987,6 +10002,8 @@ def _migrate_tables(rfc=''): is_discontinued = BooleanField(default=False) migrations.append(migrator.add_column( table, 'is_discontinued', is_discontinued)) + if 'almacen_id' in columns: + migrations.append(migrator.drop_column(table, 'almacen_id')) table = 'facturasdetalle' columns = [c.name for c in database_proxy.get_columns(table)] @@ -10002,6 +10019,19 @@ def _migrate_tables(rfc=''): divisas = TextField(default='') migrations.append(migrator.add_column(table, 'divisas', divisas)) + table = 'almacenes' + columns = [c.name for c in database_proxy.get_columns(table)] + if 'nombre' in columns: + name = TextField(unique=True, default='') + migrations.append(migrator.drop_column(table, 'nombre')) + migrations.append(migrator.add_column(table, 'name', name)) + + table = 'sucursales' + columns = [c.name for c in database_proxy.get_columns(table)] + if not 'wharehouse_id' in columns: + wharehouse = ForeignKeyField(Almacenes, null=True, to_field=Almacenes.id) + migrations.append(migrator.add_column(table, 'wharehouse', wharehouse)) + if migrations: with database_proxy.atomic() as txn: migrate(*migrations) diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js index 594da5a..33fac40 100644 --- a/source/static/js/controller/admin.js +++ b/source/static/js/controller/admin.js @@ -96,6 +96,7 @@ var controllers = { $$('chk_config_precio_con_impuestos').attachEvent('onItemClick', chk_config_item_click) $$('chk_llevar_inventario').attachEvent('onItemClick', chk_config_item_click) $$('chk_multi_stock').attachEvent('onItemClick', chk_config_item_click) + $$('cmd_add_wharehouse').attachEvent('onItemClick', cmd_add_wharehouse_click) //~ $$('chk_use_packing').attachEvent('onItemClick', chk_config_item_click) //~ Complements @@ -2521,6 +2522,7 @@ function admin_config_other_options(id){ }else{ $$('chk_multi_stock').setValue(0) $$('chk_multi_stock').disable() + set_visible_wharehouse(false) disable_config_option('chk_multi_stock') } }else if(id=='chk_multi_stock'){ @@ -2967,3 +2969,28 @@ function disable_config_option(id){ } }) } + + +function cmd_add_wharehouse_click(){ + var value = $$('txt_add_wharehouse').getValue().trim() + + if(!value){ + msg = 'El nombre del almacen es requerido' + msg_error(msg) + return + } + + msg = '¿Deseas agregar este Almacen?' + webix.confirm({ + title: 'Agregar Almacen', + ok: 'Si', + cancel: 'No', + type: 'confirm-error', + text: msg, + callback:function(result){ + if(result){ + add_wharehouse(value) + } + } + }) +}