raisfast 0.2.19

The last backend you'll ever need. Rust-powered headless CMS with built-in blog, ecommerce, wallet, payment and 4 plugin engines.
use crate::dto::ecommerce::{
    CreateProductVariantRequest, ProductVariantResponse, UpdateProductVariantRequest,
};
use crate::errors::app_error::AppResult;
use crate::errors::response::ApiResponse;
use crate::errors::validation;
use crate::middleware::auth::AuthUser;
use axum::Json;
use axum::extract::{Path, State};

pub fn routes(
    registry: &mut crate::server::RouteRegistry,
    config: &crate::config::app::AppConfig,
) -> axum::Router<crate::AppState> {
    let restful = config.api_restful;
    let r = axum::Router::new();
    let r = reg_route!(
        r,
        registry,
        restful,
        "/products/{product_id}/variants",
        get,
        list_by_product,
        "system public",
        "product_variants"
    );
    let r = reg_route!(
        r,
        registry,
        restful,
        "/admin/product-variants",
        create,
        admin_create,
        "system admin",
        "admin/product_variants"
    );
    let r = reg_route!(
        r,
        registry,
        restful,
        "/admin/product-variants/{id}",
        put,
        admin_update,
        "system admin",
        "admin/product_variants"
    );
    reg_route!(
        r,
        registry,
        restful,
        "/admin/product-variants/{id}",
        delete,
        admin_delete,
        "system admin",
        "admin/product_variants"
    )
}

pub async fn list_by_product(
    auth: AuthUser,
    State(state): State<crate::AppState>,
    Path(product_id): Path<String>,
) -> AppResult<ApiResponse<Vec<ProductVariantResponse>>> {
    let variants = state
        .product_variant_service
        .list_by_product(&auth, &product_id)
        .await?;
    let resp: Vec<ProductVariantResponse> = variants.into_iter().map(Into::into).collect();
    Ok(ApiResponse::success(resp))
}

pub async fn admin_create(
    auth: AuthUser,
    State(state): State<crate::AppState>,
    Json(req): Json<CreateProductVariantRequest>,
) -> AppResult<ApiResponse<ProductVariantResponse>> {
    auth.ensure_admin()?;
    validation::validate(&req)?;
    let v = state.product_variant_service.create(&auth, req).await?;
    Ok(ApiResponse::success(ProductVariantResponse::from(v)))
}

pub async fn admin_update(
    auth: AuthUser,
    State(state): State<crate::AppState>,
    Path(id): Path<String>,
    Json(req): Json<UpdateProductVariantRequest>,
) -> AppResult<ApiResponse<ProductVariantResponse>> {
    auth.ensure_admin()?;
    validation::validate(&req)?;
    let id = crate::types::snowflake_id::parse_id(&id)?;
    let v = state.product_variant_service.update(&auth, id, req).await?;
    Ok(ApiResponse::success(ProductVariantResponse::from(v)))
}

pub async fn admin_delete(
    auth: AuthUser,
    State(state): State<crate::AppState>,
    Path(id): Path<String>,
) -> AppResult<ApiResponse<()>> {
    auth.ensure_admin()?;
    let id = crate::types::snowflake_id::parse_id(&id)?;
    state.product_variant_service.delete(&auth, id).await?;
    Ok(ApiResponse::success(()))
}