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/notifications")
|
||||||
|| path.starts_with("/api/config")
|
|| path.starts_with("/api/config")
|
||||||
|| path.starts_with("/api/kb")
|
|| path.starts_with("/api/kb")
|
||||||
|
|| path.starts_with("/api/packages")
|
||||||
|| path.starts_with("/api/support")
|
|| path.starts_with("/api/support")
|
||||||
|| path.starts_with("/api/admin/kb")
|
|| path.starts_with("/api/admin/kb")
|
||||||
|| path.starts_with("/api/admin/support-cases")
|
|| path.starts_with("/api/admin/support-cases")
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@ use uuid::Uuid;
|
||||||
|
|
||||||
// ── Routers ───────────────────────────────────────────────────────────────────
|
// ── 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> {
|
pub fn packages_router() -> Router<AppState> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/", get(list_packages).post(create_package))
|
.route("/", get(list_packages).post(create_package))
|
||||||
|
|
@ -69,6 +75,64 @@ struct DateRangeQuery {
|
||||||
|
|
||||||
// ── Package handlers ──────────────────────────────────────────────────────────
|
// ── 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(
|
async fn list_packages(
|
||||||
_auth: AuthUser,
|
_auth: AuthUser,
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,8 @@ async fn main() {
|
||||||
// ── Coupons & Discounts (admin) ───────────────────────────────────
|
// ── Coupons & Discounts (admin) ───────────────────────────────────
|
||||||
.nest("/api/admin/coupons", handlers::coupons::coupons_router())
|
.nest("/api/admin/coupons", handlers::coupons::coupons_router())
|
||||||
.nest("/api/admin/discounts", handlers::coupons::discounts_router())
|
.nest("/api/admin/discounts", handlers::coupons::discounts_router())
|
||||||
|
// ── Tracecoin Packages (public) ───────────────────────────────────
|
||||||
|
.nest("/api/packages", handlers::pricing::public_packages_router())
|
||||||
// ── Tracecoin Packages & Reports (admin) ──────────────────────────
|
// ── Tracecoin Packages & Reports (admin) ──────────────────────────
|
||||||
.nest("/api/admin/tracecoin-packages", handlers::pricing::packages_router())
|
.nest("/api/admin/tracecoin-packages", handlers::pricing::packages_router())
|
||||||
.nest("/api/admin/reports", handlers::pricing::reports_router())
|
.nest("/api/admin/reports", handlers::pricing::reports_router())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue