Files
vmall/apps/api/src/modules/product/dto.rs
T
Chengdong ZhangandClaude Sonnet 5 8446650baf refactor(api): split catalog module into product, category, brand
Rearranges the Rust backend by domain: `modules/catalog` bundled four
distinct concepts (Product, SKU, Category, Brand) behind one router
and one 392-line service file, unlike every other module in the
codebase which owns exactly one bounded aggregate.

Splits into `modules/product` (Product/SKU, publish lifecycle,
shop-scoped CRUD), `modules/category` (category tree, subtree query),
and `modules/brand` (brand list, admin replace-all). `Category`/`Brand`
move out of the shared `models.rs` into their owning modules;
`Product`/`Sku` stay since `favorite`/`flash_sale`/`group_buying`
reference them across modules. Purely internal restructuring — no
route, schema, or behavior changes.

Implements openspec change split-catalog-into-product-category-brand.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 16:07:44 +08:00

72 lines
1.8 KiB
Rust

use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::error::{ApiError, ApiResult};
use crate::models::{Product, Sku};
#[derive(Debug, Serialize)]
pub struct ProductWithSkus {
#[serde(flatten)]
pub product: Product,
pub skus: Vec<Sku>,
pub sold_count: i64,
}
#[derive(Deserialize)]
pub struct PublicListQuery {
pub page: Option<i64>,
pub per_page: Option<i64>,
pub category_id: Option<Uuid>,
pub brand_id: Option<Uuid>,
pub shop_id: Option<Uuid>,
pub q: Option<String>,
pub sort: Option<String>,
pub order: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SortBy {
Newest,
Price,
Sales,
}
impl PublicListQuery {
pub fn sort_by(&self) -> ApiResult<SortBy> {
match self.sort.as_deref() {
None => Ok(SortBy::Newest),
Some("price") => Ok(SortBy::Price),
Some("sales") => Ok(SortBy::Sales),
Some(other) => Err(ApiError::BadRequest(format!("unsupported sort: {other}"))),
}
}
pub fn ascending(&self) -> ApiResult<bool> {
match self.order.as_deref() {
None | Some("asc") => Ok(true),
Some("desc") => Ok(false),
Some(other) => Err(ApiError::BadRequest(format!("unsupported order: {other}"))),
}
}
}
#[derive(Deserialize)]
pub struct ProductBody {
pub category_id: Option<Uuid>,
pub brand_id: Option<Uuid>,
pub slug: String,
pub name: serde_json::Value,
pub description: Option<serde_json::Value>,
pub images: Option<serde_json::Value>,
}
#[derive(Deserialize)]
pub struct SkuBody {
pub sku_code: String,
pub attributes: Option<serde_json::Value>,
pub price_minor: i64,
pub currency: String,
pub stock: i32,
pub active: Option<bool>,
}