bulk operations fixes

- Frontend: implémente bulkDelete, bulkArchive, bulkRestore
- Backend: adapts ticket DTOs pour bulk operations
- Infrastructure: MCP server pour gestion bulk tickets
- Tests: coverage frontend + backend
This commit is contained in:
2026-07-28 20:38:07 +02:00
parent 73c6081ab8
commit bd4f76ae74
19 changed files with 597 additions and 35 deletions

View File

@ -280,6 +280,7 @@ pub fn run() {
tickets::ticket_delete,
tickets::ticket_bulk_update_status,
tickets::ticket_bulk_update_priority,
tickets::ticket_bulk_delete,
tickets::open_ticket_chat,
tickets::close_ticket_chat,
tickets::ticket_list,

View File

@ -344,7 +344,9 @@ fn is_ticket_policy_mutation_tool(name: &str) -> bool {
fn is_ticket_policy_bulk_mutation_tool(name: &str) -> bool {
matches!(
name,
"idea_ticket_bulk_update_status" | "idea_ticket_bulk_update_priority"
"idea_ticket_bulk_update_status"
| "idea_ticket_bulk_update_priority"
| "idea_ticket_bulk_delete"
)
}

View File

@ -68,6 +68,7 @@ impl AppState {
update: Arc::clone(&core.update_issue),
bulk_update_status: Arc::clone(&core.bulk_update_issue_status),
bulk_update_priority: Arc::clone(&core.bulk_update_issue_priority),
bulk_delete: Arc::clone(&core.bulk_delete_issues),
read_carnet: Arc::clone(&core.read_issue_carnet),
update_carnet: Arc::clone(&core.update_issue_carnet),
link: Arc::clone(&core.link_issues),

View File

@ -31,6 +31,7 @@ pub struct AppTicketToolProvider {
pub update: Arc<application::UpdateIssue>,
pub bulk_update_status: Arc<application::BulkUpdateIssueStatus>,
pub bulk_update_priority: Arc<application::BulkUpdateIssuePriority>,
pub bulk_delete: Arc<application::BulkDeleteIssues>,
pub read_carnet: Arc<application::ReadIssueCarnet>,
pub update_carnet: Arc<application::UpdateIssueCarnet>,
pub link: Arc<application::LinkIssues>,
@ -204,6 +205,14 @@ impl TicketToolProvider for AppTicketToolProvider {
.await;
json!(TicketBulkResultDto::from(out))
}
"idea_ticket_bulk_delete" => {
let req = mcp_bulk_delete_request(project, arguments)?;
let out = self
.bulk_delete
.execute(bulk_delete_input(project.clone(), req).map_err(dto_tool_error)?)
.await;
json!(TicketBulkResultDto::from(out))
}
"idea_ticket_read_carnet" => {
let carnet = self
.read_carnet
@ -390,6 +399,19 @@ pub async fn ticket_bulk_update_priority(
Ok(TicketBulkResultDto::from(out))
}
#[tauri::command]
pub async fn ticket_bulk_delete(
request: TicketBulkDeleteRequestDto,
state: State<'_, AppState>,
) -> Result<TicketBulkResultDto, ErrorDto> {
let project = resolve_project(&state, &request.project_id).await?;
let out = state
.bulk_delete_issues
.execute(bulk_delete_input(project, request)?)
.await;
Ok(TicketBulkResultDto::from(out))
}
#[tauri::command]
pub async fn open_ticket_chat(
request: OpenTicketChatRequestDto,
@ -844,6 +866,16 @@ fn mcp_bulk_update_priority_request(
Ok(req)
}
fn mcp_bulk_delete_request(
project: &Project,
arguments: Value,
) -> Result<TicketBulkDeleteRequestDto, TicketToolError> {
let mut req: TicketBulkDeleteRequestDto = serde_json::from_value(arguments)
.map_err(|e| TicketToolError::new("invalid", e.to_string()))?;
req.project_id = project.id.to_string();
Ok(req)
}
fn parse_json_ref(arguments: &Value, key: &str) -> Result<IssueRef, TicketToolError> {
required_str(arguments, key).and_then(|raw| parse_ref_dto(raw).map_err(dto_tool_error))
}