chore: slight simplifications to bags

This commit is contained in:
Jon Seager 2025-11-27 13:24:45 +00:00
parent ec8dbea7ea
commit 7eab263071
No known key found for this signature in database
4 changed files with 50 additions and 84 deletions

View file

@ -22,16 +22,19 @@ use crate::presentation::web::views::{BagView, ListNavigator, Paginated, Roaster
const BAG_PAGE_PATH: &str = "/bags";
const BAG_FRAGMENT_PATH: &str = "/bags#bag-list";
struct BagPageData {
open_bags: Vec<BagView>,
bags: Paginated<BagView>,
navigator: ListNavigator<BagSortKey>,
}
#[tracing::instrument(skip(state))]
async fn load_bag_page(
state: &AppState,
request: ListRequest<BagSortKey>,
) -> Result<(Vec<BagView>, Paginated<BagView>, ListNavigator<BagSortKey>), AppError> {
) -> Result<BagPageData, AppError> {
let open_bags = state.bag_repo.list_open().await.map_err(AppError::from)?;
let open_bags_view = open_bags
.into_iter()
.map(BagView::from_with_roast)
.collect();
let open_bags_view = open_bags.into_iter().map(BagView::from_domain).collect();
let page = state
.bag_repo
@ -42,12 +45,16 @@ async fn load_bag_page(
let (bags, navigator) = crate::application::routes::support::build_page_view(
page,
request,
BagView::from_with_roast,
BagView::from_domain,
BAG_PAGE_PATH,
BAG_FRAGMENT_PATH,
);
Ok((open_bags_view, bags, navigator))
Ok(BagPageData {
open_bags: open_bags_view,
bags,
navigator,
})
}
#[tracing::instrument(skip(state, cookies, headers, query))]
@ -75,7 +82,11 @@ pub(crate) async fn bags_page(
let roaster_options = roasters.into_iter().map(RoasterOptionView::from).collect();
let (open_bags, bags, navigator) = load_bag_page(&state, request)
let BagPageData {
open_bags,
bags,
navigator,
} = load_bag_page(&state, request)
.await
.map_err(map_app_error)?;
@ -352,7 +363,11 @@ async fn render_bag_list_fragment(
request: ListRequest<BagSortKey>,
is_authenticated: bool,
) -> Result<Response, AppError> {
let (open_bags, bags, navigator) = load_bag_page(&state, request).await?;
let BagPageData {
open_bags,
bags,
navigator,
} = load_bag_page(&state, request).await?;
let template = BagListTemplate {
is_authenticated,

View file

@ -112,7 +112,7 @@ pub(crate) async fn roast_page(
let bag_views = bags
.into_iter()
.map(crate::presentation::web::views::BagView::from_with_roast)
.map(crate::presentation::web::views::BagView::from_domain)
.collect();
let is_authenticated =

View file

@ -9,6 +9,16 @@ use crate::domain::listing::{ListRequest, Page, SortDirection};
use crate::domain::repositories::BagRepository;
use crate::infrastructure::database::DatabasePool;
const BASE_SELECT: &str = r#"
SELECT
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
r.name as roast_name, r.slug as roast_slug,
rr.name as roaster_name, rr.slug as roaster_slug
FROM bags b
JOIN roasts r ON b.roast_id = r.id
JOIN roasters rr ON r.roaster_id = rr.id
"#;
#[derive(Clone)]
pub struct SqlBagRepository {
pool: DatabasePool,
@ -111,22 +121,12 @@ impl BagRepository for SqlBagRepository {
let order_clause = format!("{} {}", sort_column, direction);
let base_query = r#"
SELECT
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
r.name as roast_name, r.slug as roast_slug,
rr.name as roaster_name, rr.slug as roaster_slug
FROM bags b
JOIN roasts r ON b.roast_id = r.id
JOIN roasters rr ON r.roaster_id = rr.id
"#;
let count_query = "SELECT COUNT(*) FROM bags";
crate::infrastructure::repositories::pagination::paginate(
&self.pool,
request,
base_query,
BASE_SELECT,
count_query,
&order_clause,
|record| Ok(Self::to_domain_with_roast(record)),
@ -135,19 +135,12 @@ impl BagRepository for SqlBagRepository {
}
async fn list_by_roast(&self, roast_id: RoastId) -> Result<Vec<BagWithRoast>, RepositoryError> {
let query = r#"
SELECT
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
r.name as roast_name, r.slug as roast_slug,
rr.name as roaster_name, rr.slug as roaster_slug
FROM bags b
JOIN roasts r ON b.roast_id = r.id
JOIN roasters rr ON r.roaster_id = rr.id
WHERE b.roast_id = ?
ORDER BY b.roast_date DESC
"#;
let query = format!(
"{} WHERE b.roast_id = ? ORDER BY b.roast_date DESC",
BASE_SELECT
);
let records = query_as::<_, BagWithRoastRecord>(query)
let records = query_as::<_, BagWithRoastRecord>(&query)
.bind(roast_id.into_inner())
.fetch_all(&self.pool)
.await
@ -226,19 +219,12 @@ impl BagRepository for SqlBagRepository {
}
async fn list_open(&self) -> Result<Vec<BagWithRoast>, RepositoryError> {
let query = r#"
SELECT
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
r.name as roast_name, r.slug as roast_slug,
rr.name as roaster_name, rr.slug as roaster_slug
FROM bags b
JOIN roasts r ON b.roast_id = r.id
JOIN roasters rr ON r.roaster_id = rr.id
WHERE b.closed = FALSE
ORDER BY b.roast_date DESC
"#;
let query = format!(
"{} WHERE b.closed = FALSE ORDER BY b.roast_date DESC",
BASE_SELECT
);
let records = query_as::<_, BagWithRoastRecord>(query)
let records = query_as::<_, BagWithRoastRecord>(&query)
.fetch_all(&self.pool)
.await
.map_err(|err| RepositoryError::unexpected(err.to_string()))?;
@ -268,23 +254,14 @@ impl BagRepository for SqlBagRepository {
let order_clause = format!("{} {}", sort_column, direction);
let base_query = r#"
SELECT
b.id, b.roast_id, b.roast_date, b.amount, b.remaining, b.closed, b.finished_at, b.created_at, b.updated_at,
r.name as roast_name, r.slug as roast_slug,
rr.name as roaster_name, rr.slug as roaster_slug
FROM bags b
JOIN roasts r ON b.roast_id = r.id
JOIN roasters rr ON r.roaster_id = rr.id
WHERE b.closed = TRUE
"#;
let base_query = format!("{} WHERE b.closed = TRUE", BASE_SELECT);
let count_query = "SELECT COUNT(*) FROM bags WHERE closed = TRUE";
crate::infrastructure::repositories::pagination::paginate(
&self.pool,
request,
base_query,
&base_query,
count_query,
&order_clause,
|record| Ok(Self::to_domain_with_roast(record)),

View file

@ -1,4 +1,4 @@
use crate::domain::bags::{Bag, BagWithRoast};
use crate::domain::bags::BagWithRoast;
use crate::domain::listing::{DEFAULT_PAGE_SIZE, ListRequest, Page, PageSize, SortKey};
use crate::domain::roasters::Roaster;
use crate::domain::roasts::{Roast, RoastWithRoaster};
@ -537,33 +537,7 @@ pub struct BagView {
}
impl BagView {
pub fn from_domain(
bag: Bag,
roast_name: &str,
roaster_name: &str,
roast_slug: &str,
roaster_slug: &str,
) -> Self {
Self {
id: bag.id.to_string(),
roast_id: bag.roast_id.to_string(),
roast_date: bag.roast_date.map(|d| d.to_string()),
amount: format!("{:.1}", bag.amount),
remaining: format!("{:.1}", bag.remaining),
closed: bag.closed,
finished_at: bag
.finished_at
.map(|d| d.to_string())
.unwrap_or_else(|| "".to_string()),
created_at: bag.created_at.format("%Y-%m-%d").to_string(),
roast_name: roast_name.to_string(),
roaster_name: roaster_name.to_string(),
roast_slug: roast_slug.to_string(),
roaster_slug: roaster_slug.to_string(),
}
}
pub fn from_with_roast(bag: BagWithRoast) -> Self {
pub fn from_domain(bag: BagWithRoast) -> Self {
Self {
id: bag.bag.id.to_string(),
roast_id: bag.bag.roast_id.to_string(),