Загрузка данных
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 AppForm(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.pat_dd = ft.Dropdown(label="Пациент")
self.doctor_dd = ft.Dropdown(label="Доктор")
self.service_dd = ft.Dropdown(label="Услуга")
self.status_dd = ft.Dropdown(label="Статус")
self.date_f = ft.TextField(label="Дата", read_only=True, on_click=lambda e: e.page.show_dialog(self.date_pick))
def handle_date(e: ft.Event[ft.DatePicker]):
self.date_f.value = (e.data.date() + dt.timedelta(days=1)).strftime("%d.%m.%Y")
self.date_pick = ft.DatePicker(on_change=handle_date)
self.time_f = ft.TextField(label="Время", read_only=True, on_click=lambda e: e.page.show_dialog(self.time_pick))
def handle_time(e: ft.Event[ft.TimePicker]):
self.time_f.value = e.data.strftime("%H:%M")
self.time_pick = ft.TimePicker(on_change=handle_time)
self.is_paid_cb = ft.Checkbox(label="Оплачен?")
self.photo = ft.Image(src="pictures/1.jpg")
self.photo_text = ft.Text("pictures/1.jpg")
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):
photo_cont = ft.Container(
content=self.photo,
width=150,
height=150,
on_click=self.pick_image
)
pats = session.scalars(select(Patient))
self.pat_dd.options = [
ft.Dropdown(text=p.name, key=p.id) for p in pats
]
pats = session.scalars(select(Doctor))
self.doctor_dd.options = [
ft.Dropdown(text=p.name, key=p.id) for p in pats
]
pats = session.scalars(select(Service))
self.service_dd.options = [
ft.Dropdown(text=p.name, key=p.id) for p in pats
]
pats = session.scalars(select(AppStatus))
self.status_dd.options = [
ft.Dropdown(text=p.name, key=p.id) for p in pats
]
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.doctor_dd, self.pat_dd, self.service_dd, self.status_dd, self.date_f, self.time_f, self.is_paid_cb, photo_cont, self.photo_text, save_btn]
if self.mode == "edit":
self.build_edit()
res.append(del_btn)
return res
def build_edit(self):
pass
a = session.get(Appointment, self.aid)
self.pat_dd.value = a.patient_id
self.doctor_dd.value = a.doctor_id
self.service_dd.value = a.service_id
self.status_dd.value = a.app_status_id
self.date_f.value = a.date.strftime("%d.%m.%Y")
self.date_pick.value = a.date
self.time_f.value = a.app_time.strftime("%H:%M")
self.time_pick.value = a.app_time
self.is_paid_cb.value = True
self.photo.src = a.photo
self.photo_text.value = a.photo
async def pick_image(self):
file = await ft.FilePicker().pick_files(file_type=ft.FilePickerFileType.IMAGE)
if file:
new_path = f"pictures/{file[0].name}"
shutil.copy(file[0].path, new_path)
self.photo.src = new_path
self.photo_text.value = new_path
def save(self):
if self.mode == "add":
a = Appointment()
session.add(a)
else:
a = session.get(Appointment, self.aid)
pat = self.pat_dd.value
doctor = self.doctor_dd.value
service = self.service_dd.value
status = self.status_dd.value
date_ = self.date_pick.value
time_pick = self.time_pick.value
is_paid = self.is_paid_cb.value
photo = self.photo.src
if None in [pat, doctor, service, status, date_, time_pick, is_paid, photo]:
self.alert.content = ft.Text("Введите все данные")
self.page.show_dialog(self.alert)
return
try:
a.patient_id = pat
a.doctor_id = doctor
a.service_id = service
a.app_status_id = status
a.date = date_
a.app_time = time_pick
a.is_paid = int(is_paid)
a.photo = photo
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():
a = session.get(Appointment, self.aid)
session.delete(a)
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_clicl=lambda e: e.page.pop_dialog())
]
)
self.page.show_dialog(delete_dlg)
class AppView(ft.View):
def __init__(self, page: ft.Page):
super().__init__()
self._page = page
self.route = "/app"
self.scroll = ft.ScrollMode.ALWAYS
self.user_id = self._page.session.store.get("id")
self.user_role = self._page.session.store.get("role")
self.app_list = ft.Column()
self.search_f = ft.TextField(label="Поиск", icon=ft.Icons.SEARCH, on_change=self.build_list)
self.spec_dd = ft.Dropdown(label="Специализация", on_select=self.build_list)
self.sort_desc = None
self.sort_btn = ft.Button("Сортировка по дате", on_click=self.sort)
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 = "Гость"
specs = session.scalars(select(Specialization))
self.spec_dd.options = [
ft.DropdownOption(text="Все", key="all"),
*[ft.DropdownOption(text=s.name, key=s.id) for s in specs]
]
head = Header(u, self.user_role)
title = ft.Text("Записи", size=24)
row = ft.Row(
controls=[
self.spec_dd, self.search_f, self.sort_btn
],
spacing=40,
)
if self.user_role == "Администратор":
row.controls.append(ft.Button("Добавить", on_click=self.build_add))
row.controls.append(ft.Button("Доктор", on_click=lambda e: e.page.go("/doctor")))
back_btn = ft.Button("Назад", on_click=lambda e: e.page.go("/login"))
res = [head, title, back_btn, self.app_list]
if self.user_role in ["Регистратор", "Администратор"]:
res.insert(3, row)
return res
def build_list(self):
stmt = select(Appointment).join(Appointment.patient).join(Appointment.doctor).join(Appointment.service).join(Appointment.app_status)
if self.search_f.value is not None and self.search_f.value != "":
search = self.search_f.value.strip().lower()
stmt = stmt.where(
or_(
Patient.name.contains(search),
Doctor.name.contains(search),
Service.name.contains(search),
AppStatus.name.contains(search),
cast(Appointment.date, String).contains(search)
)
)
if self.sort_desc is not None:
if self.sort_desc:
stmt = stmt.order_by(Appointment.date.desc())
else:
stmt = stmt.order_by(Appointment.date.asc())
if self.spec_dd.value is not None and self.spec_dd.value != "all":
stmt = stmt.join(Appointment.doctor).where(Doctor.specialization_id == self.spec_dd.value)
try:
self.app_list.controls.clear()
apps = session.scalars(stmt)
for a in apps:
photo = ft.Image(src=a.photo)
photo_cont = ft.Container(
content=photo,
padding=ft.Padding.all(5),
border=ft.Border.all(2, ft.Colors.BLACK),
width=150,
height=150,
)
text_cont = ft.Container(
content=ft.Text(
f"{a.patient.name}\n"
f"{a.doctor.name}\n"
f"{a.service.name}\n"
f"{a.date}\n"
f"{a.app_time}\n"
f"{a.app_status.name}\n"
),
expand=True,
border=ft.Border.all(2, '#000000')
)
is_paid = "Оплачено" if a.is_paid == 1 else "Неоплачено"
is_paid_cont = ft.Container(
content=ft.Text(f"{is_paid}"),
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=[
photo_cont, text_cont, is_paid_cont
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
),
border=ft.Border.all(1, ft.Colors.BLACK),
padding=ft.Padding.all(5)
)
if self.user_role == "Администратор":
ctrl.on_click = lambda e, aid=a.id: self.build_edit(aid)
if a.app_status_id == 3:
ctrl.bgcolor = ft.Colors.GREY
if a.patient.is_vip:
ctrl.bgcolor = "#2e8b57"
self.app_list.controls.append(ctrl)
self.page.update()
except Exception as e:
print(e)
def build_add(self):
add_dialog = ft.AlertDialog(
title="Добавление",
content=AppForm("add", self.build_list),
)
self.page.show_dialog(add_dialog)
def build_edit(self, aid):
edit_dlg = ft.AlertDialog(
title=f"Редактириование товара {aid}",
content=AppForm("edit", self.build_list, aid),
)
self.page.show_dialog(edit_dlg)
def sort(self):
if self.sort_btn.icon is None:
self.sort_btn.icon = ft.Icons.ARROW_UPWARD
self.sort_desc = True
elif self.sort_btn.icon == ft.Icons.ARROW_UPWARD:
self.sort_btn.icon = ft.Icons.ARROW_DOWNWARD
self.sort_desc = False
else:
self.sort_btn.icon = None
self.sort_desc = None
self.build_list()
self.page.update()