# 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