You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
결제(APPROVED) 기준으로 Order를 생성·조회·상태전이하고, 구매자/브랜드/어드민별로 권한이 다른 주문 라이프사이클 API입니다.
주문 상세는 Payment → PaymentIntentLine을 따라 주문에 묶인 모든 결제 라인아이템(상품/사이즈/색상/수량/금액)을 조회합니다.
구매확정 시 지갑 2% 적립, 환불/취소 승인 시 현금/포인트 환불, 쿠폰복구, 재고복원 옵션을 지원합니다.
MySQL용 **실행가능 샘플 데이터(data.sql 수준)**를 함께 제공하여 로컬에서 즉시 E2E 확인 가능합니다.
작업 상세 내용
도메인/엔티티
Order 엔티티 및 매핑
컬럼: 합계 4종(원가/브랜드할인/유저추가할인/최종결제), 사용요약(쿠폰/지갑), 수령인/택배/타임스탬프
DB FK 추가: orders.order_id ↔ payment.order_id(1:1) 참조 무결성 payment_intent_line.payment_id ↔ payment.id, …product_id ↔ product.product_id 등
트랜잭션 경계 테스트: 환불 승인 시 Payment 업데이트, 월렛 적립/환불, 쿠폰 복구, 재고 복원 원자성 E2E 테스트
통합/격리 테스트(Testcontainers): 생성/조회/전이/권한/예외/금액집계
동시성 제어: 동일 주문에 대한 다중 전이/적립 경쟁 조건 테스트(낙관락/UK 기반 멱등 보강)
검증 강화: 배송지 필드 포맷, 전화번호/우편번호 정규화, 수취인 길이 제한 등 Bean Validation
관측성: 주요 전이/실패 지표(metrics) & 감사 로그(audit) 추가
에러코드 문서화: ErrorCode별 HTTP 매핑/가이드
부분환불 시 UI/정책 정의: 라인단위 환불/부분 수량 환불 UX 결정
다브랜드 주문 UI 정책: 브랜드 상세에서 라인 필터링 OK → 알림/정산 정책 연계
참고할만한 자료(선택)
핵심 조인 경로(브랜드 주문 조회) Order o → Payment p (on p.orderId = o.orderId) → PaymentIntentLine l (on l.payment = p) → Product prod (on l.product) → BrandUser
→ 브랜드 필터: prod.brandUser.userNumber = :brandUserNumber
어떤 기능인가요?
작업 상세 내용
도메인/엔티티
Order엔티티 및 매핑(user_number),(status, created_at)OrderStatus(PAID → PREPARING → IN_TRANSIT → DELIVERED → PURCHASE_CONFIRMED …)@PrePersist,@PreUpdateOrder.paid(...)(APPROVED 결제에서 최초 생성)상태 전이 가드/메서드
toPreparingByBrand,toInTransitByBrand,toDeliveredByBrandconfirmByBuyer(DELIVERED에서만)requestCancelByBuyer(PAID에서만)adminSetStatus저장소/쿼리
OrderRepositoryfindByUserNumberOrderByCreatedAtDesc브랜드 소유 판별형 페이지 쿼리:
findPageByBrandUserNumberOrder ↔ Payment ↔ PaymentIntentLine ↔ Product(brandUser)조인브랜드 취소요청 전용 페이지:
findCancelRequestedByBrand어드민 필터:
adminFilter(buyer,status)어드민 취소요청 페이지:
adminCancelRequested서비스 레이어
생성(멱등)
createFromApprovedPayment(orderId)Payment(APPROVED)필수PaymentIntentLine집계로 original, brandDiscount, couponTotal, finalPayAmount 계산brandDiscount = originalTotal - lineBaseTotal (>=0)finalPayAmount = paymentReadRepo.sumNetApprovedAmountByOrderId(orderId)사용walletUsed = payment.pointsToUse이미 존재하면 no-op(멱등)
조회
Payment → PaymentIntentLine로딩구매자 액션
WalletService.creditwith UK=ORDER_CONFIRM:orderId)브랜드 액션
REFUND_REQUESTED, 거절 →PAID어드민 액션
Size.valueOf,Color.valueOf사용 → 라인에 저장된 문자열이 Enum과 정확히 일치해야 함컨트롤러 & 보안
OrderController(구매자/브랜드/어드민 분리)@PreAuthorize+@AuthUser(본인 확인, 브랜드/슈퍼 권한)OrderApiDocs) & 예제 페이로드예외/로깅/성능
BasiliumCustomException(ErrorCode)/AccessDeniedException/IllegalStateException→ 의미있는 메시지(status, created_at)최신순 조회 최적화데이터/샘플(SQL)
카테고리/유저(노말=1, 브랜드=1, 슈퍼=1 포함)/포인트/월렛/상품(1~9)/옵션/사진/재질 예시
상품공개할인(ProductDiscount)/사용자추가할인(UserDiscount) 예시
브랜드쿠폰캠페인/개인지갑 발급 예시
결제/결제라인 2건 예시(상품1,2)
주문(Order) 2건 예시(결제와 1:1 매칭)
20250903-200500-UUID-TEST-1(user=1, 상품2, 53,000원, PAID)20250903-200000-UUID-EXAMPLE-2(user=2, 상품1, 원가 53,000→브랜드할인 34,000, 최종 19,000, DELIVERED)브랜드 소유 판별은
Order단독이 아니라 반드시Payment+PaymentIntentLine과 함께(Repo 쿼리, Service의assertBrandOwns)호환성/검증 포인트
original = Σ(productPrice*qty),brandDiscount = original - Σ(lineBase),couponTotal = Σ(couponDiscount),finalPayAmount = 승인합계createFromApprovedPayment중복 호출 시 재생성 방지size,color는 재고복원 시Size/Colorenum과 일치해야 함(예:M/L,BLACK/WHITE)권장 보완(TODO)
orders.order_id↔payment.order_id(1:1) 참조 무결성payment_intent_line.payment_id↔payment.id,…product_id↔product.product_id등Payment업데이트, 월렛 적립/환불, 쿠폰 복구, 재고 복원 원자성 E2E 테스트ErrorCode별 HTTP 매핑/가이드참고할만한 자료(선택)
핵심 조인 경로(브랜드 주문 조회)
Order o→Payment p (on p.orderId = o.orderId)→PaymentIntentLine l (on l.payment = p)→Product prod (on l.product)→BrandUser→ 브랜드 필터:
prod.brandUser.userNumber = :brandUserNumber상세 아이템 로딩 코드 요약
paymentRepo.findByOrderId(orderId).map(p -> lineRepo.findAllByPayment_Id(p.getId()))product.brandUser.userNumber == brandUserFilter필터샘플 주문 INSERT(요약)
20250903-200500-UUID-TEST-1/ user=1 / 53,000 / 할인0 / 송장없음20250903-200000-UUID-EXAMPLE-2/ user=2 / original 53,000 / brandDiscount 34,000 / final 19,000 /CJ송장 포함주의
orders만으로 불가. 반드시payment/payment_intent_line과 함께 봐야 함(이미 쿼리/서비스 반영).size/color는 Enum 상수 문자열과 일치해야 재고복원 성공.payment.order_id가 존재해야 브랜드 화면/상세가 정상 동작.