empresa-libre/source/app/models/main.py

703 lines
19 KiB
Python

#!/usr/bin/env python
import sqlite3
import click
from peewee import *
from playhouse.fields import PasswordField, ManyToManyField
if __name__ == '__main__':
import os, sys
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parent_dir)
from controllers import util
from settings import log, VERSION, PATH_CP, COMPANIES
database_proxy = Proxy()
class BaseModel(Model):
class Meta:
database = database_proxy
def conectar(opt):
db = {
'sqlite': SqliteDatabase,
'postgres': PostgresqlDatabase,
'mysql': MySQLDatabase,
}
db_type = opt.pop('type')
db_name = opt.pop('name')
if not db_type in db:
log.error('Tipo de base de datos no soportado')
return False
#~ print ('DB NAME', db_name)
database = db[db_type](db_name, **opt)
try:
database_proxy.initialize(database)
database_proxy.connect()
log.info('Conectado a la BD...')
return True
except OperationalError as e:
log.error('Error al intentar conectar a la base de datos')
log.error(e)
return False
def desconectar():
if database_proxy.obj is None:
return
if not database_proxy.is_closed():
database_proxy.close()
log.info('Desconectado a la BD...')
return
class Configuracion(BaseModel):
clave = TextField()
valor = TextField(default='')
class Meta:
order_by = ('clave',)
indexes = (
(('clave', 'valor'), True),
)
class Tags(BaseModel):
tag = TextField(index=True, unique=True)
class Meta:
order_by = ('tag',)
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)
def __str__(self):
t = '{} {} ({})'
return t.format(self.nombre, self.apellidos, self.usuario)
class Meta:
order_by = ('nombre', 'apellidos')
class SATRegimenes(BaseModel):
key = TextField(index=True, unique=True)
name = TextField(index=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
fisica = BooleanField(default=False)
moral = BooleanField(default=False)
class Meta:
order_by = ('name',)
indexes = (
(('key', 'name'), True),
)
class Emisor(BaseModel):
rfc = TextField(index=True)
nombre = TextField()
calle = TextField(default='')
no_exterior = TextField(default='')
no_interior = TextField(default='')
colonia = TextField(default='')
municipio = TextField(default='')
estado = TextField(default='')
pais = TextField(default='')
codigo_postal = TextField(default='')
cp_expedicion = TextField(default='')
es_moral = BooleanField(default=False)
es_ong = BooleanField(default=False)
es_escuela = BooleanField(default=False)
autorizacion = TextField(default='')
fecha_autorizacion = DateField(null=True)
fecha_dof = DateField(null=True)
telefono = TextField(default='')
correo = TextField(default='')
web = TextField(default='')
curp = TextField(default='')
regimenes = ManyToManyField(SATRegimenes, related_name='emisores')
def __str__(self):
t = '{} ({})'
return t.format(self.nombre, self.rfc)
class Meta:
order_by = ('nombre',)
class Certificado(BaseModel):
key = BlobField()
key_enc = TextField(default='')
cer = BlobField()
cer_pem = TextField(default='')
cer_txt = TextField(default='')
p12 = BlobField()
serie = TextField(default='')
rfc = TextField(default='')
desde = DateTimeField()
hasta = DateTimeField()
def __str__(self):
return self.serie
class Folios(BaseModel):
serie = TextField()
inicio = IntegerField(default=1)
default = BooleanField(default=False)
usar_con = TextField(default='T')
class Meta:
order_by = ('-default', 'serie', 'inicio')
indexes = (
(('serie', 'inicio'), True),
)
class Categorias(BaseModel):
categoria = TextField()
id_padre = IntegerField(default=0)
class Meta:
order_by = ('categoria',)
indexes = (
(('categoria', 'id_padre'), True),
)
class CondicionesPago(BaseModel):
condicion = TextField(unique=True)
class Meta:
order_by = ('condicion',)
class SATUnidades(BaseModel):
key = TextField(unique=True, index=True)
name = TextField(default='', index=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
class Meta:
order_by = ('name',)
indexes = (
(('key', 'name'), True),
)
class SATFormaPago(BaseModel):
key = TextField(unique=True, index=True)
name = TextField(default='', index=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
class Meta:
order_by = ('-default', 'name',)
indexes = (
(('key', 'name'), True),
)
class SATAduanas(BaseModel):
key = TextField(unique=True, index=True)
name = TextField(default='', index=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
class Meta:
order_by = ('-default', 'name',)
indexes = (
(('key', 'name'), True),
)
class SATMonedas(BaseModel):
key = TextField(unique=True, index=True)
name = TextField(default='', index=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
class Meta:
order_by = ('-default', 'name',)
indexes = (
(('key', 'name'), True),
)
class SATImpuestos(BaseModel):
key = TextField(index=True)
name = TextField(default='', index=True)
factor = TextField(default='T')
tipo = TextField(default='T')
tasa = DecimalField(default=0.0, decimal_places=6, auto_round=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
class Meta:
order_by = ('-default', 'name',)
indexes = (
(('key', 'factor', 'tipo', 'tasa'), True),
)
class SATUsoCfdi(BaseModel):
key = TextField(index=True, unique=True)
name = TextField(default='', index=True)
activo = BooleanField(default=False)
default = BooleanField(default=False)
fisica = BooleanField(default=True)
moral = BooleanField(default=False)
class Meta:
order_by = ('-default', 'name',)
indexes = (
(('key', 'name'), True),
)
class Addendas(BaseModel):
nombre = TextField(unique=True)
addenda = TextField()
class Meta:
order_by = ('nombre',)
class Socios(BaseModel):
rfc = TextField(index=True)
nombre = TextField(index=True)
nombre_comercial = TextField(index=True)
calle = TextField(default='')
no_exterior = TextField(default='')
no_interior = TextField(default='')
colonia = TextField(default='')
municipio = TextField(default='')
estado = TextField(default='')
pais = TextField(default='')
codigo_postal = TextField(default='')
notas = TextField(default='')
telefonos = TextField(default='')
es_activo = BooleanField(default=True)
es_moral = BooleanField(default=False)
es_extranjero = BooleanField(default=False)
es_ong = BooleanField(default=False)
fecha_alta = DateField(default=util.now)
dias_pago = IntegerField(default=0)
dias_habiles = BooleanField(default=False)
es_cliente = BooleanField(default=False)
es_proveedor = BooleanField(default=False)
cuenta_cliente = TextField(default='')
cuenta_proveedor = TextField(default='')
web = TextField(default='')
correo_facturas = TextField(default='')
condicion_pago = ForeignKeyField(CondicionesPago, null=True)
addenda = ForeignKeyField(Addendas, null=True)
tags = ManyToManyField(Tags, related_name='socios_tags')
def __str__(self):
t = '{} ({})'
return t.format(self.nombre, self.rfc)
class Meta:
order_by = ('nombre',)
indexes = (
(('rfc', 'nombre'), True),
)
class Productos(BaseModel):
categoria = ForeignKeyField(Categorias, null=True)
clave = TextField(unique=True, index=True)
clave_sat = TextField()
descripcion = TextField(index=True)
unidad = ForeignKeyField(SATUnidades)
valor_unitario = DecimalField(default=0.0, decimal_places=6, auto_round=True)
ultimo_costo = DecimalField(default=0.0, decimal_places=6, auto_round=True)
descuento = DecimalField(default=0.0, decimal_places=6, auto_round=True)
inventario = BooleanField(default=False)
existencia = DoubleField(default=0.0)
minimo = DoubleField(default=0.0)
codigo_barras = TextField(default='')
cuenta_predial = TextField(default='')
es_activo = BooleanField(default=True)
impuestos = ManyToManyField(SATImpuestos, related_name='productos')
tags = ManyToManyField(Tags, related_name='productos_tags')
class Meta:
order_by = ('descripcion',)
class Facturas(BaseModel):
cliente = ForeignKeyField(Socios)
serie = TextField(default='')
folio = IntegerField(default=0)
fecha = DateTimeField(default=util.now)
fecha_timbrado = DateTimeField(null=True)
forma_pago = TextField(default='')
condiciones_pago = TextField(default='')
subtotal = DecimalField(default=0.0, decimal_places=6, auto_round=True)
descuento = DecimalField(default=0.0, decimal_places=6, auto_round=True)
moneda = TextField(default='MXN')
tipo_cambio = DecimalField(default=1.0, decimal_places=6, auto_round=True)
total = DecimalField(default=0.0, decimal_places=6, auto_round=True)
total_mn = DecimalField(default=0.0, decimal_places=6, auto_round=True)
tipo_comprobante = TextField(default='I')
metodo_pago = TextField(default='PUE')
lugar_expedicion = TextField(default='')
confirmacion = TextField(default='')
uso_cfdi = TextField(default='')
total_retenciones = DecimalField(
decimal_places=6, auto_round=True, null=True)
total_trasladados = DecimalField(
decimal_places=6, auto_round=True, null=True)
xml = TextField(default='')
uuid = UUIDField(null=True)
estatus = TextField(default='Guardada')
regimen_fiscal = TextField(default='')
notas = TextField(default='')
pagada = BooleanField(default=False)
error = TextField(default='')
class Meta:
order_by = ('fecha',)
class FacturasDetalle(BaseModel):
factura = ForeignKeyField(Facturas)
producto = ForeignKeyField(Productos, null=True)
cantidad = DecimalField(default=0.0, decimal_places=6, auto_round=True)
valor_unitario = DecimalField(default=0.0, decimal_places=6, auto_round=True)
descuento = DecimalField(default=0.0, decimal_places=6, auto_round=True)
precio_final = DecimalField(default=0.0, decimal_places=6, auto_round=True)
importe = DecimalField(default=0.0, decimal_places=6, auto_round=True)
descripcion = TextField(default='')
unidad = TextField(default='')
clave = TextField(default='')
clave_sat = TextField(default='')
categoria = TextField(default='')
aduana = TextField(default='')
pedimento = TextField(default='')
fecha_pedimento = DateField(null=True)
alumno = TextField(default='')
curp = TextField(default='')
nivel = TextField(default='')
autorizacion = TextField(default='')
cuenta_predial = TextField(default='')
class Meta:
order_by = ('factura',)
class FacturasImpuestos(BaseModel):
factura = ForeignKeyField(Facturas)
impuesto = ForeignKeyField(SATImpuestos)
base = DecimalField(default=0.0, decimal_places=6, auto_round=True)
importe = DecimalField(default=0.0, decimal_places=6, auto_round=True)
class Meta:
order_by = ('factura',)
indexes = (
(('factura', 'impuesto'), True),
)
def authenticate(args):
respuesta = {'login': False, 'msg': 'No Autorizado', 'user': ''}
values = util.get_con(args['rfc'])
if not values:
return respuesta
conectar(values)
try:
obj = Usuarios.get(usuario=args['usuario'], es_activo=True)
except Usuarios.DoesNotExist:
return respuesta
if not obj.contraseña.check_password(args['contra']):
return respuesta
obj.ultimo_ingreso = util.now()
obj.save()
respuesta['msg'] = ''
respuesta['login'] = True
respuesta['user'] = str(obj)
respuesta['super'] = obj.es_superusuario
#~ desconectar()
return respuesta
def get_partners(values):
if values:
id = int(values['id'])
row = Clients.select().where(Clients.id==id).dicts()[0]
return row
rows = Clients.select(Clients.id, Clients.rfc, Clients.name).dicts()
return {'ok': True, 'rows': tuple(rows)}
def new_partner(values):
fields = util.clean(values)
fields['rfc'] = fields['rfc'].upper()
obj = Clients.create(**fields)
row = {
'id': obj.id,
'cia': obj.cia,
'rfc': obj.rfc,
'name': obj.name,
}
data = {'ok': True, 'row': row, 'new': True}
return data
def get_cp(cp):
con = sqlite3.connect(PATH_CP)
cursor = con.cursor()
sql = """
SELECT colonia, municipio, estado
FROM colonias, municipios, estados
WHERE colonias.id_municipio=municipios.id
AND municipios.id_estado=estados.id
AND cp=?
ORDER BY colonia"""
cursor.execute(sql, (cp,))
rows = cursor.fetchall()
cursor.close()
con.close()
data = {}
if rows:
data = {
'estado': rows[0][2],
'municipio': rows[0][1],
}
if len(rows) == 1:
data['colonia'] = rows[0][0]
else:
data['colonia'] = [r[0] for r in rows]
return data
def _init_values():
data = (
{'key': 'version', 'value': VERSION},
{'key': 'rfc_publico', 'value': 'XAXX010101000'},
{'key': 'rfc_extranjero', 'value': 'XEXX010101000'},
)
for row in data:
try:
Configuration.create(**row)
except IntegrityError:
pass
log.info('Valores iniciales insertados...')
return
def _crear_tablas():
tablas = [Addendas, Categorias, Certificado, CondicionesPago, Configuracion,
Emisor, Facturas, FacturasDetalle, FacturasImpuestos, Folios, Productos,
SATAduanas, SATFormaPago, SATImpuestos, SATMonedas, SATRegimenes,
SATUnidades, SATUsoCfdi, Socios, Tags, Usuarios,
Emisor.regimenes.get_through_model(),
Socios.tags.get_through_model(),
Productos.impuestos.get_through_model(),
Productos.tags.get_through_model(),
]
database_proxy.create_tables(tablas, True)
log.info('Tablas creadas correctamente...')
return True
def migrate_tables():
connect()
log.info('Tablas migradas correctamente...')
return
def _agregar_superusuario():
args = util.get_con()
if not args:
return
conectar(args)
usuario = input('Introduce el nuevo nombre para el superusuario: ').strip()
if not usuario:
msg = 'El nombre de usuario es requerido'
log.erro(msg)
return
ok, contraseña = util.get_pass()
if not ok:
log.error(contraseña)
return
try:
obj = Usuarios.create(
usuario=usuario, contraseña=contraseña, es_superusuario=True)
except IntegrityError:
msg = 'El usuario ya existe'
log.error(msg)
return
log.info('SuperUsuario creado correctamente...')
return
def _cambiar_contraseña():
args = util.get_con()
if not args:
return
conectar(args)
usuario = input('Introduce el nombre de usuario: ').strip()
if not usuario:
msg = 'El nombre de usuario es requerido'
log.error(msg)
return
try:
obj = Usuarios.get(usuario=usuario)
except Usuarios.DoesNotExist:
msg = 'El usuario no existe'
log.error(msg)
return
ok, contraseña = util.get_pass()
if not ok:
log.error(contraseña)
return
obj.contraseña = contraseña
obj.save()
log.info('Contraseña cambiada correctamente...')
return
def _add_emisor(rfc, args):
con = sqlite3.connect(COMPANIES)
cursor = con.cursor()
sql = """
INSERT INTO names
VALUES (?, ?)"""
try:
cursor.execute(sql, (rfc, args))
except sqlite3.IntegrityError as e:
log.error(e)
return False
con.commit()
cursor.close()
con.close()
return True
def _agregar_rfc():
rfc = input('Introduce el nuevo RFC: ').strip().upper()
if not rfc:
msg = 'El RFC es requerido'
log.error(msg)
return
datos = input('Introduce los datos de conexión: ').strip()
if not datos:
msg = 'Los datos de conexión son requeridos'
log.error(msg)
return
opt = util.parse_con(datos)
if not opt:
log.error('Datos de conexión incompletos')
return
args = opt.copy()
if conectar(args):
if _add_emisor(rfc, util.dumps(opt)) and _crear_tablas():
log.info('RFC agregado correctamente...')
return
log.error('No se pudo agregar el RFC')
return
def _listar_rfc():
data = util.get_rfcs()
for row in data:
msg = 'RFC: {}\n\t{}'.format(row[0], row[1])
log.info(msg)
return
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
help_create_tables = 'Crea las tablas en la base de datos'
help_migrate_db = 'Migra las tablas en la base de datos'
help_superuser = 'Crea un nuevo super usuario'
help_change_pass = 'Cambia la contraseña a un usuario'
help_rfc = 'Agrega un nuevo RFC'
help_br = 'Elimina un RFC'
help_lr = 'Listar RFCs'
@click.command(context_settings=CONTEXT_SETTINGS)
#~ @click.option('-bd', '--iniciar-bd',help=help_create_tables,
#~ is_flag=True, default=False)
@click.option('-m', '--migrar-bd', help=help_migrate_db,
is_flag=True, default=False)
@click.option('-ns', '--nuevo-superusuario', help=help_superuser,
is_flag=True, default=False)
@click.option('-cc', '--cambiar-contraseña', help=help_change_pass,
is_flag=True, default=False)
@click.option('-rfc', '--rfc', help=help_rfc, is_flag=True, default=False)
@click.option('-br', '--borrar-rfc', help=help_br, is_flag=True, default=False)
@click.option('-lr', '--listar-rfc', help=help_lr, is_flag=True, default=False)
def main(migrar_bd, nuevo_superusuario, cambiar_contraseña, rfc, borrar_rfc,
listar_rfc):
opt = locals()
#~ if opt['iniciar_bd']:
#~ _crear_tablas()
#~ sys.exit(0)
if opt['migrar_bd']:
migrate_tables()
sys.exit(0)
if opt['nuevo_superusuario']:
_agregar_superusuario()
sys.exit(0)
if opt['cambiar_contraseña']:
_cambiar_contraseña()
sys.exit(0)
if opt['rfc']:
_agregar_rfc()
sys.exit(0)
if opt['borrar_rfc']:
_borrar_rfc()
sys.exit(0)
if opt['listar_rfc']:
_listar_rfc()
sys.exit(0)
return
if __name__ == '__main__':
main()