Загрузка данных


import shutil
from dataclasses import Field
import datetime as dt
import flet as ft
from fletable import EditableTable, ForeignKeyConfig, FieldConfig
from sqlalchemy import select, cast, or_
from sqlalchemy.types import String
from core.models import Appointment, User, Patient, Service, Doctor, AppStatus, Specialization
from core.db import session, engine
from src.header import Header


class DocForm(ft.Column):
    def __init__(self, mode, on_succes, aid=0):
        super().__init__()
        self.mode = mode
        self.on_success = on_succes
        self.aid = aid
        self.scroll = ft.ScrollMode.ALWAYS

        self.spec_dd = ft.Dropdown(label="Специализация")
        self.name_f = ft.TextField(label="имя")
        self.exp_f = ft.TextField(label="Опыт")
        self.price_f = ft.TextField(label="Цена")

        self.alert = ft.AlertDialog(
            title="Предупреждение",
            icon=ft.Icons.WARNING,
            actions=[ft.Button("OK", on_click=lambda e: e.page.pop_dialog())]
        )

        self.controls = self.build()

    def build(self):
        specs = session.scalars(select(Specialization))
        self.spec_dd.options = [
            ft.Dropdown(text=p.name, key=p.id) for p in specs
        ]
        del_btn = ft.Button("Удалить", bgcolor=ft.Colors.RED, icon=ft.Icons.DELETE, on_click=self.delete)
        save_btn = ft.Button("Сохранить", icon=ft.Icons.SAVE, on_click=self.save)

        res = [self.spec_dd, self.name_f, self.exp_f, self.price_f, save_btn]

        if self.mode == "edit":
            self.build_edit()
            res.append(del_btn)
        return res

    def build_edit(self):
        d = session.get(Doctor, self.aid)
        self.spec_dd.value = d.specialization_id
        self.name_f.value = d.name
        self.exp_f.value = d.experience
        self.price_f.value = float(d.price)

    def save(self):
        if self.mode == "add":
            d = Doctor()
            session.add(d)
        else:
            d = session.get(Doctor, self.aid)

        spec = self.spec_dd.value
        name = self.name_f.value
        exp = self.exp_f.value
        price = self.price_f.value
        if None in [spec, name, exp, price]:
            self.alert.content = ft.Text("Введите все данные")
            self.page.show_dialog(self.alert)
            return
        try:
            d.specialization_id = spec
            d.name = name
            d.experience = int(exp)
            d.price = float(price)

            session.commit()
            self.on_success()
            self.alert.content = ft.Text("Успех")
            self.page.pop_dialog()
            self.page.show_dialog(self.alert)

        except (ValueError, TypeError):
            self.alert.content = ft.Text("Число")
            self.page.show_dialog(self.alert)
            session.rollback()
        except Exception as e:
            print(e)
            session.rollback()

    def delete(self):
        def real_delete():
            d = session.get(Doctor, self.aid)
            app = session.scalar(select(Appointment).where(Appointment.doctor_id == d.id))

            if app is not None:
                print(app.id)
                self.alert.content = ft.Text("Нельзя удалить: У доктора есть записи")
                self.page.show_dialog(self.alert)
                return

            session.delete(d)
            session.commit()
            self.on_success()

            self.page.pop_dialog()
            self.page.pop_dialog()
            self.alert.content = ft.Text("Успех")
            self.page.show_dialog(self.alert)

        delete_dlg = ft.AlertDialog(
            title="Подтверждение",
            content=ft.Text("Уверены что хотите удалить?"),
            actions=[
                ft.Button("Да", on_click=real_delete),
                ft.Button("НЕТ", on_click=lambda e: e.page.pop_dialog())
            ]
        )

        self.page.show_dialog(delete_dlg)






class DoctorView(ft.View):
    def __init__(self, page: ft.Page):
        super().__init__()
        self._page = page
        self.route = "/doctor"
        self.scroll = ft.ScrollMode.ALWAYS

        self.user_id = self._page.session.store.get("id")
        self.user_role = self._page.session.store.get("role")


        self.doc_list = ft.Column()

        self.build_list()
        self.controls = self.build()

    def build(self):
        if self.user_role != "гость":
            u = session.get(User, self.user_id)
            u = u.name
        else:
            u = "Гость"
        head = Header(u, self.user_role)
        title = ft.Text("Доктор", size=24)

        add_btn = ft.Button("Добавить", on_click=self.build_add)
        back_btn = ft.Button("Назад", on_click=lambda e: e.page.go("/login"))
        res = [head, title, add_btn, back_btn, self.doc_list]
        return res

    def build_list(self):
        stmt = select(Doctor).join(Doctor.specialization)

        try:
            self.doc_list.controls.clear()
            docs = session.scalars(stmt)
            for d in docs:
                text_cont = ft.Container(
                    content=ft.Text(
                        f"{d.specialization.name}\n"
                        f"{d.name}\n"
                        f"{d.price}\n"
                    ),
                    expand=True,
                    border=ft.Border.all(2, '#000000')
                )

                exp_cont = ft.Container(
                    content=ft.Text(f"{d.experience}"),
                    alignment=ft.Alignment(0, 0),
                    border=ft.Border.all(1, ft.Colors.BLACK_12),
                    width=100,
                    height=100,
                )

                ctrl = ft.Container(
                    content=ft.Row(
                        controls=[
                            text_cont, exp_cont
                        ],
                        alignment=ft.MainAxisAlignment.SPACE_BETWEEN
                    ),
                    border=ft.Border.all(1, ft.Colors.BLACK),
                    padding=ft.Padding.all(5)
                )


                ctrl.on_click = lambda e, did=d.id: self.build_edit(did)

                self.doc_list.controls.append(ctrl)
            self.page.update()
        except Exception as e:
            print(e)


    def build_add(self):
        add_dialog = ft.AlertDialog(
            title="Добавление",
            content=DocForm("add", self.build_list),
        )
        self.page.show_dialog(add_dialog)


    def build_edit(self, aid):
        edit_dlg = ft.AlertDialog(
            title=f"Редактириование товара {aid}",
            content=DocForm("edit", self.build_list, aid),
        )
        self.page.show_dialog(edit_dlg)