# FoodAI — План реализации ## Обзор итераций | # | Итерация | Цель | Зависит от | |---|----------|------|------------| | 0 | Фундамент | Go-проект, БД, авторизация, Flutter-каркас | — | | 1 | AI-рекомендации рецептов | Gemini генерирует рецепты, Pexels фото, сохранение рецептов | 0 | | 2 | Управление продуктами | CRUD продуктов, сроки хранения, ingredient_mappings | 0 | | 3 | Распознавание продуктов | OCR чека, фото продуктов, фото блюд (Gemini Vision) | 1, 2 | | 4 | Планирование меню | Меню на неделю, AI-генерация, список покупок, дневник | 1, 2 | Дальнейшие итерации определяются приоритетами после MVP. Функциональность из TODO.md (дневник статистики, режим готовки, полировка) — следующий горизонт. ## Карта зависимостей ``` ┌──────────────┐ │ 0. Фундамент │ └──────┬───────┘ │ ┌────────────┴────────────┐ │ │ ▼ ▼ ┌────────────────────┐ ┌──────────────────┐ │ 1. AI-рекомендации │ │ 2. Продукты │ │ (Gemini+Pexels) │ │ + ingredient_ │ │ saved_recipes │ │ mappings │ └──────────┬─────────┘ └────────┬─────────┘ │ │ └────────────┬────────────┘ │ ┌──────────┴──────────┐ │ │ ▼ ▼ ┌────────────────────┐ ┌─────────────────────┐ │ 3. Распознавание │ │ 4. Планирование │ │ продуктов │ │ меню │ │ (Gemini Vision) │ │ (Gemini+Pexels) │ └────────────────────┘ └─────────────────────┘ ``` **Параллельная разработка:** итерации 1 и 2 могут выполняться параллельно. Итерации 3 и 4 — тоже параллельно после завершения 1 и 2. --- ## Итерация 0: Фундамент > **Детальный план:** [Iteration_0.md](./Iteration_0.md) **Цель:** развернуть скелет проекта, базу данных, авторизацию и каркас мобильного приложения. После итерации можно зарегистрироваться, войти и увидеть пустые экраны. **Зависимости:** нет. ### User Stories #### Backend | ID | Story | Описание | |----|-------|----------| | 0.1 | Инициализация Go-проекта | Структура проекта (cmd/, internal/, pkg/), go.mod, конфигурация (envconfig), логгер (slog), graceful shutdown | | 0.2 | PostgreSQL + миграции | Подключение к PostgreSQL (pgx), система миграций (goose или golang-migrate). Начальная миграция: таблица `users` | | 0.3 | HTTP-сервер + роутер | HTTP-сервер (net/http или chi), middleware (CORS, request ID, logging, recovery), healthcheck endpoint | | 0.4 | Firebase Auth интеграция | Firebase Admin SDK. Middleware для верификации Firebase idToken. Выдача собственного JWT. Эндпоинты: `POST /auth/login`, `POST /auth/refresh`, `POST /auth/logout` | | 0.5 | Таблица users | Миграция: users (id, firebase_uid, email, name, avatar_url, параметры тела, цель, preferences JSONB, plan, created_at). CRUD-сервис | | 0.6 | Docker Compose | docker-compose.yml: PostgreSQL, приложение. Makefile с основными командами (migrate, run, test) | #### Flutter | ID | Story | Описание | |----|-------|----------| | 0.7 | Инициализация Flutter-проекта | Создание проекта, структура (features/, core/, shared/), подключение основных пакетов (dio, riverpod/bloc, go_router) | | 0.8 | Firebase Auth во Flutter | Пакеты firebase_auth, google_sign_in, sign_in_with_apple. Экраны: вход (email + Google + Apple), регистрация. Хранение JWT в secure storage | | 0.9 | Навигация и каркас экранов | Bottom Tab Bar (5 вкладок), пустые заглушки для каждого экрана, роутинг | | 0.10 | API-клиент | Dio-клиент с interceptors: JWT-токен, refresh, error handling. Базовые модели (User) | ### Результат итерации - Можно зарегистрироваться через email / Google / Apple - Войти в приложение и увидеть 5 вкладок с заглушками - Backend отвечает на healthcheck и auth-запросы - БД содержит таблицу users с данными зарегистрированных пользователей --- ## Итерация 1: AI-рекомендации рецептов > **Детальный план:** [Iteration_1.md](./Iteration_1.md) **Цель:** реализовать ключевую функцию — персонализированные рецепты, сгенерированные Gemini, с фотографиями из Pexels и возможностью сохранять понравившиеся. **Зависимости:** итерация 0. ### User Stories #### Backend | ID | Story | Описание | |----|-------|----------| | 1.1 | Gemini-клиент | Пакет internal/gemini. Интерфейс RecipeGenerator. GenerateRecipes(prompt) → []Recipe. Retry на невалидный JSON | | 1.2 | Pexels-клиент | Пакет internal/pexels. SearchPhoto(query) → image_url. Параллельные запросы | | 1.3 | Таблица saved_recipes | Миграция: id, user_id, title, description, cuisine, difficulty, prep/cook_time_min, servings, image_url, ingredients (JSONB), steps (JSONB), tags (JSONB), nutrition (JSONB), source, saved_at | | 1.4 | GET /recommendations | Формирует промпт из профиля пользователя → Gemini → Pexels → ответ с image_url | | 1.5 | CRUD saved_recipes | POST /saved-recipes, GET /saved-recipes, GET /saved-recipes/{id}, DELETE /saved-recipes/{id} | #### Flutter | ID | Story | Описание | |----|-------|----------| | 1.6 | RecommendationsScreen | Список карточек, skeleton-загрузка, кнопка 🔄 для перегенерации | | 1.7 | RecipeDetailScreen | Фото, КБЖУ≈, ингредиенты, шаги, кнопка сохранить | | 1.8 | SavedRecipesScreen | Список с удалением, пустое состояние | ### Результат итерации - Пользователь открывает вкладку «Рецепты» и видит 5 персонализированных рецептов с фото - Может сохранить рецепт, просмотреть детали, удалить из сохранённых - КБЖУ помечены «≈» как приблизительные --- ## Итерация 2: Управление продуктами > **Детальный план:** [Iteration_2.md](./Iteration_2.md) **Цель:** пользователь может вести список своих продуктов вручную — добавлять через автодополнение (ingredient_mappings), редактировать, удалять, отслеживать сроки. Рекомендации становятся персонализированными: Gemini учитывает имеющиеся продукты. **Зависимости:** итерация 0. ### User Stories #### Backend | ID | Story | Описание | |----|-------|----------| | 2.1 | Таблица products | Миграция: id, user_id, mapping_id (FK nullable), name, quantity, unit (ENUM), category, storage_days, added_at, expires_at (computed). Индексы по user_id, expires_at | | 2.2 | Products CRUD API | `GET /products` (фильтры: category, expiring), `POST /products`, `PUT /products/{id}`, `DELETE /products/{id}`, `DELETE /products` (очистить все) | | 2.3 | Частичное использование | `PATCH /products/{id}/consume` — уменьшить количество. Если количество = 0, предложить удаление | | 2.4 | Массовое добавление | `POST /products/batch` — добавление нескольких продуктов за раз (после распознавания). Обработка дубликатов: проверка по mapping_id, предложение объединить | | 2.5 | Дефолтные сроки хранения | `GET /products/storage-defaults`, `PUT /products/storage-defaults`. Хранение в user preferences (JSONB в таблице users) | | 2.6 | Fuzzy matching при добавлении | При добавлении продукта — поиск по ingredient_mappings.aliases. Если найдено — автозаполнение: mapping_id, category, unit, storage_days, нутриенты | #### Flutter | ID | Story | Описание | |----|-------|----------| | 2.7 | Экран «Мои продукты» | Список продуктов по категориям, поиск, chip-фильтры, badge «осталось X дней» | | 2.8 | Добавление/редактирование продукта | Форма: название, количество, единица, категория, период хранения. Выпадающее меню добавления (+) | | 2.9 | Частичное использование | Модалка «Сколько осталось?» при свайпе или тапе | | 2.10 | Очистить и перезаполнить | Контекстное меню (···) → подтверждение → очистка | | 2.11 | Настройки сроков хранения | Экран из Профиля: список категорий с редактируемыми днями | | 2.12 | Пустое состояние | Иллюстрация + CTA «Сфотографируйте продукты или сканируйте чек» | ### Результат итерации - Пользователь может вручную добавить продукты, указать количество и сроки - Видит «осталось X дней» для каждого продукта - Может частично использовать продукт, удалить, очистить всё - При добавлении — автоматический подбор категории, единицы, срока через fuzzy match --- ## Итерация 3: Распознавание продуктов > **Детальный план:** [Iteration_3.md](./Iteration_3.md) **Цель:** пользователь фотографирует чек, холодильник или блюдо — Gemini Vision распознаёт продукты и помогает заполнить список запасов. **Зависимости:** итерации 1, 2. ### User Stories #### Backend | ID | Story | Описание | |----|-------|----------| | 3.1 | OCR чека | POST /ai/recognize-receipt: фото → Gemini Flash (vision) → JSON (name, qty, unit, confidence). Fuzzy match по ingredient_mappings | | 3.2 | Фото продуктов | POST /ai/recognize-products: 1–3 фото → параллельные Gemini-запросы → дедупликация → JSON | | 3.3 | Распознавание блюда | POST /ai/recognize-dish: фото → Gemini → {dish_name, weight_g, КБЖУ≈, confidence} | | 3.4 | Авто-маппинг | Нераспознанный продукт → Gemini классифицирует → сохраняет в ingredient_mappings | | 3.5 | S3 / multipart | Загрузка фото: multipart или presigned URL | #### Flutter | ID | Story | Описание | |----|-------|----------| | 3.6 | ScanScreen | Выбор режима: чек / продукты / блюдо. Камера + галерея | | 3.7 | Экран подтверждения | Список с инлайн-редактированием, удалением, «Добавить ещё фото», CTA «В запасы» | | 3.8 | Экран результата блюда | Фото, КБЖУ≈, кнопки «В дневник» / «Открыть рецепт» | ### Результат итерации - Сфотографировал чек → список продуктов → подтвердил → добавил в запасы - Сфотографировал холодильник → то же - Сфотографировал блюдо → КБЖУ≈ → можно добавить в дневник --- ## Итерация 4: Планирование меню > **Детальный план:** [Iteration_4.md](./Iteration_4.md) **Цель:** пользователь получает полное меню на неделю от Gemini с учётом продуктов, целей и предпочтений. Автоматически формируется список покупок. **Зависимости:** итерации 1, 2. ### User Stories #### Backend | ID | Story | Описание | |----|-------|----------| | 4.1 | Таблицы menu_plans, menu_items | Миграции. menu_items → saved_recipes | | 4.2 | Таблица meal_diary | Миграция. Записи приёмов пищи | | 4.3 | POST /ai/generate-menu | Gemini генерирует 21 рецепт, Pexels параллельно, сохранение в БД | | 4.4 | Menu CRUD | GET /menu?week=, PUT /menu/items/{id}, DELETE /menu/items/{id} | | 4.5 | Shopping list | POST /shopping-list/generate (SQL-агрегация без Gemini), GET, PATCH check | #### Flutter | ID | Story | Описание | |----|-------|----------| | 4.6 | MenuScreen | 7-дневный вид, skeleton на генерацию, кнопка «Сгенерировать» | | 4.7 | Замена рецепта | Тап «Изменить» → выбор из saved_recipes или перегенерация | | 4.8 | ShoppingListScreen | Список по категориям, чекбоксы, «Поделиться» | | 4.9 | DiaryScreen | Записи за день, «+ Добавить» | ### Результат итерации - Пользователь получает меню на неделю одним запросом к Gemini - Все рецепты меню сохраняются в saved_recipes - Из меню автоматически формируется список покупок (то, чего нет в запасах) - Ведётся дневник питания --- ## Итоги | Итерация | Цель | Ключевые API | |----------|------|-------------| | 0. Фундамент | Auth, профиль, каркас | Firebase | | 1. AI-рекомендации | Рецепты + сохранение | Gemini, Pexels | | 2. Продукты | CRUD запасов, ingredient_mappings | — | | 3. Распознавание | OCR чека, фото продуктов/блюда | Gemini Vision | | 4. Меню | Недельное меню, список покупок | Gemini, Pexels | **MVP:** итерации 0–2 (авторизация + рекомендации + продукты) — пользователь получает персонализированные рецепты. **Полный продукт:** итерации 0–4 — полный цикл: сфотографировал чек → получил меню → список покупок → дневник питания.