From 8a1df4946d77e6af34fe8d5ab1479d58098a9847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Thu, 18 Dec 2025 13:12:28 +0100 Subject: [PATCH] add endpoint for earliest saved meal --- ...c67111c50d82f56471df1c9adba498be0d543.json | 20 ++++++++ web-api/src/endpoints/metadata.rs | 47 +++++++++++++++++++ web-api/src/endpoints/mod.rs | 2 + 3 files changed, 69 insertions(+) create mode 100644 .sqlx/query-66fcef790324f9eedc03ad052acc67111c50d82f56471df1c9adba498be0d543.json create mode 100644 web-api/src/endpoints/metadata.rs diff --git a/.sqlx/query-66fcef790324f9eedc03ad052acc67111c50d82f56471df1c9adba498be0d543.json b/.sqlx/query-66fcef790324f9eedc03ad052acc67111c50d82f56471df1c9adba498be0d543.json new file mode 100644 index 0000000..b78c80c --- /dev/null +++ b/.sqlx/query-66fcef790324f9eedc03ad052acc67111c50d82f56471df1c9adba498be0d543.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT MIN(date) AS \"date!\" FROM meals WHERE is_latest = TRUE;", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "date!", + "type_info": "Date" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + null + ] + }, + "hash": "66fcef790324f9eedc03ad052acc67111c50d82f56471df1c9adba498be0d543" +} diff --git a/web-api/src/endpoints/metadata.rs b/web-api/src/endpoints/metadata.rs new file mode 100644 index 0000000..cd189f7 --- /dev/null +++ b/web-api/src/endpoints/metadata.rs @@ -0,0 +1,47 @@ +use std::sync::OnceLock; + +use actix_web::{ + get, + web::{self, ServiceConfig}, + HttpResponse, Responder, +}; +use chrono::NaiveDate; +use serde_json::json; +use sqlx::PgPool; + +pub fn configure(cfg: &mut ServiceConfig) { + cfg.service(web::scope("/metadata").service(earliest_meal_date)); +} + +static EARLIEST_MEAL_DATE: OnceLock = OnceLock::new(); + +#[get("/earliest-meal-date")] +async fn earliest_meal_date(db: web::Data) -> impl Responder { + if let Some(earliest_date) = EARLIEST_MEAL_DATE.get() { + earliest_meal_date_ok_response(*earliest_date) + } else { + match sqlx::query_scalar!( + r#"SELECT MIN(date) AS "date!" FROM meals WHERE is_latest = TRUE;"# + ) + .fetch_one(db.as_ref()) + .await + { + Ok(date) => { + EARLIEST_MEAL_DATE.set(date).ok(); + earliest_meal_date_ok_response(date) + } + Err(err) => { + tracing::error!("Failed to query datebase: {err}"); + HttpResponse::InternalServerError().json(json!({ + "error": "Failed to query database" + })) + } + } + } +} + +fn earliest_meal_date_ok_response(date: NaiveDate) -> HttpResponse { + HttpResponse::Ok().json(json!({ + "date": date, + })) +} diff --git a/web-api/src/endpoints/mod.rs b/web-api/src/endpoints/mod.rs index 77db428..ca1b980 100644 --- a/web-api/src/endpoints/mod.rs +++ b/web-api/src/endpoints/mod.rs @@ -5,11 +5,13 @@ use shared::Canteen; use strum::IntoEnumIterator as _; mod menu; +mod metadata; mod nutrition; mod price_history; pub fn configure(cfg: &mut ServiceConfig) { cfg.service(index) + .configure(metadata::configure) .configure(menu::configure) .configure(nutrition::configure) .configure(price_history::configure);