[BE-04] OrderProposal 애그리게이트

작업 내용 (설계 의도)

변경 사항

주문 제안을 Entity로 만든다. 거부된 후보까지 전량 기록해 감사 로그를 겸하는 것이 설계 의도다 — 별도 로그 테이블을 두지 않고 “왜 이 주문이 나갔는가 / 왜 안 나갔는가”를 이 한 테이블로 재구성한다(PRD FR-24).

따라서 신호 근거(점수·등급)·사이징 근거(자본·비율·산출 주수)·게이트 판정 결과를 함께 보유한다. 상태 전이는 enum canTransitTo()로 캡슐화하고, 종결 상태(EXECUTED·EXPIRED·REJECTED_*)에서의 재전이를 거부한다.

상태 전이 표는 TDD “상태 전이 표”를 따른다.

의존

  • BE-01 (도메인 계약), DB-01 (스키마)

다이어그램

처리 흐름

sequenceDiagram
    participant Svc as AutoTradingDomainService
    participant P as OrderProposal
    Svc->>P: create(candidate, sizing, decision)
    Svc->>P: approve()
    P-->>Svc: APPROVED
    Svc->>P: markExecuted(fillId)
    P-->>Svc: EXECUTED

클래스 의존

flowchart LR
    Entity[OrderProposal] --> Status[OrderProposalStatus]
    Entity --> Decision[RiskDecision]
    Repo[OrderProposalRepository] -.->|implements| Impl[OrderProposalRepositoryImpl]
    Impl --> Table[(order_proposals)]

테스트 케이스

  • 게이트 통과 + 임계 이하로 생성하면 AUTO_EXECUTED 상태가 된다.
  • 게이트 거부로 생성하면 REJECTED_BY_RISK가 되고 거부 사유가 보존된다.
  • PENDING 제안을 승인하면 APPROVED로 전이한다.
  • 만료된 제안을 승인하면 거부된다(상태 보호).
  • EXECUTED 제안에 다시 approve()를 호출하면 거부된다(종결 상태 불변).
  • 킬 스위치 시 PENDINGINVALIDATED로 전이한다.
  • findAllPending()이 종결 상태 제안을 반환하지 않는다(TestContainers MySQL).