[BE-23] Post 도메인 모델 확장 (communityId·sportCategory·globalListed + NOTICE 규칙)

작업 내용 (설계 의도)

변경 사항

근거 TDD: 20260707-post-community-연동-tdd.md Detail Design “인터페이스 시그니처”. Post(domain/post/entity/Post.kt)에 communityId: Long?·sportCategory: SportCategory?(공유 커널)·globalListed: Boolean 필드를 추가하고 get()-only 노출(currentCommunityId/currentSportCategory/isGlobalListed)한다. 팩토리 2종:

  • create(userId, title, content, type=FREE, sportCategory=null) — 전역, communityId=null, globalListed=true (FR-4/5 하위호환)
  • createInCommunity(userId, title, content, type, communityId, sportCategory, authorIsHost, communityIsPublic) — NOTICE 규칙 내장: type==NOTICE && !authorIsHost → NoticeRequiresHostException(신규 예외, 403 매핑). sportCategory=인자(모임 상속값), globalListed=communityIsPublic (FR-7/5, C-1)

Community(domain/community/entity/Community.kt)에 순수 질의 isHostedBy(userId: Long): Boolean = hostUserId == userId 추가(throw 없음, no-external-state-check 회피용 캡슐화). domain.post는 domain.community를 import하지 않는다 — SportCategory는 common, host/공개 여부는 UseCase가 primitive로 주입(R1).

롤백

필드 additive, 이전 이미지 재기동.

의존

  • BE-20 (SportCategory in domain.common.vo)

다이어그램

클래스 의존

flowchart LR
    Post -->|createInCommunity| notice[NOTICE→host 규칙]
    Post -.->|typed| SC[common.SportCategory]
    Community --> isHostedBy[isHostedBy 질의]
    notice --> ex[NoticeRequiresHostException]

테스트 케이스

  • createInCommunity NOTICE+authorIsHost=true → 생성된다
  • createInCommunity NOTICE+authorIsHost=false → NoticeRequiresHostException
  • createInCommunity FREE+authorIsHost=false → 생성된다(비-NOTICE는 host 무관)
  • createInCommunity communityIsPublic=false → globalListed=false / true → globalListed=true
  • createInCommunity sportCategory 인자가 그대로 상속 저장된다
  • create(전역) → communityId=null, globalListed=true, sportCategory 지정/미지정 모두 허용
  • Community.isHostedBy(host userId)=true / 타 userId=false
  • Post 도메인 파일에 import com.sportsapp.domain.community.* 0건 (R1)