Cookest
API Backend

Esquema da Base de Dados

Diagrama entidade-relação e descrição das tabelas da base de dados do Cookest

Esquema da Base de Dados

A API do Cookest utiliza PostgreSQL 15+ acedido via SeaORM 1.1. As migrações são executadas automaticamente no arranque do servidor — todas as operações utilizam IF NOT EXISTS, tornando-as seguras para repetição.

Diagrama ER


Identidade e preferências

users

Credenciais de conta, perfil, dados de integração e estado da subscrição.

ColunaTipoNotas
idUUID PKGerado automaticamente (v4)
emailVARCHAR(255) UNIQUEIdentificador de início de sessão
nameVARCHAR(255)Nome de apresentação
password_hashTEXTHash bcrypt
refresh_token_hashTEXTSHA-256 do token de atualização
household_sizeINTEGERPredefinição 1 — escala porções de receitas
dietary_restrictionsTEXT[]ex.: {vegetarian, gluten_free}
allergiesTEXT[]ex.: {shellfish, eggs}
avatar_urlTEXTURL da foto de perfil
subscription_tierTEXTfree / pro / family
subscription_valid_untilTIMESTAMPTZNulo para nível free
stripe_customer_idTEXTReferência de cliente Stripe
cooking_skill_levelTEXTbeginner / intermediate / advanced
preferred_cuisinesTEXT[]Seleções de integração
health_goalsTEXT[]ex.: {weight_loss, muscle_gain}
weekly_budgetNUMERIC(10,2)Limite de orçamento opcional
preferred_time_per_meal_minINTEGERPreferência de tempo máximo de cozedura
onboarding_completedBOOLEANPredefinição false
is_adminBOOLEANVerificado via BD, nunca via JWT
is_email_verifiedBOOLEANEstado de verificação de e-mail
two_factor_enabledBOOLEANAlternância TOTP 2FA
totp_secretTEXTSemente TOTP encriptada
failed_login_attemptsINTEGERReposto em início de sessão bem-sucedido
locked_untilTIMESTAMPTZExpiração de bloqueio de conta
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

user_preferences

Vetores de preferência de IA por utilizador, atualizados incrementalmente via descida de gradiente online (taxa de aprendizagem 0.01).

ColunaTipoNotas
user_idUUID PK, FK → usersUm-para-um com users
cuisine_weightsJSONBex.: {"italian": 0.8, "japanese": 0.3}
ingredient_weightsJSONBPontuações de afinidade por ingrediente
macro_biasJSONB{"protein": 0.0, "carbs": 0.0, "fat": 0.0}
difficulty_weightsJSONB{"easy": 0.0, "medium": 0.0, "hard": 0.0}
preferred_time_minINTEGERPredefinição 30
interaction_countINTEGERTotal de avaliações + cozinhados
updated_atTIMESTAMPTZ

Ingredientes e nutrição

ingredients

Catálogo principal de ingredientes, alimentado pelo pipeline ETL a partir do FoodData Central e Open Food Facts.

ColunaTipoNotas
idBIGSERIAL PK
nameTEXT UNIQUENome canónico
categoryTEXTex.: dairy, vegetable
fdc_idINTEGERID do FoodData Central (indexado)
off_idTEXTID do Open Food Facts
created_atTIMESTAMPTZ

ingredient_nutrients

Valores detalhados de macro e micronutrientes por 100 g de ingrediente. Um-para-um com ingredients.

ColunaTipoNotas
idBIGSERIAL PK
ingredient_idBIGINT FK → ingredientsUNIQUE — uma linha por ingrediente
caloriesNUMERIC(10,4)kcal por 100 g
protein_gNUMERIC(10,4)
carbs_gNUMERIC(10,4)
fat_gNUMERIC(10,4)
fiber_gNUMERIC(10,4)
sugar_gNUMERIC(10,4)
sodium_mgNUMERIC(10,4)
saturated_fat_gNUMERIC(10,4)
cholesterol_mgNUMERIC(10,4)
micronutrientsJSONBIndexado com GIN para consultas flexíveis

