Compare commits

...

23 Commits

Author SHA1 Message Date
Сергей Ванюшкин 8189aaedd4 fix: Поправил TypeHints и убраз неиспользуемые сущности 2024-02-14 15:34:24 +03:00
Сергей Ванюшкин 5ef6aaeb6f маленькие правки 2024-02-13 13:09:09 +03:00
Сергей Ванюшкин f75415d9d9 Удаление блюда 2024-02-13 12:38:13 +03:00
Сергей Ванюшкин 4c3779776d Readme 2024-02-13 02:44:24 +03:00
Сергей Ванюшкин d54e704dfb fix: volumes не примонтировал 2024-02-13 00:02:22 +03:00
Сергей Ванюшкин 68594eb7f0 слияние веток 2024-02-12 23:52:21 +03:00
Сергей Ванюшкин 8bfa166987 слияние веток 2024-02-12 23:09:50 +03:00
Сергей Ванюшкин e0a81cf126 google sheets docker образ 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин a4f8bce657 google синхронизация 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 9ba42aae9f upd фоновая задача теперь не дропает базу 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин afdf1c5e2b fix 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 74c0ccae2a fix 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 2c48529a02 fix 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин cedf27a04d fix 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин e0798de713 fix 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 5a133a05e1 fix 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 3df3c67e7c fix: правка урла кролика 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин a0ebe9bdb9 upd: Контейнеры для celery & rabbitmq 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин ed3d7d9352 upd Разнес тесты, уменьшив портянку
upd Тест для summary роута
2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 3dbefda936 upd: Применение скидки в выводе API 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 5a95b06300 upd: Добавил bg_task xlsx>>DBase 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин ebe75b6dc3 upd: Добавил роут summary с выводом вмего меню со вложением 2024-02-12 23:09:01 +03:00
Сергей Ванюшкин 3120910552 Fix .env для локального запуска 2024-02-07 12:44:42 +03:00
17 changed files with 97 additions and 111 deletions

View File

View File

