use axum::Extension; use axum::extract::{FromRef, Path, Query, State}; use axum::response::Json; use validator::Validate; use erp_core::error::AppError; use erp_core::rbac::require_permission; use erp_core::types::{ApiResponse, PaginatedResponse, Pagination, TenantContext}; use uuid::Uuid; use crate::dto::{ProcessInstanceResp, StartInstanceReq}; use crate::service::instance_service::InstanceService; use crate::workflow_state::WorkflowState; #[utoipa::path( post, path = "/api/v1/workflow/instances", request_body = StartInstanceReq, responses( (status = 200, description = "成功", body = ApiResponse), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), ), security(("bearer_auth" = [])), tag = "流程实例" )] /// POST /api/v1/workflow/instances pub async fn start_instance( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> Result>, AppError> where WorkflowState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "workflow.start")?; req.validate() .map_err(|e| AppError::Validation(e.to_string()))?; let resp = InstanceService::start( ctx.tenant_id, ctx.user_id, &req, &state.db, &state.event_bus, ) .await?; Ok(Json(ApiResponse::ok(resp))) } #[utoipa::path( get, path = "/api/v1/workflow/instances", params(Pagination), responses( (status = 200, description = "成功", body = ApiResponse>), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), ), security(("bearer_auth" = [])), tag = "流程实例" )] /// GET /api/v1/workflow/instances pub async fn list_instances( State(state): State, Extension(ctx): Extension, Query(pagination): Query, ) -> Result>>, AppError> where WorkflowState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "workflow.list")?; let (instances, total) = InstanceService::list(ctx.tenant_id, &pagination, &state.db).await?; let page = pagination.page.unwrap_or(1); let page_size = pagination.limit(); let total_pages = total.div_ceil(page_size); Ok(Json(ApiResponse::ok(PaginatedResponse { data: instances, total, page, page_size, total_pages, }))) } #[utoipa::path( get, path = "/api/v1/workflow/instances/{id}", params(("id" = Uuid, Path, description = "流程实例ID")), responses( (status = 200, description = "成功", body = ApiResponse), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "流程实例不存在"), ), security(("bearer_auth" = [])), tag = "流程实例" )] /// GET /api/v1/workflow/instances/{id} pub async fn get_instance( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where WorkflowState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "workflow.read")?; let resp = InstanceService::get_by_id(id, ctx.tenant_id, &state.db).await?; Ok(Json(ApiResponse::ok(resp))) } #[utoipa::path( post, path = "/api/v1/workflow/instances/{id}/suspend", params(("id" = Uuid, Path, description = "流程实例ID")), responses( (status = 200, description = "成功"), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "流程实例不存在"), ), security(("bearer_auth" = [])), tag = "流程实例" )] /// POST /api/v1/workflow/instances/{id}/suspend pub async fn suspend_instance( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where WorkflowState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "workflow.update")?; InstanceService::suspend(id, ctx.tenant_id, ctx.user_id, &state.db).await?; Ok(Json(ApiResponse::ok(()))) } #[utoipa::path( post, path = "/api/v1/workflow/instances/{id}/terminate", params(("id" = Uuid, Path, description = "流程实例ID")), responses( (status = 200, description = "成功"), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "流程实例不存在"), ), security(("bearer_auth" = [])), tag = "流程实例" )] /// POST /api/v1/workflow/instances/{id}/terminate pub async fn terminate_instance( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where WorkflowState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "workflow.update")?; InstanceService::terminate(id, ctx.tenant_id, ctx.user_id, &state.db).await?; Ok(Json(ApiResponse::ok(()))) } #[utoipa::path( post, path = "/api/v1/workflow/instances/{id}/resume", params(("id" = Uuid, Path, description = "流程实例ID")), responses( (status = 200, description = "成功"), (status = 401, description = "未授权"), (status = 403, description = "权限不足"), (status = 404, description = "流程实例不存在"), ), security(("bearer_auth" = [])), tag = "流程实例" )] /// POST /api/v1/workflow/instances/{id}/resume pub async fn resume_instance( State(state): State, Extension(ctx): Extension, Path(id): Path, ) -> Result>, AppError> where WorkflowState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "workflow.update")?; InstanceService::resume(id, ctx.tenant_id, ctx.user_id, &state.db).await?; Ok(Json(ApiResponse::ok(()))) }