139 lines
4.2 KiB
Python
139 lines
4.2 KiB
Python
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'<Employee {self.id}>'
|
||
|
||
|
||
# ----------- ВАЛИДАЦИЯ БЭКЕНДА ------------
|
||
|
||
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/<int:id>")
|
||
def employee_detail(id):
|
||
emp = Employee.query.get_or_404(id)
|
||
return render_template("employee_detail.html", emp=emp)
|
||
|
||
|
||
@app.route("/employees/<int:id>/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/<int:id>/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)
|