sistema_web/private-dynamic/models/gestion.py

623 lines
19 KiB
Python

# coding: utf-8
#from datetime import datetime
from sqlalchemy.sql import func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.dialects import sqlite
from webinterface import db
from flask_login import current_user
from flask import current_app, g
import datetime
import unidecode
from webinterface.models.system import Persona
from webinterface.models.documentos import Documento
class Comision(db.Model):
__tablename__ = 'comisiones'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(100), nullable=False)
descripcion = db.Column(db.String(100))
creado = db.Column(db.Integer, db.ForeignKey('gestion.comisiones.id'), nullable=False)
logo = db.Column(UUID(as_uuid=True), nullable=True, autoincrement=False)
titulo = db.Column(UUID(as_uuid=True), nullable=True, autoincrement=False)
__table_args__ = (db.UniqueConstraint('nombre', 'creado', name='nodupesComisiones'), { 'schema': 'gestion' })
@property
def supervisor(self):
return Comision.query.filter(Comision.id==self.creado).one_or_none()
@property
def quorum(self):
miembro = Miembro.query.filter(Miembro.comisionid==self.id).count()
if miembro == 0:
return False
else:
return miembro
@property
def miembros(self):
for miembro in Miembro.query.filter(Miembro.comisionid==self.id).all():
yield miembro.persona
def mvector(self):
vector = []
for persona in self.miembros:
vector.append(persona.id)
return vector
class Miembro(db.Model):
__tablename__ = 'miembros'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
personaid = db.Column(db.BigInteger, db.ForeignKey('usuarios.personas.id'))
comisionid = db.Column(db.Integer, db.ForeignKey('gestion.comisiones.id'))
persona = db.relationship('Persona')
comision = db.relationship('Comision')
class Objetivo(db.Model):
__tablename__ = 'objetivos'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
tipo = db.Column(db.String(100), nullable=False, default=u'Estratégico')
nombre = db.Column(db.String(200), nullable=False)
descripcion = db.Column(db.Text)
parentid = db.Column(db.Integer, db.ForeignKey('gestion.objetivos.id'), nullable=False)
responsableid = db.Column(db.Integer, db.ForeignKey('gestion.comisiones.id'), nullable=False)
invitadosid = db.Column(db.Integer, db.ForeignKey('gestion.comisiones.id'), nullable=True)
# indicadores = db.relationship('Avance', back_populates="objetivo", order_by='Accion.id.desc()')
actas = db.relationship('Acta', back_populates="objetivo", order_by='Acta.secuencia.desc()')
actividades = db.relationship('Accion', back_populates="objetivo", order_by='Accion.fecha.desc()')
responsable = db.relationship('Comision', foreign_keys=[responsableid])
invitados = db.relationship('Comision', foreign_keys=[invitadosid])
estado = db.Column(db.SmallInteger, default=100)
## registros de auditoria
creado = db.Column(db.DateTime, default=func.now())
creadopor = db.Column(db.Integer, db.ForeignKey('usuarios.personas.id'), nullable=True)
modificado = db.Column(db.DateTime, default=func.now(), onupdate=func.now())
modificadopor = db.Column(db.Integer, db.ForeignKey('usuarios.personas.id'), nullable=True)
@property
def actasr(self):
for item in Acta.query.filter(Acta.objetivoid==self.id).order_by(Acta.secuencia.asc()).all():
yield item
@property
def sub_HDS(self):
return round(self.sub_horas/26,2)
@property
def modulo(self):
return ModuloGestion.query.filter(ModuloGestion.basenodeid==self.get_root().parentid).one_or_none()
@property
def modulo_raw(self):
return ModuloGestion.query.filter(ModuloGestion.basenodeid==self.id).one_or_none()
@property
def indicadores(self):
for item in Avance.query.filter(Avance.objetivoid==self.id).order_by(Avance.id.asc()).all():
yield item
@property
def iactividades(self):
for item in Accion.query.filter(Accion.objetivoid==self.id).order_by(Accion.fecha.asc()).all():
yield item
@property
def hijos(self):
for item in Objetivo.query.filter(Objetivo.parentid==self.id, Objetivo.estado<100).order_by(Objetivo.id.asc()).all():
yield item
for item in Objetivo.query.filter(Objetivo.parentid==self.id, Objetivo.estado>=100).order_by(Objetivo.id.asc()).all():
yield item
@property
def padre(self):
return Objetivo.query.get(self.parentid)
@property
def icon_class(self):
return self.get_root().tipo
@property
def sub_actividades(self):
i = 0
for item in self.hijos:
i += item.sub_actividades
for item in self.actividades:
i += 1
return i
@property
def sub_horas(self):
h = 0
for item in self.hijos:
h += item.sub_horas
for item in self.actividades:
h += item.dedicacion
for item in self.actas:
h += item.dedicacion
return h
@property
def sub_HDS(self):
return round(self.sub_horas/26,2)
@property
def sub_avanceNormalizado(self):
base = 0
numBase = 0
for item in self.hijos:
base += item.sub_avanceNormalizado
numBase += 1
for item in self.indicadores:
base += item.avanceNormalizado
numBase += 1
return base/numBase if numBase else 0
@property
def sub_avance(self):
return round(100*self.sub_avanceNormalizado)
def is_root(self):
if self.padre.parentid == 1:
return True
else:
return False
def get_root(self):
node = self
while node.padre.parentid > 1:
node = node.padre
return node
@property
def comisiones_validas(self):
node = self.get_root()
yield node.responsable
for comision in Comision.query.filter(Comision.creado == node.responsableid).all():
yield comision
@property
def miembros_responsables(self):
for miembro in self.responsable.miembros:
yield miembro
@property
def miembros_habilitados(self):
vistos = []
for miembro in self.responsable.miembros:
if miembro not in vistos:
vistos.append(miembro)
yield miembro
if self.invitados is not None:
for miembro in self.invitados.miembros:
if miembro not in vistos:
vistos.append(miembro)
yield miembro
@property
def archivado(self):
if self.estado < 100:
return False
else:
return True
def lineage(self):
ancestrys=[]
node = self.padre
while node.parentid > 1:
ancestrys.append(node)
node = node.padre
for node in reversed(ancestrys):
yield node
def get_comisiones(self, lvl=1, archived=False):
if self.invitadosid is None:
comisiones = [self.responsableid]
else:
comisiones = [self.responsableid, self.invitadosid]
if lvl > 0:
lvl = lvl - 1
for objetivo in self.hijos:
if objetivo.estado is None or objetivo.estado<100 or archived:
comisiones = comisiones + objetivo.get_comisiones(lvl=lvl, archived=archived)
return comisiones
def visible(self, lvl=5, archived=False):
comisiones = self.get_comisiones(lvl=lvl, archived=archived)
if len(comisiones)>0:
comisiones = list(set(comisiones))
try:
comisiones.remove(1)
except:
pass
existe = Miembro.query.filter(Miembro.comisionid.in_(comisiones), Miembro.personaid==current_user.id).first()
if existe is None:
# current_app.logger.debug('[No-Visble] Nodo {}: {} ({})'.format(self.nombre, current_user.login, comisiones))
return False
else:
# current_app.logger.debug('[Visible] Nodo {}: {} ({})'.format(self.nombre, current_user.login, comisiones))
return True
else:
return False
@property
def is_manager(self):
comisiones = list(set( [ self.responsableid, self.padre.responsableid ] ))
existe = Miembro.query.filter(Miembro.comisionid.in_(comisiones), Miembro.personaid==current_user.id).first()
if existe is None:
return False
else:
return True
class Avance(db.Model):
__tablename__ = 'indicadores'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
objetivoid = db.Column(db.Integer, db.ForeignKey('gestion.objetivos.id'))
nombre = db.Column(db.String(200), nullable=False)
inicial = db.Column(db.Integer, default=0)
valor = db.Column(db.Integer)
meta = db.Column(db.Integer, default=100)
ponderacion = db.Column(db.Integer, default=1)
objetivo = db.relationship('Objetivo')
@property
def progreso(self):
if self.valor>self.inicial:
return self.valor-self.inicial
else:
return 0
@property
def previo(self):
return int(100.0*self.inicial/self.meta)
@property
def avanceNormalizado(self):
return min(self.progreso/(self.meta-self.inicial), 1)
@property
def avance(self):
return int(100.0*self.progreso/self.meta)
class Acta(db.Model):
__tablename__ = 'actas'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
objetivoid = db.Column(db.Integer, db.ForeignKey('gestion.objetivos.id'))
secuencia = db.Column(db.Integer)
horaini = db.Column(db.DateTime)
horafin = db.Column(db.DateTime)
lugar = db.Column(db.String, nullable=False)
temas = db.Column(db.Text)
desarrollo = db.Column(db.Text)
acuerdos = db.Column(db.Text)
objetivo = db.relationship('Objetivo', back_populates='actas')
miembros = db.relationship('MiembrosAsistentes', back_populates='acta')
invitados = db.relationship('InvitadosAsistentes', back_populates='acta')
anexos = db.relationship('AnexosActa', back_populates='acta')
## registros de auditoria
creado = db.Column(db.DateTime, default=func.now())
creadopor = db.Column(db.Integer, db.ForeignKey('usuarios.personas.id'), nullable=True)
modificado = db.Column(db.DateTime, default=func.now(), onupdate=func.now())
modificadopor = db.Column(db.Integer, db.ForeignKey('usuarios.personas.id'), nullable=True)
@property
def documentos(self):
for evidencia in self.anexos:
yield evidencia.documento
@property
def dedicacion(self):
import datetime
now = datetime.datetime.now()
if self.horaini < now and self.horafin < now:
timedelta = self.horafin - self.horaini
secondsdelta = timedelta.total_seconds()
horasdelta = secondsdelta / 3600.0
else:
horasdelta = 0
return horasdelta
@property
def correosasistentes(self):
asistentes = []
for persona in self.miembros:
asistentes.append( (persona.persona.nombrecompleto, persona.persona.correodefecto.correo) )
for persona in self.invitados:
asistentes.append( (persona.nombre, persona.correo) )
return asistentes
@property
def asistentes(self):
asistentes = []
for persona in self.miembros:
asistentes.append( persona.persona.nombrecompleto )
for persona in self.invitados:
asistentes.append( persona.nombre )
return asistentes
@property
def txtasistentes(self):
asistentes = []
for persona in self.miembros:
asistentes.append( persona.persona.nombrecompleto )
for persona in self.invitados:
asistentes.append( u"{} ({})".format(persona.nombre, persona.correo) )
return ", ".join(asistentes)
@property
def miembrosid(self):
listado = []
for persona in self.miembros:
listado.append( persona.personaid )
return listado
@property
def invitadostextarea(self):
listado = []
for persona in self.invitados:
listado.append( u"{} {}".format(persona.correo, persona.nombre))
return "\n".join(listado)
@property
def documentos(self):
for anexo in self.anexos:
yield anexo.documento
class AnexosActa(db.Model):
__tablename__ = 'acta_anexos'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
actaid = db.Column(db.Integer, db.ForeignKey('gestion.actas.id'))
documentohash = db.Column(UUID(as_uuid=True), db.ForeignKey('doc.archivos.hash'))
__table_args__ = (db.UniqueConstraint('actaid', 'documentohash', name='nodupesAnexosActa'), { 'schema': 'gestion' })
acta = db.relationship('Acta', back_populates='anexos')
documento = db.relationship('Documento')
class MiembrosAsistentes(db.Model):
__tablename__ = 'acta_asistentes'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
personaid = db.Column(db.BigInteger, db.ForeignKey('usuarios.personas.id'))
actaid = db.Column(db.Integer, db.ForeignKey('gestion.actas.id'))
acta = db.relationship('Acta', back_populates='miembros')
persona = db.relationship('Persona')
__table_args__ = (db.UniqueConstraint('personaid', 'actaid', name='nodupesMiembrosActas'), { 'schema': 'gestion' })
class InvitadosAsistentes(db.Model):
__tablename__ = 'acta_invitados'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
correo = db.Column(db.String, nullable=False)
nombre = db.Column(db.String, nullable=False)
actaid = db.Column(db.Integer, db.ForeignKey('gestion.actas.id'))
acta = db.relationship('Acta', back_populates='invitados')
__table_args__ = (db.UniqueConstraint('correo', 'actaid', name='nodupesInvitadosActas'), { 'schema': 'gestion' })
class Accion(db.Model):
__tablename__ = 'actividades'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
objetivoid = db.Column(db.Integer, db.ForeignKey('gestion.objetivos.id'))
nombre = db.Column(db.String(200), nullable=False)
descripcion = db.Column(db.Text)
fecha = db.Column(db.Date)
estado = db.Column(db.SmallInteger, default=100)
dedicacion = db.Column(db.Integer, default=0)
objetivo = db.relationship('Objetivo', back_populates='actividades')
evidencias = db.relationship('Evidencia', back_populates='actividad')
## registros de auditoria
creado = db.Column(db.DateTime, default=func.now())
creadopor = db.Column(db.Integer, db.ForeignKey('usuarios.personas.id'), nullable=True)
modificado = db.Column(db.DateTime, default=func.now(), onupdate=func.now())
modificadopor = db.Column(db.Integer, db.ForeignKey('usuarios.personas.id'), nullable=True)
@property
def documentos(self):
for evidencia in self.evidencias:
yield evidencia.documento
class Evidencia(db.Model):
__tablename__ = 'evidencias'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
actividadid = db.Column(db.Integer, db.ForeignKey('gestion.actividades.id'))
documentohash = db.Column(UUID(as_uuid=True), db.ForeignKey('doc.archivos.hash'))
__table_args__ = (db.UniqueConstraint('actividadid', 'documentohash', name='nodupesEvidencia'), { 'schema': 'gestion' })
actividad = db.relationship('Accion', back_populates='evidencias')
documento = db.relationship('Documento')
class ModuloGestion(db.Model):
__tablename__ = 'modulo'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
basenodeid = db.Column(db.Integer, db.ForeignKey('gestion.objetivos.id'))
nombre = db.Column(db.String(100), nullable=False)
uri = db.Column(db.String(100), nullable=False, unique=True)
etiqueta = db.Column(db.String(100), nullable=False)
nodobase = db.relationship('Objetivo')
@property
def icon(self):
return self.nodobase.tipo
@property
def quorum(self):
return AccesosModuloGestion.query.filter(AccesosModuloGestion.moduloid==self.id).count()
def mvector(self):
vector = []
for acceso in AccesosModuloGestion.query.filter(AccesosModuloGestion.moduloid==self.id).all():
vector.append(acceso.comisionid)
return vector
class AccesosModuloGestion(db.Model):
__tablename__ = 'acceso'
__table_args__ = { 'schema': 'gestion' }
__bind_key__ = 'system'
id = db.Column(db.Integer, primary_key=True)
moduloid = db.Column(db.Integer, db.ForeignKey('gestion.modulo.id'))
comisionid = db.Column(db.Integer, db.ForeignKey('gestion.comisiones.id'))
__table_args__ = (db.UniqueConstraint('moduloid', 'comisionid', name='no_dupes_acceso_gestion'), { 'schema': 'gestion' })
modulo = db.relationship('ModuloGestion')
comision = db.relationship('Comision')
class AccesoGestion():
def __init__(self):
if 'accesogestion' not in g:
self.sysadmin = False
self.admin = []
self.usuario = []
for modulo in self.get_modulos():
if modulo.nodobase.visible():
self.usuario.append(modulo)
for comision in Comision.query.join(Miembro).filter(Miembro.personaid==current_user.id, Comision.creado==1).all():
if comision.id > 999:
self.admin.append(comision.id)
elif comision.id == 1:
self.sysadmin = True
self.admin.append(comision.id)
g.accesogestion = {
'sysadmin': self.sysadmin,
'admin': self.admin,
'usuario': self.usuario
}
else:
self.sysadmin = g.accesogestion['sysadmin']
self.admin = g.accesogestion['admin']
self.usuario = g.accesogestion['usuario']
def get_nodes(self):
for modulo in self.usuario:
yield modulo
def get_modulos(self):
for modulo in ModuloGestion.query.order_by(ModuloGestion.id.asc()).all():
yield modulo
def in_gestion(self):
if len(self.usuario) > 0:
return True
else:
return self.sysadmin
def is_sysadmin(self):
return self.sysadmin
def is_admin(self):
if len(self.admin)>0:
return True
else:
return False
def administrador(self):
for item in self.admin:
yield Comision.query.get(item)
def comisiones(self, admin):
if admin > 1:
yield Comision.query.get(admin)
for item in Comision.query.filter(Comision.creado.in_(self.admin), Comision.creado==admin).all():
yield item
elif self.sysadmin:
for item in Comision.query.filter(Comision.creado==1).order_by(Comision.id.asc()).all():
yield item
def valid_users(self, admin):
if admin > 1:
for item in Miembro.query.join(Comision).filter(Comision.creado==1).distinct(Miembro.personaid).all():
yield Persona.query.get(item.personaid)
elif self.sysadmin:
for item in Persona.query.order_by(Persona.nombres.asc(), Persona.apellidop.asc()).all():
yield item