feat: ensure deletion of custom fields and values when a board is deleted

This commit is contained in:
Abhimanyu Saharan
2026-02-16 00:44:40 +05:30
parent 1d63bd0148
commit 47dfc1b52f
2 changed files with 18 additions and 1 deletions

View File

@@ -23,6 +23,7 @@ from app.models.board_webhooks import BoardWebhook
from app.models.organization_board_access import OrganizationBoardAccess from app.models.organization_board_access import OrganizationBoardAccess
from app.models.organization_invite_board_access import OrganizationInviteBoardAccess from app.models.organization_invite_board_access import OrganizationInviteBoardAccess
from app.models.tag_assignments import TagAssignment from app.models.tag_assignments import TagAssignment
from app.models.task_custom_fields import BoardTaskCustomField, TaskCustomFieldValue
from app.models.task_dependencies import TaskDependency from app.models.task_dependencies import TaskDependency
from app.models.task_fingerprints import TaskFingerprint from app.models.task_fingerprints import TaskFingerprint
from app.models.tasks import Task from app.models.tasks import Task
@@ -84,6 +85,12 @@ async def delete_board(session: AsyncSession, *, board: Board) -> OkResponse:
col(TagAssignment.task_id).in_(task_ids), col(TagAssignment.task_id).in_(task_ids),
commit=False, commit=False,
) )
await crud.delete_where(
session,
TaskCustomFieldValue,
col(TaskCustomFieldValue.task_id).in_(task_ids),
commit=False,
)
# Keep teardown ordered around FK/reference chains so dependent rows are gone # Keep teardown ordered around FK/reference chains so dependent rows are gone
# before deleting their parent task/agent/board records. # before deleting their parent task/agent/board records.
await crud.delete_where( await crud.delete_where(
@@ -129,6 +136,11 @@ async def delete_board(session: AsyncSession, *, board: Board) -> OkResponse:
OrganizationInviteBoardAccess, OrganizationInviteBoardAccess,
col(OrganizationInviteBoardAccess.board_id) == board.id, col(OrganizationInviteBoardAccess.board_id) == board.id,
) )
await crud.delete_where(
session,
BoardTaskCustomField,
col(BoardTaskCustomField.board_id) == board.id,
)
# Tasks reference agents and have dependent records. # Tasks reference agents and have dependent records.
# Delete tasks before agents. # Delete tasks before agents.

View File

@@ -64,13 +64,14 @@ async def test_delete_board_cleans_org_board_access_rows() -> None:
deleted_table_names = [statement.table.name for statement in session.executed] deleted_table_names = [statement.table.name for statement in session.executed]
assert "organization_board_access" in deleted_table_names assert "organization_board_access" in deleted_table_names
assert "organization_invite_board_access" in deleted_table_names assert "organization_invite_board_access" in deleted_table_names
assert "board_task_custom_fields" in deleted_table_names
assert board in session.deleted assert board in session.deleted
assert session.committed == 1 assert session.committed == 1
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_delete_board_cleans_tag_assignments_before_tasks() -> None: async def test_delete_board_cleans_tag_assignments_before_tasks() -> None:
"""Deleting a board should remove task-tag links before deleting tasks.""" """Deleting a board should remove task-linked rows before deleting tasks."""
session: Any = _FakeSession(exec_results=[[], [uuid4()]]) session: Any = _FakeSession(exec_results=[[], [uuid4()]])
board = Board( board = Board(
id=uuid4(), id=uuid4(),
@@ -87,7 +88,11 @@ async def test_delete_board_cleans_tag_assignments_before_tasks() -> None:
deleted_table_names = [statement.table.name for statement in session.executed] deleted_table_names = [statement.table.name for statement in session.executed]
assert "tag_assignments" in deleted_table_names assert "tag_assignments" in deleted_table_names
assert "task_custom_field_values" in deleted_table_names
assert deleted_table_names.index("tag_assignments") < deleted_table_names.index("tasks") assert deleted_table_names.index("tag_assignments") < deleted_table_names.index("tasks")
assert deleted_table_names.index("task_custom_field_values") < deleted_table_names.index(
"tasks"
)
@pytest.mark.asyncio @pytest.mark.asyncio