From a74d2b6a3598c25452bf88ef820e105b4b0684f9 Mon Sep 17 00:00:00 2001 From: tobinio Date: Sun, 31 May 2026 14:57:52 +0200 Subject: [PATCH] recover tags / category --- api/services/src/todos.rs | 38 +++++++++++++++- api/tests/todos/delete.rs | 95 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 2 deletions(-) diff --git a/api/services/src/todos.rs b/api/services/src/todos.rs index 0ef72cc..d5af97d 100644 --- a/api/services/src/todos.rs +++ b/api/services/src/todos.rs @@ -6,7 +6,7 @@ use sea_orm::ActiveValue::{NotSet, Set}; use sea_orm::sea_query::Expr; use sea_orm::{ ColumnTrait, ConnectionTrait, EntityTrait, IntoActiveModel, ModelTrait, PaginatorTrait, - QueryFilter, QueryOrder, TransactionTrait, + QueryFilter, QueryOrder, TransactionTrait, Value, }; use serde::Deserialize; use thiserror::Error; @@ -17,7 +17,7 @@ use uuid::Uuid; use crate::User; use crate::categories::to_category_dto; use crate::tags::to_tag_dto; -use orm::entities::{check, prelude::*, time, todo, todo_tag}; +use orm::entities::{category, check, prelude::*, tag, time, todo, todo_tag}; #[derive(Error, Debug, PartialEq)] pub enum TodoServiceError { @@ -400,6 +400,7 @@ impl TodoService { db: &OrmConnection, id: Uuid, ) -> Result<(), TodoServiceError> { + // Restore todo Todo::update(todo::ActiveModel { id: Set(id), deleted: Set(None), @@ -409,6 +410,39 @@ impl TodoService { .exec(db) .await?; + // Load todo with relations + let todo = Todo::find_by_id(id) + .filter(todo::Column::OwnerId.eq(user.id.clone())) + .one(db) + .await? + .ok_or(TodoServiceError::NotFound)?; + + // Restore category + if let Some(category_id) = todo.category_id { + Category::update_many() + .col_expr( + category::Column::Deleted, + Expr::value(Value::TimeDate(None)), + ) + .filter(category::Column::Id.eq(category_id)) + .filter(category::Column::OwnerId.eq(user.id.clone())) + .exec(db) + .await?; + } + + // Restore tags + let tags = todo.find_related(Tag).all(db).await?; + let tag_ids: Vec = tags.into_iter().map(|t| t.id).collect(); + + if !tag_ids.is_empty() { + Tag::update_many() + .col_expr(tag::Column::Deleted, Expr::value(Value::TimeDate(None))) + .filter(tag::Column::Id.is_in(tag_ids)) + .filter(tag::Column::OwnerId.eq(user.id.clone())) + .exec(db) + .await?; + } + Ok(()) } diff --git a/api/tests/todos/delete.rs b/api/tests/todos/delete.rs index 83cfebe..a1aab7a 100644 --- a/api/tests/todos/delete.rs +++ b/api/tests/todos/delete.rs @@ -175,3 +175,98 @@ async fn get_deleted_todo_with_labels() { assert_eq!(todos.len(), 1); assert_eq!(todos[0], todo); } + +#[tokio::test] +async fn reactivate_deleted_todo_recover_labels() { + let client = get_client().await; + + let todo_uuid = Uuid::new_v4(); + let tag_uuid = Uuid::new_v4(); + let category_uuid = Uuid::new_v4(); + + client + .add_category_json(json!( + { + "uuid": category_uuid, + "name": "Test Category", + "color": "#233212", + "icon": "icon", + } + )) + .await; + + client + .add_tag_json(json!( + { + "uuid": tag_uuid, + "name": "Test Tag", + "color": "#233212", + } + )) + .await; + + let todo = Todo { + uuid: todo_uuid, + title: "Test Todo".to_string(), + note: "Test Note".to_string(), + time: None, + tags: Some(vec![Tag { + uuid: tag_uuid, + name: "Test Tag".to_string(), + color: HexColor::from_text("#233212").unwrap(), + }]), + category: Some(Category { + uuid: category_uuid, + name: "Test Category".to_string(), + color: HexColor::from_text("#233212").unwrap(), + icon: "icon".to_string(), + }), + checks: None, + }; + + client + .add_todo_json(json!( + { + "data": { + "uuid": todo_uuid, + "title": "Test Todo", + "note": "Test Note", + "tags": [tag_uuid], + "category": category_uuid, + } + } + )) + .await; + + client.delete_todo(todo_uuid).await.assert_status_success(); + client.delete_tag(tag_uuid).await.assert_status_success(); + client + .delete_category(category_uuid) + .await + .assert_status_success(); + + client + .reactivate_todo(todo_uuid) + .await + .assert_status_success(); + + let todos = client.get_deleted_todos_json().await; + assert_eq!(todos.len(), 0); + + let todos = client.get_todos_json().await; + assert_eq!(todos.len(), 1); + assert_eq!(todos[0], todo); + + let tags = client.get_tags_json().await; + assert_eq!(tags.len(), 1); + assert_eq!(tags[0].uuid, tag_uuid); + assert_eq!(tags[0].name, "Test Tag"); + assert_eq!(tags[0].color, HexColor::from_text("#233212").unwrap()); + + let categories = client.get_categories_json().await; + assert_eq!(categories.len(), 1); + assert_eq!(categories[0].uuid, category_uuid); + assert_eq!(categories[0].name, "Test Category"); + assert_eq!(categories[0].color, HexColor::from_text("#233212").unwrap()); + assert_eq!(categories[0].icon, "icon"); +} -- 2.51.2