portion_sizes

Tamanhos de porções comuns por ingrediente (ex.: "1 ovo médio = 50 g").

ColunaTipoNotas
idBIGSERIAL PK
ingredient_idBIGINT FK → ingredients
descriptionTEXTex.: "1 médio"
weight_gramsNUMERIC(10,3)
unitTEXTex.: "chávena", "colher de sopa"

Receitas

recipes

Metadados de receitas. Suporta filtros alimentares, pesquisa de texto completo (índice GIN trigram em name) e autoria por utilizador.

ColunaTipoNotas
idBIGSERIAL PK
nameTEXTIndexado com trigram GIN
slugTEXT UNIQUEIdentificador seguro para URL
descriptionTEXT
cuisineTEXTIndexado
categoryTEXTIndexado
difficultyTEXTIndexado — easy / medium / hard
servingsINTEGERPredefinição 2
prep_time_minINTEGER
cook_time_minINTEGER
total_time_minINTEGER
is_vegetarianBOOLEANÍndice alimentar composto
is_veganBOOLEAN
is_gluten_freeBOOLEAN
is_dairy_freeBOOLEAN
is_nut_freeBOOLEAN
source_urlTEXTURL da receita original
average_ratingNUMERIC(3,2)Média desnormalizada
rating_countINTEGER
author_idUUID FK → usersAnulável — receitas submetidas por utilizadores
is_publicBOOLEANPredefinição true
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

recipe_ingredients

Tabela de junção entre receitas e ingredientes com quantidade e unidade.

ColunaTipoNotas
idBIGSERIAL PK
recipe_idBIGINT FK → recipesON DELETE CASCADE
ingredient_idBIGINT FK → ingredientsON DELETE RESTRICT
quantityNUMERIC(10,3)ex.: 200
unitTEXTex.: g, ml, colher de sopa
quantity_gramsNUMERIC(10,3)Peso normalizado para cálculo nutricional
notesTEXTex.: "finamente picado"
display_orderINTEGERSequência de apresentação

recipe_steps

Instruções de confeção ordenadas para uma receita.

ColunaTipoNotas
idBIGSERIAL PK
recipe_idBIGINT FK → recipes
step_numberINTEGERUNIQUE por receita
instructionTEXTTexto do passo
duration_minINTEGEREstimativa de tempo opcional
image_urlTEXTFoto do passo opcional
tipTEXTDica de cozinha opcional

recipe_images

URLs de imagens associadas a receitas.

ColunaTipoNotas
idBIGSERIAL PK
recipe_idBIGINT FK → recipes
urlTEXTURL da imagem
image_typeTEXTex.: hero, step
is_primaryBOOLEANPredefinição false
widthINTEGER
heightINTEGER
sourceTEXTAtribuição
created_atTIMESTAMPTZ

recipe_nutrition

Totais de macros pré-calculados para uma receita. Um-para-um com recipes.

ColunaTipoNotas
idBIGSERIAL PK
recipe_idBIGINT FK → recipesUNIQUE
per_servingBOOLEANPredefinição true — valores são por porção
caloriesNUMERIC(10,4)
protein_gNUMERIC(10,4)
carbs_gNUMERIC(10,4)
fat_gNUMERIC(10,4)
fiber_gNUMERIC(10,4)
sugar_gNUMERIC(10,4)
sodium_mgNUMERIC(10,4)
saturated_fat_gNUMERIC(10,4)
cholesterol_mgNUMERIC(10,4)
micronutrientsJSONB
calculated_atTIMESTAMPTZ

Interações do utilizador

user_favorites

Receitas guardadas/marcadas por utilizador.

ColunaTipoNotas
idBIGSERIAL PK
user_idUUID FK → usersUNIQUE(user_id, recipe_id)
recipe_idBIGINT FK → recipes
saved_atTIMESTAMPTZ

recipe_ratings

Avaliações de 1 a 5 estrelas com comentário de texto opcional.