@ -5,29 +5,50 @@ Fastapi веб приложение реализующее api для общеп
Данный проект, это результат выполнения практических домашних заданий интенсива от YLAB Development. Проект реализован на фреймворке fastapi, с использованием sqlalchemy. В качестве базы данных используется postgresql.
## Техническое задание
### Спринт 3 - Паттерны и принципы разработки
### Спринт 4 - Многопроцессорность, асинхронность
В этом домашнем задании необходимо:
1.Переписать текущее FastAPI приложение на асинхронное выполнение
2.Добавить в проект фоновую задачу с помощью Celery + RabbitMQ.
3.Добавить эндпоинт (GET) для вывода всех меню со всеми связанными подменю и со всеми связанными блюдами.
4.Реализовать инвалидация кэша в background task (встроено в FastAPI)
5.* Обновление меню из google sheets раз в 15 сек.
6.** Блюда по акции. Размер скидки (%) указывается в столбце G файла Menu.xlsx
1.Вынести бизнес логику и запросы в БД в отдельные слои приложения.
Фоновая задача: синхронизация Excel документа и БД.
В проекте создаем папку admin. В эту папку кладем файл Menu.xlsx (будет прикреплен к ДЗ). Не забываем запушить в гит.
При внесении изменений в файл все изменения должны отображаться в БД. Периодичность обновления 15 сек. Удалять БД при каждом обновлении нельзя.
2.Добавить кэширование запросов к API с использованием Redis. Не забыть про инвалидацию кэша.
3.Добавить pre-commit хуки в проект. Файл yaml будет прикреплен к ДЗ.
4.Покрыть проект type hints (тайпхинтами)
5.* Описать ручки API в соответствий c OpenAPI
6.** Реализовать в тестах аналог Django reverse() для FastAPI
Требования:
●Код должен проходить все линтеры.
●Код должен соответствовать принципам SOLID, DRY, KISS.
●Проект должен запускаться по одной команде (докер).
●Проект должен проходить все Postman тесты (коллекция с Вебинара №1).
●Тесты написанные вами после Вебинара №2, должны быть актуальны, запускать и успешно проходить
●Данные меню, подменю, блюд для нового эндпоинта должны доставаться одним ORM-запросом в БД (использовать подзапросы и агрегирующие функций SQL).
●Проект должен запускаться одной командой
●Проект должен соответствовать требованиям всех предыдущих вебинаров. (Не забыть добавить тесты для нового API эндпоинта)
### Выполненные доп задания со *
Спринт 2
3.* Реализовать вывод количества подменю и блюд для Меню через один (сложный) ORM запрос.
`./fastfood/repository/menu.py` Метод `get_menu_item`
4.** Реализовать тестовый сценарий «Проверка кол-ва блюд и подменю в меню» из Postman с помощью pytest
`./tests/test_postman.py`
Спринт 3
5.* Описать ручки API в соответствий c OpenAPI
'./openapi.json'
6.** Реализовать в тестах аналог Django reverse() для FastAPI
'./tests/urls.py'
Спринт 4
5.* Обновление меню из google sheets раз в 15 сек.
`./bg_tasks/` Реализовано чтение как локальной, так и удаленной таблицы.
В зависимости какой compose поднять, тот и будет использоваться
6.** Блюда по акции. Размер скидки (%) указывается в столбце G файла Menu.xlsx
`./fastfood/service/dish.py`, метод _get_discont, подменяет сумму в выдаче,
скидка хранится в REDIS под ключами вида DISCONT:{UUID блюда}
Дополнительно:
Контейнеры с проектом и с тестами запускаются разными командами.
## Зависимости
- docker
@ -43,8 +64,12 @@ Fastapi веб приложение реализующее api для общеп
Запуск/остановка образов:
- Запуск FAstAPI приложения
> `$ docker-compose -f compose_app.yml up `
- Запуск FAstAPI приложения c локальным файлом для фоновой задачи
> `$ docker-compose -f compose_app.yml up`
- Запуск FAstAPI приложения c Google Sheets для фоновой задачи
> `$ docker-compose -f compose_google.yml up`
(ЧИТАЙТЕ СООБЩЕНИЕ В ЧАТЕ)
После успешного запуска образов документация по API будет доступна по адресу <a href="http://localhost:8000/docs">http://localhost:8000</a>

Binary file not shown.

View File

@ -1,4 +1,5 @@
import os
from typing import Any
import gspread
import openpyxl
@ -43,7 +44,9 @@ async def local_xlsx_to_rows() -> list[list[str | int | float]]:
return data
async def rows_to_dict(rows: list[list]) -> tuple:
async def rows_to_dict(
rows: list[list],
) -> tuple[dict[int, Any], dict[Any, Any], dict[Any, Any]]:
"""Парсит строки полученные и источников в словарь"""
menus = {}

View File

