테마
Story: 원가 CSV 업로드
메타
| 항목 | 값 |
|---|---|
| Story ID | E-03-S-08 |
| Epic | E-03 원가 히스토리 |
| 상태 | draft |
| 우선순위 | P0 |
| 규모 | L |
| 담당 | BE: 희선님, FE: 수민님 |
사용자 스토리
As a 상품 수가 많은 셀러, I want CSV 파일로 원가를 일괄 업데이트, So that 시세 변동 시 빠르게 전체 원가를 반영할 수 있다.
수락 기준 (Acceptance Criteria)
AC-01: 업로드 버튼 노출 (Pro 이상)
| 항목 | 내용 |
|---|---|
| Given | 매입원가 관리 페이지 |
| When | Pro 이상 요금제 사용자 |
| Then | "CSV 업로드" 버튼 노출 |
요금제별 노출:
| 티어 | CSV 업로드 |
|---|---|
| Starter | ❌ |
| Basic | ❌ (업그레이드 유도 UI) |
| Pro+ | ✅ |
AC-02: 파일 업로드 및 파싱
| 항목 | 내용 |
|---|---|
| Given | CSV 파일 선택 |
| When | 업로드 버튼 클릭 |
| Then | 파일 파싱 후 벌크 업데이트 실행 |
파싱 규칙:
- UTF-8 / EUC-KR 자동 감지
- 첫 행: 헤더 (한글 컬럼명)
- Key 매칭:
쇼핑몰+판매자ID+상품코드
AC-03: 벌크 업데이트 (즉시 적용)
| 항목 | 내용 |
|---|---|
| Given | CSV 파싱 완료 |
| When | Key 매칭 성공 |
| Then | Product 테이블 + PurchasePrice 히스토리 업데이트 |
업데이트 대상 컬럼:
| 컬럼명 (한글) | DB 컬럼 |
|---|---|
| 매입원가 | purchasePrice |
| 매입배송비 | purchaseDeliveryAmount |
| 운임비 | actualDeliveryAmount |
| 기타비용 | etcAmount |
| 광고비용 | marketingAmount |
| 입출고비용 | warehousingAmount |
AC-04: 결과 리포트
| 항목 | 내용 |
|---|---|
| Given | 업데이트 완료 |
| When | 처리 결과 반환 |
| Then | 성공/실패 건수 표시 |
결과 메시지 예시:
✅ 업로드 완료
- 전체: 150건
- 성공: 147건
- 실패: 3건 (상품코드 미매칭)
실패 목록:
- 행 23: 상품코드 'SKU-999' 없음
- 행 45: 상품코드 'ABC-123' 없음
- 행 89: 상품코드 '' 비어있음태스크 분해
Task 1: BE - CSV 업로드 API (AC-02, AC-03)
- [ ]
POST /api/products/cost/import엔드포인트 - [ ] 파일 인코딩 자동 감지 (UTF-8 / EUC-KR)
- [ ] 한글 헤더 → DB 컬럼 매핑
- [ ] Key 매칭: marketCode + vendorId + productId
Task 2: BE - 벌크 업데이트 로직 (AC-03)
- [ ] Product 테이블 업데이트 (원가 컬럼)
- [ ] PurchasePrice 히스토리 INSERT (신규 row)
- [ ] 트랜잭션 처리 (부분 실패 허용 vs 전체 롤백)
- [ ] marginUpdatedAt 타임스탬프 갱신
Task 3: FE - 업로드 UI (AC-01, AC-04)
- [ ] 업로드 버튼 컴포넌트
- [ ] 요금제별 노출 분기 (Pro 이상)
- [ ] Basic: 업그레이드 유도 모달
- [ ] 파일 선택 다이얼로그
- [ ] 업로드 진행률 표시
- [ ] 결과 리포트 모달
Task 4: 에러 핸들링
- [ ] 파일 형식 오류 (CSV 아님)
- [ ] 필수 컬럼 누락
- [ ] Key 컬럼 비어있음
- [ ] 숫자 형식 오류 (문자 입력)
Dev Notes
검증 전략 (MVP)
Phase 1 (S53): 즉시 적용, 기본 검증만
- Key 매칭 실패 → 해당 row skip, 결과에 표시
- 숫자 형식 오류 → 해당 row skip
Phase 2 (S54+ 백로그): 고급 검증
- 프리뷰 모드 (적용 전 확인)
- 원가 급변 경고 (2배 이상 변동)
- 실행 취소 (롤백)
부분 실패 정책
전체 롤백 ❌ → 부분 성공 ✅
- 이유: 100건 중 1건 실패로 99건 롤백은 UX 나쁨
- 실패 건만 skip하고 성공 건은 적용
PurchasePrice 히스토리 정책
업로드 시 원가 변경 있으면:
- Product.purchasePrice 업데이트
- PurchasePrice 테이블에 새 row INSERT
- Product.purchaseId 갱신 (신규 PurchasePrice.id)
- Product.marginUpdatedAt 갱신
E-05 연계
- Pro 이상에서만 CSV 업로드 제공
- E-05 Feature Flag / PlanTier 체크 필요
- E-05 배포 전: 전체 공개 또는 Feature Flag로 숨김
References
생성일: 2026-01-28
