Spaces:
Paused
Paused
| from datetime import datetime, date | |
| from flask_login import UserMixin | |
| from werkzeug.security import generate_password_hash, check_password_hash | |
| from extensions import db | |
| class User(UserMixin, db.Model): | |
| __tablename__ = 'users' | |
| id = db.Column(db.Integer, primary_key=True) | |
| username = db.Column(db.String(80), unique=True, nullable=False, index=True) | |
| email = db.Column(db.String(120), unique=True, nullable=True) | |
| password_hash = db.Column(db.String(256), nullable=False) | |
| full_name = db.Column(db.String(200), nullable=False) | |
| role = db.Column(db.String(20), nullable=False, default='employee') | |
| is_active = db.Column(db.Boolean, default=True) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| senior_expert_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) | |
| telegram_chat_id = db.Column(db.String(100), nullable=True) | |
| profile_pic = db.Column(db.String(300), nullable=True) | |
| grade = db.Column(db.String(50), nullable=True) | |
| project_start_date = db.Column(db.Date, nullable=True) | |
| phone = db.Column(db.String(30), nullable=True) | |
| telegram = db.Column(db.String(100), nullable=True) | |
| emergency_contact = db.Column(db.String(200), nullable=True) | |
| emergency_contact_phone = db.Column(db.String(30), nullable=True) | |
| position = db.Column(db.String(100), nullable=True) | |
| delegated_admin_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) | |
| previous_review_rating = db.Column(db.String(50), nullable=True) | |
| senior_expert = db.relationship('User', remote_side=[id], backref='subordinates', foreign_keys=[senior_expert_id]) | |
| delegated_admin = db.relationship('User', remote_side=[id], foreign_keys=[delegated_admin_id]) | |
| def set_password(self, password): | |
| self.password_hash = generate_password_hash(password) | |
| def check_password(self, password): | |
| return check_password_hash(self.password_hash, password) | |
| def has_role(self, *roles): | |
| return self.role in roles | |
| def _is_admin(self): | |
| if self.role in ('admin', 'sm'): | |
| return True | |
| if self.position == 'руководитель': | |
| return True | |
| if self.delegated_admin_id is not None: | |
| return True | |
| return False | |
| def can_view_employee(self, employee): | |
| if not self.is_authenticated: | |
| return False | |
| if self._is_admin(): | |
| return True | |
| if self.role == 'guest': | |
| return True | |
| if self.id == employee.id: | |
| return True | |
| if employee.is_active: | |
| return True | |
| return False | |
| def can_edit(self): | |
| return self._is_admin() | |
| def get_visible_users(self): | |
| if self._is_admin(): | |
| return User.query.filter_by(is_active=True).all() | |
| if self.role == 'guest': | |
| return User.query.filter_by(is_active=True).all() | |
| if self.role == 'senior_expert': | |
| visible = [self] | |
| visible.extend(User.query.filter_by(senior_expert_id=self.id, is_active=True).all()) | |
| return visible | |
| return [self] | |
| class KpiDefinition(db.Model): | |
| __tablename__ = 'kpi_definitions' | |
| id = db.Column(db.Integer, primary_key=True) | |
| name = db.Column(db.String(200), nullable=False) | |
| description = db.Column(db.Text, nullable=True) | |
| unit = db.Column(db.String(50), nullable=True) | |
| category = db.Column(db.String(100), nullable=True) | |
| target_value = db.Column(db.Float, nullable=True) | |
| is_active = db.Column(db.Boolean, default=True) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| class KpiValue(db.Model): | |
| __tablename__ = 'kpi_values' | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| kpi_id = db.Column(db.Integer, db.ForeignKey('kpi_definitions.id'), nullable=False, index=True) | |
| value = db.Column(db.Float, nullable=True) | |
| month = db.Column(db.Integer, nullable=False) | |
| year = db.Column(db.Integer, nullable=False) | |
| uploaded_file_id = db.Column(db.Integer, db.ForeignKey('uploaded_files.id'), nullable=True) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| user = db.relationship('User', backref='kpi_values') | |
| kpi = db.relationship('KpiDefinition', backref='values') | |
| uploaded_file = db.relationship('UploadedFile', backref='kpi_values') | |
| class UploadedFile(db.Model): | |
| __tablename__ = 'uploaded_files' | |
| id = db.Column(db.Integer, primary_key=True) | |
| filename = db.Column(db.String(300), nullable=False) | |
| original_name = db.Column(db.String(300), nullable=False) | |
| file_type = db.Column(db.String(10), nullable=False) | |
| file_size = db.Column(db.Integer, default=0) | |
| description = db.Column(db.String(500), nullable=True) | |
| kpi_name = db.Column(db.String(200), nullable=True) | |
| uploaded_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) | |
| upload_date = db.Column(db.DateTime, default=datetime.utcnow) | |
| uploader = db.relationship('User', backref='uploads') | |
| class Notification(db.Model): | |
| __tablename__ = 'notifications' | |
| __table_args__ = ( | |
| db.Index('ix_notif_user_read', 'user_id', 'is_read'), | |
| ) | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| message = db.Column(db.Text, nullable=False) | |
| type = db.Column(db.String(50), default='info') | |
| is_read = db.Column(db.Boolean, default=False) | |
| link = db.Column(db.String(500), nullable=True) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| user = db.relationship('User', backref='notifications') | |
| class Task(db.Model): | |
| __tablename__ = 'tasks' | |
| id = db.Column(db.Integer, primary_key=True) | |
| title = db.Column(db.String(300), nullable=False) | |
| description = db.Column(db.Text, nullable=True) | |
| assigned_to = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| assigned_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) | |
| status = db.Column(db.String(20), default='pending') | |
| priority = db.Column(db.String(20), default='medium') | |
| due_date = db.Column(db.Date, nullable=True) | |
| comment = db.Column(db.Text, nullable=True) | |
| rework_comment = db.Column(db.Text, nullable=True) | |
| completed_at = db.Column(db.DateTime, nullable=True) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| assignee = db.relationship('User', foreign_keys=[assigned_to], backref='assigned_tasks') | |
| assigner = db.relationship('User', foreign_keys=[assigned_by], backref='created_tasks') | |
| class KpiWeeklyData(db.Model): | |
| __tablename__ = 'kpi_weekly_data' | |
| __table_args__ = ( | |
| db.Index('ix_kwd_week_cat_metric', 'week_start', 'category', 'metric_name'), | |
| ) | |
| id = db.Column(db.Integer, primary_key=True) | |
| category = db.Column(db.String(100), nullable=False) | |
| metric_name = db.Column(db.String(200), nullable=False) | |
| week_start = db.Column(db.Date, nullable=False, index=True) | |
| value = db.Column(db.String(50), nullable=True) | |
| updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| class EmployeeKpiValue(db.Model): | |
| __tablename__ = 'employee_kpi_values' | |
| __table_args__ = ( | |
| db.Index('ix_ekv_lookup', 'user_id', 'week_start', 'category', 'metric_name'), | |
| db.Index('ix_ekv_week', 'week_start'), | |
| ) | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| category = db.Column(db.String(100), nullable=False) | |
| metric_name = db.Column(db.String(200), nullable=False) | |
| week_start = db.Column(db.Date, nullable=False, index=True) | |
| value_date = db.Column(db.Date, nullable=True) | |
| plan_value = db.Column(db.String(50), nullable=True) | |
| fact_value = db.Column(db.String(50), nullable=True) | |
| aggregation = db.Column(db.String(10), default='sum') | |
| updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| user = db.relationship('User', backref='kpi_entries') | |
| class EmployeeMapping(db.Model): | |
| __tablename__ = 'employee_mappings' | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, unique=True, index=True) | |
| rebus_login = db.Column(db.String(200), nullable=False) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| user = db.relationship('User', backref='rebus_mapping', uselist=False) | |
| class Training(db.Model): | |
| __tablename__ = 'trainings' | |
| id = db.Column(db.Integer, primary_key=True) | |
| title = db.Column(db.String(300), nullable=False) | |
| description = db.Column(db.Text, nullable=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| date = db.Column(db.Date, nullable=False, default=date.today) | |
| hours = db.Column(db.Float, nullable=True) | |
| status = db.Column(db.String(20), default='completed') | |
| file_path = db.Column(db.String(300), nullable=True) | |
| original_name = db.Column(db.String(300), nullable=True) | |
| file_size = db.Column(db.Integer, default=0) | |
| uploaded_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) | |
| upload_date = db.Column(db.DateTime, default=datetime.utcnow) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| user = db.relationship('User', foreign_keys=[user_id], backref='trainings') | |
| uploader = db.relationship('User', foreign_keys=[uploaded_by], backref='uploaded_trainings') | |
| class Audit(db.Model): | |
| __tablename__ = 'audits' | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| file_name = db.Column(db.String(300), nullable=False) | |
| original_name = db.Column(db.String(300), nullable=False) | |
| audit_type = db.Column(db.String(20), nullable=False, default='audit') | |
| file_size = db.Column(db.Integer, default=0) | |
| uploaded_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True) | |
| upload_date = db.Column(db.DateTime, default=datetime.utcnow) | |
| user = db.relationship('User', foreign_keys=[user_id], backref='audits') | |
| uploader = db.relationship('User', foreign_keys=[uploaded_by], backref='uploaded_audits') | |
| class ScheduleShift(db.Model): | |
| __tablename__ = 'schedule_shifts' | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True) | |
| date = db.Column(db.Date, nullable=False, index=True) | |
| shift_type = db.Column(db.String(20), nullable=False, default='shift') | |
| time_from = db.Column(db.String(5), nullable=True) | |
| time_to = db.Column(db.String(5), nullable=True) | |
| hours = db.Column(db.Float, nullable=True) | |
| created_at = db.Column(db.DateTime, default=datetime.utcnow) | |
| updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| user = db.relationship('User', backref='schedule_shifts') | |
| __table_args__ = ( | |
| db.UniqueConstraint('user_id', 'date', name='uq_user_date'), | |
| ) | |