Add public packages endpoint and register in gateway
- pricing.rs: public GET /api/packages?role= for user-facing package list - main.rs: nest /api/packages public route - gateway: route /api/packages to users service Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d900c361d8
commit
2312f5dfdc
3 changed files with 67 additions and 0 deletions
|
|
@ -79,6 +79,7 @@ impl Services {
|
|||
|| path.starts_with("/api/notifications")
|
||||
|| path.starts_with("/api/config")
|
||||
|| path.starts_with("/api/kb")
|
||||
|| path.starts_with("/api/packages")
|
||||
|| path.starts_with("/api/support")
|
||||
|| path.starts_with("/api/admin/kb")
|
||||
|| path.starts_with("/api/admin/support-cases")
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ use uuid::Uuid;
|
|||
|
||||
// ── Routers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Public (user-facing) — list active packages for their role
|
||||
pub fn public_packages_router() -> Router<AppState> {
|
||||
Router::new().route("/", get(public_list_packages))
|
||||
}
|
||||
|
||||
/// Admin CRUD
|
||||
pub fn packages_router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", get(list_packages).post(create_package))
|
||||
|
|
@ -69,6 +75,64 @@ struct DateRangeQuery {
|
|||
|
||||
// ── Package handlers ──────────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct PackageQuery {
|
||||
role: Option<String>,
|
||||
}
|
||||
|
||||
async fn public_list_packages(
|
||||
State(state): State<AppState>,
|
||||
Query(params): Query<PackageQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let rows = if let Some(role) = params.role {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
SELECT id, name, role_key, package_type, tracecoins_amount, price_inr, description, is_active
|
||||
FROM pricing_packages
|
||||
WHERE is_active = true AND (role_key = $1 OR role_key = 'ALL')
|
||||
ORDER BY price_inr
|
||||
"#,
|
||||
role
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await
|
||||
} else {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
SELECT id, name, role_key, package_type, tracecoins_amount, price_inr, description, is_active
|
||||
FROM pricing_packages
|
||||
WHERE is_active = true
|
||||
ORDER BY role_key, price_inr
|
||||
"#
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await
|
||||
};
|
||||
|
||||
match rows {
|
||||
Ok(rows) => {
|
||||
let dtos: Vec<PackageDto> = rows
|
||||
.into_iter()
|
||||
.map(|r| PackageDto {
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
role_key: r.role_key,
|
||||
package_type: r.package_type,
|
||||
tracecoins_amount: r.tracecoins_amount,
|
||||
price_inr: r.price_inr,
|
||||
description: r.description,
|
||||
is_active: r.is_active,
|
||||
})
|
||||
.collect();
|
||||
(StatusCode::OK, Json(serde_json::json!({ "packages": dtos }))).into_response()
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to list packages: {e}");
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({ "error": "Failed to load packages" }))).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_packages(
|
||||
_auth: AuthUser,
|
||||
State(state): State<AppState>,
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ async fn main() {
|
|||
// ── Coupons & Discounts (admin) ───────────────────────────────────
|
||||
.nest("/api/admin/coupons", handlers::coupons::coupons_router())
|
||||
.nest("/api/admin/discounts", handlers::coupons::discounts_router())
|
||||
// ── Tracecoin Packages (public) ───────────────────────────────────
|
||||
.nest("/api/packages", handlers::pricing::public_packages_router())
|
||||
// ── Tracecoin Packages & Reports (admin) ──────────────────────────
|
||||
.nest("/api/admin/tracecoin-packages", handlers::pricing::packages_router())
|
||||
.nest("/api/admin/reports", handlers::pricing::reports_router())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue