mirror of
https://codeberg.org/likwid/likwid.git
synced 2026-02-10 05:23:09 +00:00
160 lines
4.8 KiB
Rust
160 lines
4.8 KiB
Rust
|
|
//! Decision Workflows API endpoints.
|
||
|
|
|
||
|
|
use axum::{
|
||
|
|
extract::{Path, State},
|
||
|
|
http::StatusCode,
|
||
|
|
routing::{get, post},
|
||
|
|
Json, Router,
|
||
|
|
};
|
||
|
|
use serde::Deserialize;
|
||
|
|
use serde_json::{json, Value};
|
||
|
|
use sqlx::PgPool;
|
||
|
|
use uuid::Uuid;
|
||
|
|
|
||
|
|
use crate::auth::AuthUser;
|
||
|
|
use crate::plugins::builtin::decision_workflows::{
|
||
|
|
WorkflowInstance, WorkflowPhase, WorkflowService, WorkflowTemplate,
|
||
|
|
};
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Request Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
#[derive(Debug, Deserialize)]
|
||
|
|
pub struct CreateTemplateRequest {
|
||
|
|
pub name: String,
|
||
|
|
pub description: Option<String>,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug, Deserialize)]
|
||
|
|
pub struct AddPhaseRequest {
|
||
|
|
pub name: String,
|
||
|
|
pub phase_type: String,
|
||
|
|
pub sequence_order: i32,
|
||
|
|
pub duration_hours: i32,
|
||
|
|
pub quorum_value: f64,
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Handlers
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/// List workflow templates for a community
|
||
|
|
async fn list_templates(
|
||
|
|
Path(community_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
) -> Result<Json<Vec<WorkflowTemplate>>, (StatusCode, String)> {
|
||
|
|
let templates = WorkflowService::list_templates(&pool, Some(community_id))
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(templates))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Create a new workflow template
|
||
|
|
async fn create_template(
|
||
|
|
auth: AuthUser,
|
||
|
|
Path(community_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
Json(req): Json<CreateTemplateRequest>,
|
||
|
|
) -> Result<Json<Value>, (StatusCode, String)> {
|
||
|
|
let template_id = WorkflowService::create_template(
|
||
|
|
&pool,
|
||
|
|
community_id,
|
||
|
|
&req.name,
|
||
|
|
req.description.as_deref(),
|
||
|
|
auth.user_id,
|
||
|
|
)
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(json!({"id": template_id})))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Get phases for a template
|
||
|
|
async fn get_template_phases(
|
||
|
|
Path(template_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
) -> Result<Json<Vec<WorkflowPhase>>, (StatusCode, String)> {
|
||
|
|
let phases = WorkflowService::get_template_phases(&pool, template_id)
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(phases))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Add a phase to a template
|
||
|
|
async fn add_phase(
|
||
|
|
_auth: AuthUser,
|
||
|
|
Path(template_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
Json(req): Json<AddPhaseRequest>,
|
||
|
|
) -> Result<Json<Value>, (StatusCode, String)> {
|
||
|
|
let phase_id = WorkflowService::add_phase(
|
||
|
|
&pool,
|
||
|
|
template_id,
|
||
|
|
&req.name,
|
||
|
|
&req.phase_type,
|
||
|
|
req.sequence_order,
|
||
|
|
req.duration_hours,
|
||
|
|
req.quorum_value,
|
||
|
|
)
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(json!({"id": phase_id})))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Get workflow for a proposal
|
||
|
|
async fn get_workflow_for_proposal(
|
||
|
|
Path(proposal_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
) -> Result<Json<Option<WorkflowInstance>>, (StatusCode, String)> {
|
||
|
|
let workflow = WorkflowService::get_workflow_for_proposal(&pool, proposal_id)
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(workflow))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Get workflow progress
|
||
|
|
async fn get_workflow_progress(
|
||
|
|
Path(proposal_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
) -> Result<Json<Value>, (StatusCode, String)> {
|
||
|
|
let progress = WorkflowService::get_workflow_progress(&pool, proposal_id)
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(progress))
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Manually advance workflow phase
|
||
|
|
async fn advance_phase(
|
||
|
|
auth: AuthUser,
|
||
|
|
Path(proposal_id): Path<Uuid>,
|
||
|
|
State(pool): State<PgPool>,
|
||
|
|
) -> Result<Json<Value>, (StatusCode, String)> {
|
||
|
|
let success = WorkflowService::advance_phase(&pool, proposal_id, Some(auth.user_id), None)
|
||
|
|
.await
|
||
|
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||
|
|
|
||
|
|
Ok(Json(json!({"success": success})))
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Router
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
pub fn router(pool: PgPool) -> Router {
|
||
|
|
Router::new()
|
||
|
|
// Templates
|
||
|
|
.route("/api/communities/{community_id}/workflow-templates", get(list_templates).post(create_template))
|
||
|
|
.route("/api/workflow-templates/{template_id}/phases", get(get_template_phases).post(add_phase))
|
||
|
|
// Proposal workflows
|
||
|
|
.route("/api/proposals/{proposal_id}/workflow", get(get_workflow_for_proposal))
|
||
|
|
.route("/api/proposals/{proposal_id}/workflow/progress", get(get_workflow_progress))
|
||
|
|
.route("/api/proposals/{proposal_id}/workflow/advance", post(advance_phase))
|
||
|
|
.with_state(pool)
|
||
|
|
}
|