ColunaTipoNotas
idBIGSERIAL PK
user_idUUID FK → usersUNIQUE(user_id, recipe_id)
recipe_idBIGINT FK → recipes
ratingSMALLINTCHECK 1–5
commentTEXT
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

cooking_history

Registo datado de cada vez que um utilizador cozinha uma receita. Desencadeia dedução automática de inventário.

ColunaTipoNotas
idBIGSERIAL PK
user_idUUID FK → users
recipe_idBIGINT FK → recipes
servings_madeINTEGERPredefinição 1
inventory_deductedBOOLEANPredefinição false — definido true após dedução
cooked_atTIMESTAMPTZ

Planeamento e inventário

inventory_items

Itens da despensa com quantidade, unidade, data de validade e localização de armazenamento.

ColunaTipoNotas
idBIGSERIAL PK
user_idUUID FK → users
ingredient_idBIGINT FK → ingredientsON DELETE RESTRICT
custom_nameTEXTNome de apresentação alternativo opcional
quantityNUMERIC(10,3)
unitTEXTex.: g, ml, unidades
expiry_dateDATEIndexado para alertas de validade
storage_locationTEXTfridge / freezer / pantry / other
added_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

meal_plans

Contentor do plano semanal. Um plano por utilizador por semana.

ColunaTipoNotas
idBIGSERIAL PK
user_idUUID FK → usersUNIQUE(user_id, week_start)
week_startDATESegunda-feira da semana do plano
is_ai_generatedBOOLEANPredefinição false
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

meal_plan_slots

Atribuições individuais de refeições: dia 0–6 × tipo de refeição. Suporta dias flex/de descanso.

ColunaTipoNotas
idBIGSERIAL PK
meal_plan_idBIGINT FK → meal_plans
recipe_idBIGINT FK → recipesAnulável — nulo para dias flex
day_of_weekSMALLINTCHECK 0–6 (Seg–Dom)
meal_typeTEXTbreakfast / lunch / dinner / snack
servings_overrideINTEGERSubstitui predefinição da receita
is_completedBOOLEANPredefinição false
is_flexBOOLEANPredefinição false — indicador de dia de descanso
flex_typeTEXTeffort / nutrition / mental / social
energy_levelTEXTRastreio de energia opcional

A restrição UNIQUE em (meal_plan_id, day_of_week, meal_type) garante no máximo uma receita por slot.

shopping_list_items

Itens da lista de compras do utilizador, opcionalmente ligados a um plano de refeições para sincronização automática.

ColunaTipoNotas
idUUID PK
user_idUUID FK → users
ingredient_idBIGINT FK → ingredientsAnulável — para itens manuais
nameTEXTNome de apresentação
quantityNUMERIC(10,3)
unitTEXT
is_checkedBOOLEANPredefinição false
is_manualBOOLEANtrue se adicionado manualmente vs. sincronizado
meal_plan_idBIGINT FK → meal_plansAnulável — liga ao plano de origem
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

Chat com IA

chat_sessions

Uma sessão por fio de conversa, opcionalmente contextualizada a uma receita (chat do Modo de Cozinha).

ColunaTipoNotas
idBIGSERIAL PK
user_idUUID FK → users
current_recipe_idBIGINT FK → recipesAnulável — fornece contexto de receita
titleTEXTGerado automaticamente ou definido pelo utilizador
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

chat_messages

Mensagens individuais dentro de uma sessão de chat.

ColunaTipoNotas
idBIGSERIAL PK
session_idBIGINT FK → chat_sessionsIndexado com created_at ASC
roleTEXTCHECK user / assistant / system
contentTEXTCorpo da mensagem
tokens_usedINTEGERContagem de tokens LLM para limitação de taxa
created_atTIMESTAMPTZ

Lojas e promoções

stores

Lojas cujos folhetos promocionais são processados pelo pipeline de PDFs.

ColunaTipoNotas
idUUID PK
nameTEXTNome da loja
slugTEXT UNIQUEIdentificador seguro para URL
websiteTEXT
logo_urlTEXT
countryTEXT
cityTEXT
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

pdf_processing_jobs

Rastreia o estado dos trabalhos de processamento de folhetos PDF.

ColunaTipoNotas
idUUID PK
store_idUUID FK → stores
file_pathTEXTCaminho do PDF carregado
statusTEXTpending / processing / completed / failed
errorTEXTMensagem de erro em caso de falha
retry_countINTEGERPredefinição 0
started_atTIMESTAMPTZ
heartbeat_atTIMESTAMPTZVerificação de atividade para trabalhos longos
processed_atTIMESTAMPTZ
created_atTIMESTAMPTZ

store_promotions

Preços promocionais em tempo real extraídos de PDFs processados e aprovados pelo administrador.

ColunaTipoNotas
idUUID PK
store_idUUID FK → stores
product_nameTEXTNome do produto extraído do PDF
brandTEXT
original_priceNUMERIC(10,2)
discounted_priceNUMERIC(10,2)
discount_pctNUMERIC(5,2)
unitTEXTex.: kg, unidade
valid_fromTIMESTAMPTZJanela da promoção
valid_untilTIMESTAMPTZ
is_activeBOOLEANPredefinição true
source_pdf_urlTEXT
confidenceNUMERIC(4,3)Confiança de extração LLM 0–1
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

store_promotion_ingredients

Liga promoções a ingredientes no catálogo usando correspondência por semelhança.

ColunaTipoNotas
promotion_idUUID FK → store_promotionsPK composta
ingredient_idBIGINT FK → ingredientsPK composta
similarity_scoreNUMERIC(4,3)Confiança de correspondência 0–1

store_promotion_candidates

Tabela de preparação para promoções extraídas de PDFs, pendentes de revisão do administrador.

ColunaTipoNotas
idUUID PK
store_idUUID FK → stores
job_idUUID FK → pdf_processing_jobsTrabalho de processamento de origem
product_nameTEXT
brandTEXT
original_priceNUMERIC(10,2)
discounted_priceNUMERIC(10,2)
discount_pctNUMERIC(5,2)
unitTEXT
valid_fromTIMESTAMPTZ
valid_untilTIMESTAMPTZ
confidenceNUMERIC(4,3)
review_statusTEXTpending / approved / rejected
reviewed_byUUID FK → usersAdministrador que reviu
reviewed_atTIMESTAMPTZ
created_atTIMESTAMPTZ

Notificações push e pagamentos

user_push_tokens

Tokens push de dispositivos para notificações.

ColunaTipoNotas
idUUID PK
user_idUUID FK → users
tokenTEXT UNIQUEToken do dispositivo
platformTEXTios / android / web
created_atTIMESTAMPTZ

stripe_processed_events

Tabela de idempotência para processamento de webhooks Stripe — previne tratamento duplicado de eventos.

ColunaTipoNotas
event_idTEXT PKID do evento Stripe
processed_atTIMESTAMPTZ

Relações principais

  • recipe_ingredients liga receitas a ingredientes, armazenando quantity e unit (ex.: 200 g). A coluna quantity_grams contém o peso normalizado usado para cálculo nutricional.
  • meal_plan_slots associa planos semanais a receitas específicas e controla is_flex, flex_type, is_completed e servings_override.
  • cooking_history desencadeia deduções automáticas de inventário escaladas pelo household_size quando inventory_deducted transita de false para true.
  • user_preferences armazena vetores de peso em vírgula flutuante que o algoritmo de aprendizagem online atualiza de forma incremental com cada avaliação ou evento de cozedura.
  • store_promotion_candidatesstore_promotions — as promoções passam por revisão de administrador antes de ficarem ativas.
  • stripe_processed_events garante idempotência de webhooks — cada evento Stripe é processado exatamente uma vez.

Fonte de verdade

O SQL de migração em api/src/main.rs é o esquema canónico. Este documento reflete esse esquema — consulte o ficheiro fonte para tipos de colunas e restrições exatas.

On this page