journal: multi-select emotions and per-category writing templates

- Mood switches from a single enum column to a many-to-many
  JournalEntryMood table so an entry can carry several feelings at
  once; the vocabulary is trimmed to 9 named emotions (dropped the
  overlapping satisfaction scale) with unified noun-style labels.
- Categories can define a content_template that pre-fills the "new
  entry" textarea when selected (only if the user hasn't started
  typing), seeded with a Story/Feelings/Decisions/Insights/Actions
  reflection template on the default "일상" category.
- Fixes a real attribute-injection bug found while building the
  template feature: Jinja's built-in |tojson filter doesn't escape
  double quotes, which breaks a double-quoted x-data="..." attribute
  when the JSON payload contains one; added |forceescape and a
  regression test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 19:12:59 +09:00
co-authored by Claude Sonnet 5
parent 54c971875c
commit c466cc6639
8 changed files with 172 additions and 9 deletions
+13
View File
@@ -41,12 +41,25 @@ def _upload(filename: str, content_type: str, data: bytes) -> UploadFile:
def test_ensure_default_category_creates_once(db_session, test_user):
first = journal_service.ensure_default_category(db_session, test_user.id)
assert first.name == journal_service.DEFAULT_CATEGORY_NAME
assert first.content_template == journal_service.DEFAULT_CATEGORY_TEMPLATE.strip()
second = journal_service.ensure_default_category(db_session, test_user.id)
assert second.id == first.id
assert len(journal_service.list_categories(db_session, test_user.id)) == 1
def test_category_content_template_persists_and_updates(db_session, test_user):
category = journal_service.create_category(
db_session, test_user.id, JournalCategoryCreate(name="회고", content_template="질문 1\n\n질문 2")
)
assert category.content_template == "질문 1\n\n질문 2"
updated = journal_service.update_category(
db_session, category, JournalCategoryCreate(name="회고", content_template=" ")
)
assert updated.content_template is None
def test_list_categories_scoped_to_user(db_session, test_user, other_user):
_make_category(db_session, test_user.id, name="일상")
_make_category(db_session, other_user.id, name="남의 카테고리")