[STK5-03] order/holding 도메인 Entity·DomainService + 토스 주문·보유 Gateway 구현
작업 내용 (설계 의도)
변경 사항
order·holding 도메인 패키지 2개를 신규 구성한다. STK5-02(account 도메인)과 별도 패키지이므로 병렬 진행 가능하다.
구성 범위:
- order domain:
OrderEntity,OrderType·OrderPriceType·OrderStatus(canTransitTo 포함) +OrderDomainService+OrderGateway·OrderRepositoryinterface - order infrastructure:
TossOrderGateway(주문 접수·정정·취소 Toss API 호출) +OrderRepositoryImpl+OrderJpaRepository+OrderEntity - holding domain:
HoldingEntity,TradeHistoryEntity,TradeType+HoldingDomainService+HoldingGateway·HoldingRepository·TradeHistoryRepositoryinterface - holding infrastructure:
TossHoldingGateway(보유종목·거래내역 Toss API 호출) +HoldingRepositoryImpl·TradeHistoryRepositoryImpl+ JPA 구현체 - application:
OrderResponse,HoldingResponse,TradeHistoryResponse
TossOrderGateway와 TossHoldingGateway 모두 TOSS_USER_TOKEN 헤더를 사용한다.
다이어그램
클래스 의존
flowchart LR subgraph OrderDomain["order domain"] ODS[OrderDomainService] OGW[OrderGateway] OR[OrderRepository] Order[Order Entity] OS[OrderStatus] end subgraph HoldingDomain["holding domain"] HDS[HoldingDomainService] HGW[HoldingGateway] HR[HoldingRepository] THR[TradeHistoryRepository] Holding[Holding Entity] TH[TradeHistory Entity] end subgraph OrderInfra["order infrastructure"] TOG[TossOrderGateway] ORI[OrderRepositoryImpl] end subgraph HoldingInfra["holding infrastructure"] THG[TossHoldingGateway] HRI[HoldingRepositoryImpl] THRI[TradeHistoryRepositoryImpl] end ODS --> OGW ODS --> OR ODS --> Order Order --> OS HDS --> HGW HDS --> HR HDS --> THR HDS --> Holding HDS --> TH TOG -.->|implements| OGW ORI -.->|implements| OR THG -.->|implements| HGW HRI -.->|implements| HR THRI -.->|implements| THR
처리 흐름 (주문 접수)
sequenceDiagram participant DS as OrderDomainService participant G as OrderGateway participant R as OrderRepository DS->>G: placeOrder(accountNumber, symbol, type, priceType, quantity, price) alt Toss 성공 G-->>DS: tossOrderId DS->>R: save(Order(tossOrderId, PENDING)) R-->>DS: Order else Toss 실패 G-->>DS: 예외 (TossApiException) DS-->>DS: 예외 전파 (save 미실행) end
처리 흐름 (보유종목 fetch·upsert)
sequenceDiagram participant DS as HoldingDomainService participant G as HoldingGateway participant HR as HoldingRepository participant THR as TradeHistoryRepository DS->>G: fetchHoldings(accountNumber) G-->>DS: List<HoldingData> DS->>HR: upsertAll(holdings) HR-->>DS: List<Holding> DS->>G: fetchTradeHistory(accountNumber, from, to) G-->>DS: List<TradeHistoryData> DS->>THR: upsertAll(tradeHistories) THR-->>DS: List<TradeHistory>
테스트 케이스
COMPLETED상태의Order에cancel()을 호출하면InvalidOrderStateException이 발생하고 상태가 변경되지 않는다.PENDING상태의Order에cancel()을 호출하면 상태가CANCELLED로 전이된다.PENDING상태의Order에correct(newQuantity, newPrice)를 호출하면 상태가CORRECTED로 전이되고 수량·가격이 갱신된다.CANCELLED상태의Order에correct()를 호출하면InvalidOrderStateException이 발생한다.OrderStatus.canTransitTo()에서COMPLETED → PENDING전이는 false를 반환한다.Toss OrderGateway실패 시OrderDomainService는OrderRepository.save()를 호출하지 않는다.- 동일
(account_number, symbol)보유종목을 2회 upsert하면 행이 1건으로 유지되고refreshed_at이 최신값으로 갱신된다. - 동일
toss_transaction_id거래내역 upsert 2회 시 중복 저장 없이 멱등하게 처리된다.