-
Notifications
You must be signed in to change notification settings - Fork 3
Description
어떤 기능인가요?
결제(APPROVED) 기준으로
Order를 생성·조회·상태전이하고, 구매자/브랜드/어드민별로 권한이 다른 주문 라이프사이클 API입니다.
주문 상세는Payment→PaymentIntentLine을 따라 주문에 묶인 모든 결제 라인아이템(상품/사이즈/색상/수량/금액)을 조회합니다.
구매확정 시 지갑 2% 적립, 환불/취소 승인 시 현금/포인트 환불, 쿠폰복구, 재고복원 옵션을 지원합니다.
MySQL용 **실행가능 샘플 데이터(data.sql 수준)**를 함께 제공하여 로컬에서 즉시 E2E 확인 가능합니다.
작업 상세 내용
도메인/엔티티
-
Order엔티티 및 매핑- 컬럼: 합계 4종(원가/브랜드할인/유저추가할인/최종결제), 사용요약(쿠폰/지갑), 수령인/택배/타임스탬프
- 인덱스:
(user_number),(status, created_at) - 상태 열거형
OrderStatus(PAID → PREPARING → IN_TRANSIT → DELIVERED → PURCHASE_CONFIRMED …) - 라이프사이클 콜백:
@PrePersist,@PreUpdate - 팩토리:
Order.paid(...)(APPROVED 결제에서 최초 생성)
-
상태 전이 가드/메서드
- 배송지 수정 제한(배송 진행 이후 불가)
- 브랜드 전이:
toPreparingByBrand,toInTransitByBrand,toDeliveredByBrand - 구매확정:
confirmByBuyer(DELIVERED에서만) - 취소신청:
requestCancelByBuyer(PAID에서만) - 어드민 임의전이:
adminSetStatus
저장소/쿼리
-
OrderRepository-
findByUserNumberOrderByCreatedAtDesc -
브랜드 소유 판별형 페이지 쿼리:
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로딩 - 브랜드 상세는 해당 브랜드의 라인만 필터링
- 리뷰 가능여부 계산(배송완료+14일 내, 주문당 미작성)
-
구매자 액션
- 배송지 수정(가드 포함)
- 구매확정(2% 지갑 적립;
WalletService.creditwith UK=ORDER_CONFIRM:orderId) - 취소/환불/반품 신청 (상태 가드 및 전이)
-
브랜드 액션
- PREPARING / IN_TRANSIT(택배사/송장 필수) / DELIVERED 전이
- 취소신청 승인 →
REFUND_REQUESTED, 거절 →PAID
-
어드민 액션
- 환불/반품 승인(현금/지갑 환불, 전액 시 쿠폰 복구, 재고 복원 옵션)
- 환불/반품 거절(상태 되돌림)
- 강제 취소(전액 환불/포인트 환급/쿠폰복구/재고복원 옵션)
- 임의 상태 전이
- 재고 복원 시
Size.valueOf,Color.valueOf사용 → 라인에 저장된 문자열이 Enum과 정확히 일치해야 함
컨트롤러 & 보안
-
OrderController(구매자/브랜드/어드민 분리) -
@PreAuthorize+@AuthUser(본인 확인, 브랜드/슈퍼 권한) - Swagger 문서(
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중복 호출 시 재생성 방지 - Enum 일치: 라인의
size,color는 재고복원 시Size/Colorenum과 일치해야 함(예:M/L,BLACK/WHITE) - 권한 가드: 구매자 본인/브랜드 소유/어드민
권장 보완(TODO)
- 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 -
상세 아이템 로딩 코드 요약
paymentRepo.findByOrderId(orderId).map(p -> lineRepo.findAllByPayment_Id(p.getId()))- 브랜드 상세:
product.brandUser.userNumber == brandUserFilter필터
-
샘플 주문 INSERT(요약)
- PAID:
20250903-200500-UUID-TEST-1/ user=1 / 53,000 / 할인0 / 송장없음 - DELIVERED:
20250903-200000-UUID-EXAMPLE-2/ user=2 / original 53,000 / brandDiscount 34,000 / final 19,000 /CJ송장 포함
- PAID:
-
주의
- 브랜드 판별은
orders만으로 불가. 반드시payment/payment_intent_line과 함께 봐야 함(이미 쿼리/서비스 반영). - 라인
size/color는 Enum 상수 문자열과 일치해야 재고복원 성공. - 주문을 수동 INSERT할 때는 반드시 동일한
payment.order_id가 존재해야 브랜드 화면/상세가 정상 동작.
- 브랜드 판별은
Metadata
Metadata
Assignees
Labels
Projects
Status