fix: clean up folder and tag assignments on tree soft delete

When a tree is soft-deleted, folder assignments and tag assignments are
now removed from junction tables. Tag usage counts are decremented with
a floor of zero to prevent negative counts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-02-06 00:23:24 -05:00
parent 02e00963e1
commit 5ae22e041f
2 changed files with 100 additions and 3 deletions

View File

@@ -3,15 +3,15 @@ from typing import Annotated, Optional
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, or_, true as sa_true
from sqlalchemy import select, func, or_, true as sa_true, update
from sqlalchemy.orm import selectinload
from app.core.database import get_db
from app.models.tree import Tree
from app.models.user import User
from app.models.category import TreeCategory
from app.models.tag import TreeTag
from app.models.folder import UserFolder
from app.models.tag import TreeTag, tree_tag_assignments
from app.models.folder import UserFolder, user_folder_trees
from app.schemas.tree import TreeCreate, TreeUpdate, TreeResponse, TreeListResponse, CategoryInfo
from app.api.deps import get_current_active_user, require_engineer_or_admin, require_admin
from app.core.permissions import can_edit_tree, can_access_tree
@@ -522,6 +522,31 @@ async def delete_tree(
tree.is_active = False
tree.deleted_at = datetime.now(timezone.utc)
tree.deleted_by = current_user.id
# Clean up folder assignments
await db.execute(
user_folder_trees.delete().where(user_folder_trees.c.tree_id == tree.id)
)
# Decrement usage_count on associated tags (floor at 0)
tag_ids_result = await db.execute(
select(tree_tag_assignments.c.tag_id).where(
tree_tag_assignments.c.tree_id == tree.id
)
)
tag_ids = [row[0] for row in tag_ids_result.fetchall()]
if tag_ids:
await db.execute(
update(TreeTag)
.where(TreeTag.id.in_(tag_ids))
.values(usage_count=func.greatest(TreeTag.usage_count - 1, 0))
)
# Clean up tag assignments
await db.execute(
tree_tag_assignments.delete().where(tree_tag_assignments.c.tree_id == tree.id)
)
await log_audit(db, current_user.id, "tree.delete", "tree", tree.id,
{"tree_name": tree.name})
await db.commit()