diff --git a/backend/src/routes/order.rs b/backend/src/routes/order.rs index d011e0e..d03b6f9 100644 --- a/backend/src/routes/order.rs +++ b/backend/src/routes/order.rs @@ -8,7 +8,7 @@ use actix_web::{ HttpResponse, Responder, Scope, web::{Data, Json, Path, Query}, }; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use sqlx::{PgPool, error::DatabaseError}; use uuid::Uuid; @@ -21,6 +21,9 @@ struct QueryParams { pub limit: Option, pub offset: Option, pub sort_order: Option, + pub invoice_number: Option, + pub customer_id: Option, + pub batch_id: Option, } #[actix_web::post("")] @@ -40,6 +43,13 @@ async fn post(pool: Data, body: Json, user: User) -> impl Respon } } +#[derive(Serialize)] +struct OrderListResponse { + rows: Vec, + total: i64, + page_count: i64, +} + #[actix_web::get("")] async fn get_all(pool: Data, options: Query, user: User) -> impl Responder { if !user.permissions.contains(Main::PERM_READ) { @@ -52,11 +62,66 @@ async fn get_all(pool: Data, options: Query, user: User) -> let limit = options.limit.unwrap_or(100) as i64; let offset = options.offset.unwrap_or(0) as i64; let sort_asc = options.sort_order.unwrap_or(SortOrder::Desc) == SortOrder::Asc; + let sort_by = "created_at"; + + let invoice_like = options.invoice_number.as_ref().map(|n| format!("%{}%", n)); + let customer_id = options.customer_id.as_ref(); + let batch_id = options.batch_id.as_ref(); + + let mut count_query = + sqlx::QueryBuilder::new(&format!("SELECT COUNT(*) FROM {}", Main::TABLE_NAME)); + count_query.push(" WHERE 1=1"); + + if let Some(like) = &invoice_like { + count_query.push(" AND invoice_number ILIKE "); + count_query.push_bind(like); + } + + if let Some(cid) = &customer_id { + count_query.push(" AND customer_id = "); + count_query.push_bind(cid); + } + + if let Some(bid) = &batch_id { + let table = Main::TABLE_NAME; + count_query.push(&format!(" AND EXISTS (SELECT 1 FROM order_items WHERE order_items.order_id = {table}.id AND order_items.batch_id = ")); + count_query.push_bind(bid); + count_query.push(")"); + } + + let total: i64 = match count_query + .build_query_scalar::() + .fetch_one(pool.get_ref()) + .await + { + Ok(n) => n, + Err(err) => { + tracing::error!("count query failed: {err:?}"); + return HttpResponse::InternalServerError().finish(); + } + }; - let mut query = sqlx::QueryBuilder::new(format!("SELECT * FROM {}", Main::TABLE_NAME)); + let mut query = sqlx::QueryBuilder::new(&format!("SELECT * FROM {}", Main::TABLE_NAME)); query.push(" WHERE 1=1"); - query.push(" ORDER BY created_at "); + if let Some(like) = &invoice_like { + query.push(" AND invoice_number ILIKE "); + query.push_bind(like); + } + + if let Some(cid) = &customer_id { + query.push(" AND customer_id = "); + query.push_bind(cid); + } + + if let Some(bid) = &batch_id { + let table = Main::TABLE_NAME; + query.push(&format!(" AND EXISTS (SELECT 1 FROM order_items WHERE order_items.order_id = {table}.id AND order_items.batch_id = ")); + query.push_bind(bid); + query.push(")"); + } + + query.push(format!(" ORDER BY {sort_by} ")); if sort_asc { query.push("ASC"); } else { @@ -68,12 +133,18 @@ async fn get_all(pool: Data, options: Query, user: User) -> query.push(" OFFSET "); query.push_bind(offset); + let page_count = (total + limit - 1) / limit; + match query - .build_query_as::
() + .build_query_as::() .fetch_all(pool.get_ref()) .await { - Ok(batches) => HttpResponse::Ok().json(batches), + Ok(order) => HttpResponse::Ok().json(OrderListResponse { + rows: order, + page_count, + total, + }), Err(err) => { tracing::error!("{err:?}"); HttpResponse::InternalServerError().finish()