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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
0b594c0147
commit
8446650baf
@@ -0,0 +1,11 @@
|
||||
use serde::Serialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Serialize, sqlx::FromRow)]
|
||||
pub struct Category {
|
||||
pub id: Uuid,
|
||||
pub parent_id: Option<Uuid>,
|
||||
pub name: serde_json::Value,
|
||||
pub slug: String,
|
||||
pub position: i32,
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
use axum::{extract::State, routing::get, Json, Router};
|
||||
|
||||
use crate::error::ApiResult;
|
||||
use crate::state::AppState;
|
||||
|
||||
use super::dto::Category;
|
||||
use super::service;
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new().route("/categories", get(list_categories))
|
||||
}
|
||||
|
||||
async fn list_categories(State(state): State<AppState>) -> ApiResult<Json<Vec<Category>>> {
|
||||
Ok(Json(service::list_categories(&state).await?))
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
mod dto;
|
||||
mod handlers;
|
||||
pub mod service;
|
||||
|
||||
use axum::Router;
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
handlers::router()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use crate::error::ApiResult;
|
||||
use crate::state::AppState;
|
||||
|
||||
use super::dto::Category;
|
||||
|
||||
pub(crate) const SUBTREE_CTE: &str = "WITH RECURSIVE subtree AS (
|
||||
SELECT id FROM categories WHERE id = $1::uuid
|
||||
UNION ALL
|
||||
SELECT c.id FROM categories c JOIN subtree st ON c.parent_id = st.id
|
||||
) ";
|
||||
|
||||
pub async fn list_categories(state: &AppState) -> ApiResult<Vec<Category>> {
|
||||
Ok(sqlx::query_as::<_, Category>(
|
||||
"SELECT id, parent_id, name, slug, position FROM categories ORDER BY position, slug",
|
||||
)
|
||||
.fetch_all(&state.db)
|
||||
.await?)
|
||||
}
|
||||
Reference in New Issue
Block a user