@ -1,5 +1,6 @@
import os
import pickle
from typing import Any
import redis.asyncio as redis # type: ignore
from sqlalchemy import delete, update
@ -45,7 +46,8 @@ async def is_changed_xls() -> bool:
async def on_menu_change(
new_menu: dict, old_menu: dict, session: AsyncSession
) -> dict | None:
) -> dict[str, Any]:
"""Изменение, удаление или создание меню"""
if new_menu and not old_menu:
# Создаем меню
menu = Menu(
@ -55,6 +57,7 @@ async def on_menu_change(
session.add(menu)
await session.flush()
new_menu['id'] = str(menu.id)
elif new_menu and old_menu:
# Обновляем меню
await session.execute(
@ -67,10 +70,6 @@ async def on_menu_change(
await session.execute(delete(Menu).where(Menu.id == old_menu['id']))
await session.commit()
# Чистим кэш
await clear_cache('MENUS*')
await clear_cache('summary')
return new_menu
@ -108,9 +107,9 @@ async def menus_updater(menus: dict, session: AsyncSession) -> None:
async def on_submenu_change(
new_sub: dict, old_sub: dict, session: AsyncSession
) -> dict:
) -> dict[str, Any]:
if new_sub and not old_sub:
# Создаем меню
# Создаем подменю
submenu = SubMenu(
title=new_sub['data']['title'],
description=new_sub['data']['description'],
@ -121,8 +120,9 @@ async def on_submenu_change(
await session.flush()
new_sub['id'] = str(submenu.id)
new_sub['parent_menu'] = str(submenu.parent_menu)
elif new_sub and old_sub:
# Обновляем меню
# Обновляем подменю
await session.execute(
update(SubMenu)
.where(SubMenu.id == old_sub['id'])
@ -132,12 +132,9 @@ async def on_submenu_change(
new_sub['parent_menu'] = old_sub['parent_menu']
else:
# Удаляем меню
# Удаляем подменю
await session.execute(delete(SubMenu).where(SubMenu.id == old_sub['id']))
await clear_cache('MENUS*')
await clear_cache('summary')
await session.commit()
return new_sub
@ -146,7 +143,7 @@ async def submenus_updater(submenus: dict, session: AsyncSession) -> None:
"""Проверяет пункты подменю на изменения
При необходимости запускае обновление БД
"""
# Получаем Меню из кэша для получения их ID по померу в таблице
# Получаем меню из кэша для получения их ID по померу в таблице
cached_menus = await redis.get('ALL_MENUS')
if cached_menus is not None:
cached_menus = pickle.loads(cached_menus)
@ -189,7 +186,9 @@ async def submenus_updater(submenus: dict, session: AsyncSession) -> None:
await redis.set('ALL_SUBMENUS', pickle.dumps(submenus))
async def on_dish_change(new_dish: dict, old_dish, session: AsyncSession) -> dict:
async def on_dish_change(
new_dish: dict, old_dish, session: AsyncSession
) -> dict[str, Any]:
if new_dish and not old_dish:
dish = Dish(
title=new_dish['data']['title'],
@ -204,7 +203,7 @@ async def on_dish_change(new_dish: dict, old_dish, session: AsyncSession) -> dic
new_dish['parent_submenu'] = str(dish.parent_submenu)
new_dish['data']['price'] = str(dish.price)
elif new_dish and old_dish:
# Обновляем меню
# Обновляем блюдо
await session.execute(
update(Dish).where(Dish.id == old_dish['id']).values(**(new_dish['data']))
)
@ -213,12 +212,9 @@ async def on_dish_change(new_dish: dict, old_dish, session: AsyncSession) -> dic
new_dish['data']['price'] = old_dish['data']['price']
else:
# Удаляем меню
# Удаляем блюдо
await session.execute(delete(Dish).where(Dish.id == old_dish['id']))
await clear_cache('MENUS*')
await clear_cache('summary')
await session.commit()
return new_dish
@ -233,7 +229,7 @@ async def dishes_updater(dishes: dict, session: AsyncSession) -> None:
else:
cached_submenus = {}
# Получаем подмен из кэша
# Получаем блюда из кэша
cached_dishes = await redis.get('ALL_DISHES')
if cached_dishes is not None:
@ -244,21 +240,21 @@ async def dishes_updater(dishes: dict, session: AsyncSession) -> None:
await clear_cache('DISCONT*')
for key in {k: cached_dishes[k] for k in set(cached_dishes) - set(dishes)}:
# Проверяем на удаленные меню
await on_submenu_change({}, cached_dishes.pop(key), session)
# Проверяем на удаленные блюда и обновляемся
await on_dish_change({}, cached_dishes.pop(key), session)
for key in dishes.keys():
parent = cached_submenus[dishes[key]['parent_num']]['id']
dishes[key]['parent_submenu'] = parent
if key not in cached_dishes.keys():
# Получаем и ставим UUID parent_menu
# Получаем и ставим UUID parent_submenu
dishes[key]['parent_submenu'] = parent
dish = await on_dish_change(dishes[key], {}, session)
dishes[key] = dish
elif key in cached_dishes.keys():
# Обновление меню
# Обновление блюда
if dishes[key].get('data') != cached_dishes[key].get('data'):
dish = await on_dish_change(dishes[key], cached_dishes[key], session)
dishes[key] = dish
@ -271,15 +267,18 @@ async def dishes_updater(dishes: dict, session: AsyncSession) -> None:
f"DISCONT:{dishes[key]['id']}", pickle.dumps(dishes[key]['discont'])
)
await redis.set('ALL_DISHES', pickle.dumps(dishes))
await redis.set('ALL_DISHES', pickle.dumps(dishes))
async def updater(rows):
async def updater(rows) -> None:
menus, submenus, dishes = await rows_to_dict(rows)
async with async_session_maker() as session:
await menus_updater(menus, session)
await submenus_updater(submenus, session)
await dishes_updater(dishes, session)
# Чистим кэш
await clear_cache('MENUS*')
await clear_cache('summary')
async def main() -> None:
@ -291,5 +290,6 @@ async def main() -> None:
async def main_gsheets() -> None:
"""Главная функция фоновой задачи для работы с Google"""
rows = await gsheets_to_rows()
await updater(rows)

View File

@ -55,6 +55,7 @@ services:
redis:
condition: service_healthy
restart: always
volumes:
- .:/usr/src/fastfood
command: /bin/bash -c 'poetry run pytest -vv'

View File

@ -1,13 +0,0 @@
{
"type": "service_account",
"project_id": "psyched-ceiling-413920",
"private_key_id": "d19492eea6a030092cf8ad767b62d7909734ccb1",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDPP2UrfDE+UOlD\nA761Jemy1IKKdIanRKXSziGvDYJ7zbY5gPFxY8Vo+9fsh1oumvROXqEH4+1LiR0J\nnUiy33R1KDOHETeP4H/FJ3u8+gHoL8wsA7SN5pIX9AR8AyBZCBjgSSp+KJchfrp/\nWN2qnFAbgp248QPvmG7/wLzBNnVsAQhQULLKqSc46hbiZ8Jt7t0ajJgOFRJSp2wP\nT5VE5k737w6b4OH8mUnhw7VK04Wk6DBmQhN1jrnxmMxmdG2hSM2zR824RIMBBs/O\n1dF+5Vkav0tgja/tVqm41Aaa2vgPRACP6bpF13YS+8C1lzw6s+7M/VdE5TH5NXRU\nvChuRknBAgMBAAECggEABmuckna0krVsawaXhLaQ30DsLf5w9hdLTvDy6CCuO9Aw\nPKb//9UNNmjMKD4rlQNY1YFS6jbxZNZRrIC7aftwQOGE2mKuIMBl6+tinuy0tLr/\nl3baS+22VZyyG36ILNrqZJ8epGm08CEsNVYRKKwS0x3aXZKFnnlnqaeYn2CUzdqa\na9iNZqrdXdRt4O7KVP7IfdNi11WuOL4epmHwBBYmCxiN0Z2KAIYvS6AcflYWtYTZ\npsBFjCQexqS37PdUyyQX9E/gKwqNZmahYwIC3vsCMCLdQQ93iODYni7LKsG0vvls\nwz03TtlMmZpMJJQGkALeqlv7jeyj+oRuqg6gjs2moQKBgQDxuDt3u1rDWhTJ50bD\nAp5T1LaiV0/+lu29ElTmYpa0RF1tlHvrndFm/MrdUjpzP4/VISmRkP3bmAgwPP6p\nYeALqQXCCGJtl44LG6D9VIOCOZxntytjLHogY8S3BLpwzKC+VMFsd56ay6wCl03S\nJEnvG10FQX8sFd+6j5qMy73OoQKBgQDbfc7hV4/r7PMaUVWFRqWjLry3dtTErxnM\nTdX30BDtuqMrm+hx0zC85ePcsbx+Zhwneyaxw2ICN5F954mJurBqs9cVaxitNSv1\nX5XjAoZqf3TevufkmSBXog6t/p4FHqAHftHYzwQvQXIINFrmT15PJkbx0lMYEYzw\nPyB7doBHIQKBgGiJi7ZpYYRw1eLH0fOOk1if+uhUqHTrYx/M6MjGRHTryBgXCkzI\n8QIAO9/hqwOirpq2/9pDgXZR1uC90EkC2jlQvPvAUokg7T5ikYpd3Y4ZSkoUjoAS\ngTK20yFvuw4DgVUvJIO7a+14PgjU1MQYC52MEPuv6sbvItX1Oxq/FnRhAoGAHWYK\ncbBSvJzuKtY+CC3gPa0i5cfq07VIVU8Pm7OosM7Q0CR/y88ntgVsscC0qJFwr/EU\ny7aJyBY9TInYqDPzMTeJVXsUwQ5gJut4ngFWk6kitDsJwFqqNFKmeLOj4repY5ee\n79U6kEHJzkOE8VgsH5nW4sjzDEQ9hmhOJ3tFz0ECgYEA8N+7yq1tK/99S8ThYW1J\n9mvUXRhAcFamBYp+8bIBdnQlrM9bGd9j8gYzQj+RBcvfCpVHFM20z8CC8oN0bitk\nh5MEjLBkw1vaywFlA/hcnA8A3g+5/IgHl03Y1tPWnyAtB77vE2M2ThklZ5l4E8eT\nP1vYw9RUSAPjtd43XDTqPNQ=\n-----END PRIVATE KEY-----\n",
"client_email": "tester@psyched-ceiling-413920.iam.gserviceaccount.com",
"client_id": "100697987276606879445",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/tester%40psyched-ceiling-413920.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

View File

@ -13,7 +13,7 @@ class DishRepository:
def __init__(self, session: AsyncSession = Depends(get_async_session)) -> None:
self.db = session
async def get_dishes(self, menu_id: UUID, submenu_id: UUID) -> list[Dish]:
async def get_dishes(self, submenu_id: UUID) -> list[Dish]:
query = select(Dish).where(
Dish.parent_submenu == submenu_id,
)
@ -22,7 +22,6 @@ class DishRepository:
async def create_dish_item(
self,
menu_id: UUID,
submenu_id: UUID,
dish_data: Dish_db,
) -> Dish:
@ -35,8 +34,6 @@ class DishRepository:
async def get_dish_item(
self,
menu_id: UUID,
submenu_id: UUID,
dish_id: UUID,
) -> Dish | None:
query = select(Dish).where(Dish.id == dish_id)
@ -45,8 +42,6 @@ class DishRepository:
async def update_dish_item(
self,
menu_id: UUID,
submenu_id: UUID,
dish_id: UUID,
dish_data: Dish_db,
) -> Dish | None:
@ -59,8 +54,6 @@ class DishRepository:
async def delete_dish_item(
self,
menu_id: UUID,
submenu_id: UUID,
dish_id: UUID,
) -> None:
query = delete(Dish).where(Dish.id == dish_id)

View File

@ -32,14 +32,13 @@ class SubMenuRepository:
await self.db.commit()
await self.db.refresh(new_submenu)
full_sub = await self.get_submenu_item(menu_id, new_submenu.id)
full_sub = await self.get_submenu_item(new_submenu.id)
if full_sub is None:
raise TypeError
return full_sub
async def get_submenu_item(
self,
menu_id: UUID,
submenu_id: UUID,
) -> SubMenu | None:
s = aliased(SubMenu)
@ -56,7 +55,6 @@ class SubMenuRepository:
async def update_submenu_item(
self,
menu_id: UUID,
submenu_id: UUID,
submenu_data: MenuBase,
) -> SubMenu | None:
@ -71,7 +69,7 @@ class SubMenuRepository:
updated_submenu = await self.db.execute(qr)
return updated_submenu.scalar_one_or_none()
async def delete_submenu_item(self, menu_id: UUID, submenu_id: UUID) -> None:
async def delete_submenu_item(self, submenu_id: UUID) -> None:
query = delete(SubMenu).where(
SubMenu.id == submenu_id,
)

View File

@ -1,3 +1,5 @@
from typing import Any
from fastapi import Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
@ -11,7 +13,7 @@ class SummaryRepository:
def __init__(self, session: AsyncSession = Depends(get_async_session)) -> None:
self.db = session
async def get_data(self):
async def get_data(self) -> list[Any]:
query = select(Menu).options(
selectinload(Menu.submenus).selectinload(SubMenu.dishes)
)

View File

@ -1,6 +1,6 @@
from uuid import UUID
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException
from fastfood.schemas import Dish, DishBase
from fastfood.service.dish import DishService
@ -19,7 +19,6 @@ async def get_dishes(
menu_id: UUID,
submenu_id: UUID,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> list[Dish]:
result = await dish.read_dishes(menu_id, submenu_id)
return result
@ -35,7 +34,6 @@ async def create_dish(
submenu_id: UUID,
dish_data: DishBase,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> Dish:
return await dish.create_dish(
menu_id,
@ -53,7 +51,6 @@ async def get_dish(
submenu_id: UUID,
dish_id: UUID,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> Dish | None:
result = await dish.read_dish(
menu_id,
@ -78,7 +75,6 @@ async def update_dish(
dish_id: UUID,
dish_data: DishBase,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> Dish:
result = await dish.update_dish(
menu_id,
@ -102,6 +98,5 @@ async def delete_dish(
submenu_id: UUID,
dish_id: UUID,
dish: DishService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> None:
await dish.del_dish(menu_id, submenu_id, dish_id)
await dish.del_dish(menu_id, dish_id)

View File

@ -1,6 +1,6 @@
from uuid import UUID
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException
from fastfood.schemas import MenuBase, MenuRead
from fastfood.service.menu import MenuService
@ -18,7 +18,6 @@ router = APIRouter(
)
async def get_menus(
menu: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> list[MenuRead]:
return await menu.read_menus()
@ -31,7 +30,6 @@ async def get_menus(
async def add_menu(
menu: MenuBase,
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> MenuRead:
return await responce.create_menu(menu)
@ -43,7 +41,6 @@ async def add_menu(
async def get_menu(
menu_id: UUID,
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> MenuRead:
result = await responce.read_menu(menu_id=menu_id)
@ -63,7 +60,6 @@ async def update_menu(
menu_id: UUID,
menu: MenuBase,
responce: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> MenuRead:
result = await responce.update_menu(
menu_id=menu_id,
@ -85,6 +81,5 @@ async def update_menu(
async def delete_menu(
menu_id: UUID,
menu: MenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> None:
await menu.del_menu(menu_id)

View File

@ -1,6 +1,6 @@
from uuid import UUID
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException
from fastfood.schemas import MenuBase, SubMenuRead
from fastfood.service.submenu import SubmenuService
@ -18,7 +18,6 @@ router = APIRouter(
async def get_submenus(
menu_id: UUID,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> list[SubMenuRead]:
result = await submenu.read_submenus(menu_id=menu_id)
return result
@ -33,7 +32,6 @@ async def create_submenu_item(
menu_id: UUID,
submenu_data: MenuBase,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> SubMenuRead:
result = await submenu.create_submenu(
menu_id=menu_id,
@ -50,7 +48,6 @@ async def get_submenu(
menu_id: UUID,
submenu_id: UUID,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> SubMenuRead:
result = await submenu.read_menu(
menu_id=menu_id,
@ -73,7 +70,6 @@ async def update_submenu(
submenu_id: UUID,
submenu_data: MenuBase,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> SubMenuRead:
result = await submenu.update_submenu(
menu_id=menu_id,
@ -96,6 +92,5 @@ async def delete_submenu(
menu_id: UUID,
submenu_id: UUID,
submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> None:
await submenu.del_menu(menu_id=menu_id, submenu_id=submenu_id)

View File

@ -1,4 +1,4 @@
from fastapi import APIRouter, BackgroundTasks, Depends
from fastapi import APIRouter, Depends
from fastfood.schemas import MenuSummary
from fastfood.service.summary import SummaryService
@ -12,6 +12,5 @@ router = APIRouter(
@router.get('/', response_model=list[MenuSummary])
async def get_summary(
sum: SummaryService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(),
) -> list[MenuSummary]:
return await sum.read_data()

View File

@ -42,7 +42,7 @@ class DishService:
if cached_dishes is not None:
return cached_dishes
data = await self.dish_repo.get_dishes(menu_id, submenu_id)
data = await self.dish_repo.get_dishes(submenu_id)
response = []
for row in data:
dish = await self._convert_dish_to_dict(row)
@ -67,7 +67,6 @@ class DishService:
) -> Dish:
dish_db = Dish_db(**dish_data.model_dump())
data = await self.dish_repo.create_dish_item(
menu_id,
submenu_id,
dish_db,
)
@ -95,7 +94,7 @@ class DishService:
if cached_dish is not None:
return cached_dish
data = await self.dish_repo.get_dish_item(menu_id, submenu_id, dish_id)
data = await self.dish_repo.get_dish_item(dish_id)
if data is None:
return None
dish = await self._convert_dish_to_dict(data)
@ -116,9 +115,7 @@ class DishService:
self, menu_id: UUID, submenu_id: UUID, dish_id, dish_data: DishBase
) -> Dish | None:
dish_db = Dish_db(**dish_data.model_dump())
data = await self.dish_repo.update_dish_item(
menu_id, submenu_id, dish_id, dish_db
)
data = await self.dish_repo.update_dish_item(dish_id, dish_db)
if data is None:
return None
@ -139,10 +136,8 @@ class DishService:
return dish
async def del_dish(self, menu_id: UUID, submenu_id: UUID, dish_id: UUID) -> None:
async def del_dish(self, menu_id: UUID, dish_id: UUID) -> None:
await self.dish_repo.delete_dish_item(
menu_id,
submenu_id,
dish_id,
)
await self.cache.delete(key=str(menu_id), bg_task=self.bg_tasks)

View File

@ -33,7 +33,7 @@ class SubmenuService:
submenus = []
for r in data:
submenu = r.__dict__
subq = await self.submenu_repo.get_submenu_item(menu_id, r.id)
subq = await self.submenu_repo.get_submenu_item(r.id)
if subq is not None:
submenu['dishes_count'] = len(subq.dishes)
submenu = SubMenuRead(**submenu)
@ -73,7 +73,7 @@ class SubmenuService:
if cached_submenu is not None:
return cached_submenu
data = await self.submenu_repo.get_submenu_item(menu_id, submenu_id)
data = await self.submenu_repo.get_submenu_item(submenu_id)
if data is None:
return None
submenu = data.__dict__
@ -90,9 +90,7 @@ class SubmenuService:
async def update_submenu(
self, menu_id: UUID, submenu_id: UUID, submenu_data: MenuBase
) -> SubMenuRead | None:
data = await self.submenu_repo.update_submenu_item(
menu_id, submenu_id, submenu_data
)
data = await self.submenu_repo.update_submenu_item(submenu_id, submenu_data)
if data is None:
return None
@ -111,7 +109,7 @@ class SubmenuService:
return submenu
async def del_menu(self, menu_id: UUID, submenu_id: UUID) -> None:
await self.submenu_repo.delete_submenu_item(menu_id, submenu_id)
await self.submenu_repo.delete_submenu_item(submenu_id)
await self.cache.delete(
key=self.key(
'submenu',

View File

@ -19,7 +19,7 @@ class SummaryService:
self.key = get_key
self.bg_tasks = background_tasks
async def read_data(self):
async def read_data(self) -> list[MenuSummary]:
result = []