import re from datetime import datetime from flask import Flask, render_template, request, redirect, url_for, flash from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///accounting.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SECRET_KEY'] = "lab4_secret_key" db = SQLAlchemy(app) # ---------------- МОДЕЛЬ ---------------- class Employee(db.Model): id = db.Column(db.Integer, primary_key=True) fullname = db.Column(db.String(120), nullable=False) salary = db.Column(db.Integer, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) def __repr__(self): return f'' # ----------- ВАЛИДАЦИЯ БЭКЕНДА ------------ def validate_employee(fullname: str, salary: str): errors = [] fullname = fullname.strip() if not fullname: errors.append("ФИО не может быть пустым") elif len(fullname) < 5 or len(fullname) > 120: errors.append("ФИО должно быть от 5 до 120 символов") elif not re.fullmatch(r"[A-Za-zА-Яа-яЁё\s\-\']+", fullname): errors.append("ФИО может содержать только буквы, пробелы, дефисы и апострофы") if not salary: errors.append("Зарплата обязательна") else: try: salary = int(salary) if salary <= 0 or salary > 10_000_000: errors.append("Зарплата должна быть от 1 до 10 000 000") except: errors.append("Зарплата должна быть числом") return errors # ---------------- РОУТЫ ---------------- @app.route("/") def index(): return render_template("index.html") @app.route("/employees") def employees(): items = Employee.query.order_by(Employee.created_at.desc()).all() total_salary = sum(e.salary for e in items) return render_template("employees.html", employees=items, total_salary=total_salary) @app.route("/create", methods=["GET", "POST"]) def create_employee(): if request.method == "POST": fullname = request.form.get("fullname", "") salary = request.form.get("salary", "") errors = validate_employee(fullname, salary) if errors: for e in errors: flash(e, "error") return render_template("create_employee.html", fullname=fullname, salary=salary) employee = Employee(fullname=fullname.strip(), salary=int(salary)) try: db.session.add(employee) db.session.commit() return redirect(url_for("employees")) except: return render_template("error.html", msg="Ошибка добавления") return render_template("create_employee.html") @app.route("/employees/") def employee_detail(id): emp = Employee.query.get_or_404(id) return render_template("employee_detail.html", emp=emp) @app.route("/employees//delete") def employee_delete(id): emp = Employee.query.get_or_404(id) try: db.session.delete(emp) db.session.commit() return redirect(url_for("employees")) except: return render_template("error.html", msg="Ошибка удаления") @app.route("/employees//update", methods=["GET", "POST"]) def employee_update(id): emp = Employee.query.get_or_404(id) if request.method == "POST": fullname = request.form.get("fullname", "") salary = request.form.get("salary", "") errors = validate_employee(fullname, salary) if errors: for e in errors: flash(e, "error") return render_template("employee_update.html", emp=emp) emp.fullname = fullname.strip() emp.salary = int(salary) try: db.session.commit() return redirect(url_for("employees")) except: return render_template("error.html", msg="Ошибка обновления") return render_template("employee_update.html", emp=emp) if __name__ == "__main__": with app.app_context(): db.create_all() app.run(debug=True)