fix(cleanup): don't flag a character's fandom (or a chaptered series) as unused
CI / lint (push) Failing after 3s
CI / frontend-build (push) Successful in 23s
CI / backend-lint-and-test (push) Successful in 26s
CI / integration (push) Successful in 3m7s

find_unused_tags only excluded tags with image_tag or series_page references, so
it flagged every fandom as 'unused' — fandoms are NEVER applied to images (a
character carries its fandom via tag.fandom_id), and the FK is ondelete=SET NULL,
so deleting one silently strips the fandom off all its characters
(operator-flagged 2026-06-08: artist-OC fandoms showing as unused).

Exclude tags referenced as a character's fandom_id, and (same class of gap) tags
referenced by a series_chapter (an all-placeholder series has chapters but no
pages yet). A genuinely orphaned fandom with no characters is still swept.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-08 08:41:27 -04:00
parent e90e6b2c34
commit fb05c5eef7
2 changed files with 46 additions and 5 deletions
+25
View File
@@ -155,6 +155,31 @@ def test_find_unused_tags_returns_only_unreferenced(db_sync, tmp_path):
assert names.index("aaa-unused") < names.index("zzz-unused")
def test_find_unused_tags_excludes_fandom_referenced_by_character(db_sync):
# A fandom is never on an image — a character carries it via fandom_id — so
# an assigned fandom must NOT be flagged unused (deleting it SET-NULLs the
# fandom off its characters). Operator-flagged 2026-06-08.
fandom = _make_tag(db_sync, name="Creux", kind=TagKind.fandom)
char = _make_tag(db_sync, name="OcChar", kind=TagKind.character)
char.fandom_id = fandom.id
orphan_fandom = _make_tag(db_sync, name="NobodysFandom", kind=TagKind.fandom)
db_sync.commit()
names = [t.name for t in cleanup_service.find_unused_tags(db_sync)]
assert "Creux" not in names # referenced by a character → kept
assert "NobodysFandom" in names # genuinely orphaned → still swept
def test_find_unused_tags_excludes_series_with_only_chapters(db_sync):
# An all-placeholder series has chapters but no pages yet — not unused.
series = _make_tag(db_sync, name="EmptySeries", kind=TagKind.series)
db_sync.add(SeriesChapter(series_tag_id=series.id, chapter_number=1))
db_sync.commit()
names = [t.name for t in cleanup_service.find_unused_tags(db_sync)]
assert "EmptySeries" not in names
# --- unlink_image_files ---------------------------------------------