/
livi
/
gitExample
Обзор
Документация
Войти
/
livi
/
gitExample
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
test-branch
src/main/py/main.py
504 строки
32 KB
Ivan Ivanovski
5 лаба + изменения
15 ноя 2025, 09:07
15 ноя 2025, 09:07
8746420
Код
Авторство
О чём код?
import sys # Импорт модуля sys для работы с системными параметрами import os # Импорт модуля os для работы с операционной системой import json # Импорт модуля json для работы с JSON-форматом import csv # Импорт модуля csv для работы с CSV-файлами import xml.etree.ElementTree as ET # Импорт модуля для работы с XML import yaml # Импорт модуля yaml для работы с YAML-форматом from datetime import datetime # Импорт datetime для работы с датой и временем # Исправленный путь - добавление пути к проекту в sys.path для импорта модулей sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))) # Импорт функций из репозитория from src.repository.repository import ( list_clients, list_dishes, list_cooks, list_statuses, # Функции для получения списков add_order, get_all_orders, get_order_by_id, delete_order, update_status, # Функции работы с заказами reset_session_data, mark_order_as_ready, mark_order_as_completed, # Функции управления статусами get_orders_by_status, get_revenue_report, mark_order_as_awaiting_pickup # Функции отчетности и статусов ) # Словарь с паролями для разных ролей PASSWORDS = { "client": "client123", # Пароль для клиента "cook": "cook123" # Пароль для повара } def create_output_folder(): # Создание пути к папке out out_path = os.path.join(os.path.dirname(__file__), 'out') # Создание папки, если она не существует if not os.path.exists(out_path): os.makedirs(out_path) return out_path # Возврат пути к папке def export_dish_data(): # Получение данных о блюдах dishes_data = list_dishes() # Создание списка для хранения данных о блюдах dishes_list = [] # Цикл по всем блюдам for dish in dishes_data: # Добавление информации о блюде в список dishes_list.append({ 'Dish_ID': dish['Dish_ID'], # ID блюда 'Title': dish['Title'], # Название блюда 'Price': dish['Price'], # Цена блюда 'Quantity': dish['Quantity'] # Количество блюда }) # Создание папки для экспорта out_path = create_output_folder() # Экспорт в JSON with open(os.path.join(out_path, 'data.json'), 'w', encoding='utf-8') as f: json.dump(dishes_list, f, ensure_ascii=False, indent=2) # Запись данных в JSON-файл # Экспорт в CSV with open(os.path.join(out_path, 'data.csv'), 'w', encoding='utf-8', newline='') as f: if dishes_list: # Проверка, что список не пустой writer = csv.DictWriter(f, fieldnames=dishes_list[0].keys()) # Создание writer с заголовками writer.writeheader() # Запись заголовков writer.writerows(dishes_list) # Запись данных # Экспорт в XML root = ET.Element('dishes') # Создание корневого элемента for dish in dishes_list: # Цикл по всем блюдам dish_elem = ET.SubElement(root, 'dish') # Создание элемента для блюда for key, value in dish.items(): # Цикл по полям блюда child = ET.SubElement(dish_elem, key) # Создание дочернего элемента child.text = str(value) # Установка текста элемента # Функция для форматирования XML с отступами def indent(elem, level=0): i = "\n" + level * " " # Создание отступа if len(elem): # Если у элемента есть дочерние элементы if not elem.text or not elem.text.strip(): # Если нет текста elem.text = i + " " # Установка отступа if not elem.tail or not elem.tail.strip(): # Если нет хвостового текста elem.tail = i # Установка хвостового отступа for elem in elem: # Рекурсивный вызов для дочерних элементов indent(elem, level + 1) if not elem.tail or not elem.tail.strip(): # Если нет хвостового текста elem.tail = i # Установка хвостового отступа else: # Если нет дочерних элементов if level and (not elem.tail or not elem.tail.strip()): # Если нужен отступ elem.tail = i # Установка хвостового отступа indent(root) # Применение форматирования к корневому элементу tree = ET.ElementTree(root) # Создание XML-дерева tree.write(os.path.join(out_path, 'data.xml'), encoding='utf-8', xml_declaration=True) # Запись XML-файла # Экспорт в YAML with open(os.path.join(out_path, 'data.yaml'), 'w', encoding='utf-8') as f: yaml_data = { 'dishes': dishes_list # Структура данных для YAML } yaml.dump(yaml_data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) # Запись YAML-файла # Вывод информации об экспорте print("Данные таблицы Dish экспортированы в папку out:") print("- data.json") # JSON файл print("- data.csv") # CSV файл print("- data.xml") # XML файл print("- data.yaml") # YAML файл def authenticate_user(): print("=== Система учёта заказов кафе ===") # Заголовок системы while True: # Бесконечный цикл для выбора роли print("\nВыберите роль:") # Меню выбора роли print("1 - Клиент") # Опция клиента print("2 - Повар") # Опция повара print("3 - Экспорт данных Dish") # Опция экспорта print("0 - Выход") # Опция выхода choice = input("Ваш выбор: ").strip() # Ввод выбора пользователя if choice == "1": # Если выбран клиент return authenticate_with_password("client") # Авторизация клиента elif choice == "2": # Если выбран повар return authenticate_with_password("cook") # Авторизация повара elif choice == "3": # Если выбран экспорт export_dish_data() # Вызов функции экспорта continue # Продолжение цикла elif choice == "0": # Если выбран выход reset_session_data() # Сброс данных сессии return None # Возврат None для выхода else: # Если неверный выбор print("Неверный выбор. Попробуйте снова.") # Сообщение об ошибке def authenticate_with_password(role): attempts = 3 # Количество попыток ввода пароля while attempts > 0: # Цикл пока есть попытки password = input(f"Введите пароль для {role}: ") # Ввод пароля if password == PASSWORDS[role]: # Проверка пароля print(f"Успешная авторизация! Добро пожаловать, {role}!") # Сообщение об успехе return role # Возврат роли else: # Если пароль неверный attempts -= 1 # Уменьшение количества попыток print(f"Неверный пароль. Осталось попыток: {attempts}") # Сообщение об ошибке print("Доступ запрещен. Слишком много неудачных попыток.") # Сообщение о блокировке return None # Возврат None при неудаче def print_client_menu(): print("\n=== Меню клиента ===") # Заголовок меню клиента print("1 - Добавить заказ") # Опция добавления заказа print("2 - Удалить заказ") # Опция удаления заказа print("3 - Просмотреть мои заказы") # Опция просмотра заказов print("4 - Забрать заказ") # Опция получения заказа print("0 - Выход") # Опция выхода def print_cook_menu(): print("\n=== Меню повара ===") # Заголовок меню повара print("1 - Просмотреть все заказы") # Опция просмотра всех заказов print("2 - Просмотреть заказ по ID") # Опция просмотра заказа по ID print("3 - Отметить заказы как готовые") # Опция отметки готовности print("4 - Просмотреть отчетность") # Опция просмотра отчетов print("0 - Выход") # Опция выхода def main_loop(role): if role == "client": # Если роль клиент client_loop() # Запуск цикла клиента elif role == "cook": # Если роль повар cook_loop() # Запуск цикла повара def client_loop(): while True: # Бесконечный цикл меню клиента print_client_menu() # Вывод меню клиента choice = input("Выберите опцию: ").strip() # Ввод выбора if choice == "1": # Если выбрано добавление заказа prompt_add_order() # Вызов функции добавления заказа elif choice == "2": # Если выбрано удаление заказа prompt_delete_order() # Вызов функции удаления заказа elif choice == "3": # Если выбран просмотр заказов prompt_view_client_orders() # Вызов функции просмотра заказов elif choice == "4": # Если выбрано получение заказа prompt_pickup_order() # Вызов функции получения заказа elif choice == "0": # Если выбран выход print("Выход...") # Сообщение о выходе break # Выход из цикла else: # Если неверный выбор print("Неверный выбор.") # Сообщение об ошибке def cook_loop(): while True: # Бесконечный цикл меню повара print_cook_menu() # Вывод меню повара choice = input("Выберите опцию: ").strip() # Ввод выбора if choice == "1": # Если выбран просмотр всех заказов prompt_list_all_orders() # Вызов функции просмотра заказов elif choice == "2": # Если выбран просмотр заказа по ID prompt_view_one_order() # Вызов функции просмотра заказа elif choice == "3": # Если выбрана отметка готовности prompt_mark_orders_ready() # Вызов функции отметки готовности elif choice == "4": # Если выбран просмотр отчетов prompt_view_reports() # Вызов функции просмотра отчетов elif choice == "0": # Если выбран выход print("Выход...") # Сообщение о выходе break # Выход из цикла else: # Если неверный выбор print("Неверный выбор.") # Сообщение об ошибке def choose_from_list(rows, id_field, label_fields): if not rows: # Если список пустой print("Список пуст.") # Сообщение о пустом списке return None # Возврат None for r in rows: # Цикл по строкам label = " ".join(str(r[f]) for f in label_fields) # Создание метки print(f"{r[id_field]}: {label}") # Вывод элемента списка try: # Обработка исключений chosen = int(input("Введите ID из списка (или 0 для отмены): ").strip()) # Ввод выбора except ValueError: # Если введено не число print("Неверный ввод.") # Сообщение об ошибке return None # Возврат None if chosen == 0: # Если выбран отмена return None # Возврат None for r in rows: # Поиск выбранного элемента if r[id_field] == chosen: # Если ID совпадает return chosen # Возврат выбранного ID print("ID не найден.") # Сообщение если ID не найден return None # Возврат None def choose_client_with_budget(rows): if not rows: # Если список клиентов пустой print("Список клиентов пуст.") # Сообщение о пустом списке return None # Возврат None for r in rows: # Цикл по клиентам print(f"{r['Client_ID']}: {r['Name']} {r['Surname']} (Бюджет: {r['Budget']} руб.)") # Вывод информации о клиенте try: # Обработка исключений chosen = int(input("Введите ID клиента (или 0 для отмена): ").strip()) # Ввод выбора клиента except ValueError: # Если введено не число print("Неверный ввод.") # Сообщение об ошибке return None # Возврат None if chosen == 0: # Если выбран отмена return None # Возврат None for r in rows: # Поиск клиента if r['Client_ID'] == chosen: # Если ID совпадает return chosen # Возврат ID клиента print("ID клиента не найден.") # Сообщение если клиент не найден return None # Возврат None def prompt_add_order(): print("\n=== Добавление заказа ===") # Заголовок добавления заказа clients = list_clients() # Получение списка клиентов client_id = choose_client_with_budget(clients) # Выбор клиента if client_id is None: # Если клиент не выбран print("Отменено.") # Сообщение об отмене return # Выход из функции cook_id = 1 # ID повара по умолчанию dishes = list_dishes() # Получение списка блюд if not dishes: # Если меню пустое print("Меню пустое. Добавьте блюда в таблицу Dish.") # Сообщение об ошибке return # Выход из функции all_dish_items = [] # Список для хранения выбранных блюд while True: # Цикл выбора блюд print("Выберите блюда для заказа. Введите несколько записей через запятую в формате dish_id:quantity") # Инструкция print("Доступные блюда:") # Заголовок списка блюд for d in dishes: # Цикл по блюдам print(f"{d['Dish_ID']}: {d['Title']} (цена={d['Price']} руб., в наличии={d['Quantity']} шт.)") # Информация о блюде raw = input("Пример ввода: 1:2,3:1 -> ").strip() # Ввод блюд if not raw: # Если ввод пустой print("Отменено.") # Сообщение об отмене return # Выход из функции try: # Обработка исключений parts = [p.strip() for p in raw.split(",") if p.strip()] # Разделение ввода на части current_items = [] # Временный список для текущих блюд for p in parts: # Цикл по частям did, qty = p.split(":") # Разделение на ID и количество current_items.append((int(did), int(qty))) # Добавление в список all_dish_items.extend(current_items) # Добавление блюд в общий список add_more = input("\nДобавить еще блюда в заказ? (да/нет): ").strip().lower() # Вопрос о добавлении if add_more not in ['да', 'д', 'yes', 'y']: # Если не нужно добавлять break # Выход из цикла except Exception as e: # Обработка ошибок print("Ошибка парсинга списка блюд. Формат dish_id:quantity,...") # Сообщение об ошибке continue # Продолжение цикла if not all_dish_items: # Если не выбрано ни одного блюда print("Не выбрано ни одного блюда.") # Сообщение об ошибке return # Выход из функции try: # Обработка исключений order_id = add_order(client_id, all_dish_items, cook_id) # Добавление заказа # АВТОМАТИЧЕСКИ МЕНЯЕМ СТАТУС НА "ПЕРЕДАН НА КУХНЮ" update_status(order_id, 2) # Обновление статуса заказа print(f"Заказ {order_id} передан на кухню! Статус изменен на 'передан на кухню'") # Сообщение # ФОРМИРУЕМ СЧЕТ order_info = get_order_by_id(order_id) # Получение информации о заказе total_cost = sum(d['Price'] * d['Quantity'] for d in order_info['dishes']) # Расчет общей стоимости client_info = None # Переменная для информации о клиенте for client in clients: # Поиск клиента if client['Client_ID'] == client_id: # Если ID совпадает client_info = client # Сохранение информации о клиенте break # Выход из цикла print("\n=== Заказ создан и оплачен ===") # Заголовок счета print(f"ID заказа: {order_id}") # ID заказа print(f"Дата формирования: {order_info.get('Date_of_formation')}") # Дата формирования print(f"Время формирования: {order_info.get('Formation_time')}") # Время формирования if client_info: # Если есть информация о клиенте print(f"Клиент: {client_info['Name']} {client_info['Surname']} (ID: {client_id})") # Информация о клиенте print(f"Статус заказа: {order_info.get('StatusTitle')}") # Статус заказа print("=== СЧЕТ ===") # Заголовок счета for d in order_info['dishes']: # Цикл по блюдам заказа print(f" - {d['Title']} x{d['Quantity']} - {d['Price'] * d['Quantity']} руб.") # Информация о блюде print(f"ИТОГО: {total_cost} руб.") # Общая стоимость print("=============") # Конец счета except ValueError as e: # Обработка ошибок значения print(f"Ошибка: {e}") # Вывод ошибки except Exception as e: # Обработка других ошибок print(f"Произошла непредвиденная ошибка: {e}") # Вывод ошибки def prompt_list_all_orders(): print("\n=== Все заказы ===") # Заголовок списка заказов orders = get_all_orders() # Получение всех заказов if not orders: # Если заказов нет print("Заказов нет.") # Сообщение return # Выход из функции for o in orders: # Цикл по заказам print("-" * 40) # Разделитель print( f"Order_ID: {o['Order_ID']} | Клиент: {o.get('ClientName')} {o.get('ClientSurname')} | Статус: {o.get('StatusTitle')}") # Информация о заказе print( f"Дата формирования: {o.get('Date_of_formation')} | Время: {o.get('Formation_time')} | Повар: {o.get('CookName') or '-'}") # Дополнительная информация print("Блюда:") # Заголовок списка блюд for d in o['dishes']: # Цикл по блюдам заказа print(f" - {d['Dish_ID']} {d['Title']} x{d['Quantity']} (цена {d['Price']} руб.)") # Информация о блюде print("-" * 40) # Разделитель def prompt_view_one_order(): try: # Обработка исключений oid = int(input("Введите Order_ID для просмотра: ").strip()) # Ввод ID заказа except ValueError: # Если введено не число print("Неверный ввод.") # Сообщение об ошибке return # Выход из функции o = get_order_by_id(oid) # Получение заказа по ID if not o: # Если заказ не найден print("Заказ не найден.") # Сообщение return # Выход из функции print(f"Order_ID: {o['Order_ID']}") # ID заказа print(f"Клиент: {o.get('ClientName')} {o.get('ClientSurname')} (ID {o.get('Client_ID')})") # Информация о клиенте print(f"Статус: {o.get('StatusTitle')} (ID {o.get('Status')})") # Статус заказа print(f"Повар: {o.get('CookName')} {o.get('CookSurname')} (ID {o.get('Cook_ID')})") # Информация о поваре print(f"Дата формирования: {o.get('Date_of_formation')}") # Дата формирования print(f"Время формирования: {o.get('Formation_time')}") # Время формирования print("Блюда:") # Заголовок списка блюд for d in o['dishes']: # Цикл по блюдам print(f" - {d['Dish_ID']} {d['Title']} x{d['Quantity']} (цена {d['Price']} руб.)") # Информация о блюде def prompt_delete_order(): try: # Обработка исключений oid = int(input("Введите Order_ID для удаления: ").strip()) # Ввод ID заказа для удаления except ValueError: # Если введено не число print("Неверный ввод.") # Сообщение об ошибке return # Выход из функции ok = delete_order(oid) # Удаление заказа if ok: # Если удаление успешно print("Заказ удалён.") # Сообщение об успехе else: # Если удаление не удалось print("Заказ не найден или не удалось удалить.") # Сообщение об ошибке def prompt_mark_orders_ready(): print("\n=== Отметить заказы как готовые ===") # Заголовок функции # Показываем только заказы со статусом "передан на кухню" orders = get_orders_by_status(2) # 2 = "передан на кухню" - получение заказов по статусу if not orders: # Если заказов нет print("Нет заказов для приготовления.") # Сообщение return # Выход из функции print("Заказы для приготовления:") # Заголовок списка заказов for o in orders: # Цикл по заказам print(f"Order_ID: {o['Order_ID']} | Клиент: {o.get('ClientName')}") # Информация о заказе try: # Обработка исключений order_ids_input = input("Введите ID заказов для отметки как готовые (через запятую): ").strip() # Ввод ID заказов if not order_ids_input: # Если ввод пустой print("Отменено.") # Сообщение об отмене return # Выход из функции order_ids = [int(oid.strip()) for oid in order_ids_input.split(",")] # Разделение ввода на список ID for order_id in order_ids: # Цикл по ID заказов # УБРАТЬ этот вызов - он устанавливает статус 3 ("готов") # mark_order_as_ready(order_id) # ОСТАВИТЬ только этот - устанавливает статус 4 ("ожидает получения") mark_order_as_awaiting_pickup(order_id) # Установка статуса "ожидает получения" print(f"Заказы {order_ids} отмечены как готовые! Статус изменен на 'ожидает получения'") # Сообщение об успехе print("Клиенты уведомлены о готовности заказов!") # Дополнительное сообщение except ValueError: # Обработка ошибки значения print("Неверный формат ввода. Введите числа через запятую.") # Сообщение об ошибке except Exception as e: # Обработка других ошибок print(f"Ошибка: {e}") # Вывод ошибки def prompt_pickup_order(): print("\n=== Забрать заказ ===") # Заголовок функции try: # Обработка исключений order_id = int(input("Введите ID заказа для получения: ").strip()) # Ввод ID заказа except ValueError: # Если введено не число print("Неверный ввод.") # Сообщение об ошибке return # Выход из функции order = get_order_by_id(order_id) # Получение заказа по ID if not order: # Если заказ не найден print("Заказ не найден.") # Сообщение return # Выход из функции # Проверяем, что заказ ожидает получения if order.get('Status') != 4: # 4 = "ожидает получения" - проверка статуса print("Этот заказ еще не готов к выдаче или уже получен.") # Сообщение return # Выход из функции mark_order_as_completed(order_id) # Отметка заказа как полученного print(f"Заказ {order_id} получен! Статус изменен на 'получен'") # Сообщение об успехе def prompt_view_client_orders(): print("\n=== Мои заказы ===") # Заголовок функции clients = list_clients() # Получение списка клиентов client_id = choose_client_with_budget(clients) # Выбор клиента if client_id is None: # Если клиент не выбран print("Отменено.") # Сообщение об отмене return # Выход из функции orders = get_all_orders() # Получение всех заказов client_orders = [o for o in orders if o.get('Client_ID') == client_id] # Фильтрация заказов клиента if not client_orders: # Если заказов нет print("У вас нет заказов.") # Сообщение return # Выход из функции for o in client_orders: # Цикл по заказам клиента print("-" * 30) # Разделитель print(f"Order_ID: {o['Order_ID']} | Статус: {o.get('StatusTitle')}") # Информация о заказе print(f"Дата: {o.get('Date_of_formation')} | Время: {o.get('Formation_time')}") # Дата и время print("Блюда:") # Заголовок списка блюд for d in o['dishes']: # Цикл по блюдам print(f" - {d['Title']} x{d['Quantity']}") # Информация о блюде if o.get('StatusTitle') == 'ожидает получения': # Если заказ готов к получению print("✅ ЗАКАЗ ГОТОВ К ПОЛУЧЕНИЮ!") # Сообщение print("-" * 30) # Разделитель def prompt_view_reports(): print("\n=== Отчетность ===") # Заголовок отчетности report = get_revenue_report() # Получение отчета print(f"Общее количество заказов: {report['total_orders']}") # Количество заказов print(f"Общая выручка: {report['total_revenue']:.2f} руб.") # Выручка print("\nЗаказы по статусам:") # Заголовок статистики по статусам for status, count in report['status_counts'].items(): # Цикл по статусам print(f" - {status}: {count}") # Вывод статистики if __name__ == "__main__": # Точка входа в программу try: # Обработка исключений while True: # Бесконечный цикл user_role = authenticate_user() # Авторизация пользователя if user_role is None: # Если пользователь вышел break # Выход из цикла main_loop(user_role) # Запуск основного цикла для роли except KeyboardInterrupt: # Обработка прерывания клавиатурой print("\n\nПрервано пользователем.") # Сообщение reset_session_data() # Сброс данных сессии print("Все данные восстановлены!") # Сообщение sys.exit(0) # Выход из программы