Skip to content

Story: 크레딧 관리 API

메타

항목
Story IDE-02-S-04
EpicE-02 어드민 강화
상태draft
우선순위P1
규모S
담당 개발자BE (하록님)

사용자 스토리

As a CS팀/운영팀 관리자, I want 사용자 크레딧 잔액을 조회하고 직접 지급/차감, So that CS 보상을 즉시 처리하고 오지급 시 회수할 수 있다.


수락 기준 (Acceptance Criteria)

AC-01: 크레딧 잔액 조회

항목내용
Given특정 사업장 ID (bizId)
When잔액 조회 요청
Then해당 사업장의 크레딧 잔액 + 통계 반환

응답 필드:

{
  bizId: number,
  bizName: string,           // Biz 테이블 조인
  balance: number,           // 현재 잔액
  totalEarned: number,       // 총 적립액
  totalUsed: number,         // 총 사용액
  totalExpired: number,      // 총 만료액
  updatedAt: string
}

AC-02: 크레딧 지급

항목내용
GivenbizId, 금액, 사유
When크레딧 지급 요청
Then크레딧이 지급되고 원장에 기록됨

요청 필드:

{
  bizId: number,          // 필수
  amount: number,         // 필수, 양수
  reason: string,         // 필수 (지급 사유)
  expireAt?: string       // 선택 (만료일, 기본 90일 후)
}

처리 로직:

  1. CreditBalance 생성 또는 업데이트 (balance += amount)
  2. CreditLedger에 EARN 타입 기록
  3. 지급 내역 반환

AC-03: 크레딧 거래 이력 조회

항목내용
Given특정 사업장 ID
When거래 이력 조회
Then해당 사업장의 전체 크레딧 이력 반환

응답 필드:

{
  items: [{
    id, bizId,
    type,              // EARN, USE, EXPIRE, REFUND, HOLD, CANCEL
    amount,            // 금액 (EARN: +, USE/EXPIRE: -)
    balanceAfter,      // 거래 후 잔액
    reason,            // 지급/사용 사유
    expireAt,          // 만료 예정일
    createdAt
  }],
  pagination: { page, size, total, totalPages }
}

필터:

  • type (전체/적립/사용/만료)

AC-04: 존재하지 않는 사업장

항목내용
Given존재하지 않는 bizId
When잔액 조회/지급 요청
Then404 Not Found

AC-05: 잘못된 금액

항목내용
Givenamount ≤ 0
When크레딧 지급 요청
Then400 Bad Request + "지급 금액은 0보다 커야 합니다"

AC-06: 크레딧 차감/취소

항목내용
GivenbizId, 차감 금액, 사유
When크레딧 차감 요청
Then크레딧이 차감되고 원장에 기록됨

요청 필드:

{
  bizId: number,          // 필수
  amount: number,         // 필수, 양수
  reason: string,         // 필수 (차감 사유)
  type: string            // DEDUCT | CANCEL (차감 유형)
}

처리 로직:

  1. 잔액 부족 검증 (balance >= amount)
  2. CreditBalance 업데이트 (balance -= amount)
  3. CreditLedger에 USE 또는 CANCEL 타입 기록
  4. 잔액 부족 시 400 + "잔액이 부족합니다"

사용 시나리오:

  • DEDUCT: 오지급된 크레딧 회수
  • CANCEL: 지급 취소 (사유: "오지급 취소" 등)

태스크 분해

Task 1: 잔액 조회 API AC-01, AC-04

  • [ ] 1.1: GET /admin/credits/balance/:bizId 엔드포인트 생성
  • [ ] 1.2: CreditBalance + Biz 조인 쿼리
  • [ ] 1.3: 잔액이 없는 경우 기본값 반환 (0)
  • [ ] 1.4: 사업장 존재 여부 검증

Task 2: 크레딧 지급 API AC-02, AC-04, AC-05

  • [ ] 2.1: POST /admin/credits/grant 엔드포인트 생성
  • [ ] 2.2: 요청 DTO 정의 + 유효성 검증
  • [ ] 2.3: 사업장 존재 여부 검증
  • [ ] 2.4: CreditBalance upsert 로직
  • [ ] 2.5: CreditLedger EARN 기록
  • [ ] 2.6: 트랜잭션 처리

Task 3: 거래 이력 API AC-03

  • [ ] 3.1: GET /admin/credits/ledger/:bizId 엔드포인트 생성
  • [ ] 3.2: CreditLedger 조회 + 페이지네이션
  • [ ] 3.3: type 필터 구현
  • [ ] 3.4: 정렬 (최신순)

Task 4: 크레딧 차감/취소 API AC-06

  • [ ] 4.1: POST /admin/credits/deduct 엔드포인트 생성
  • [ ] 4.2: 요청 DTO 정의 + 유효성 검증
  • [ ] 4.3: 잔액 부족 검증 로직
  • [ ] 4.4: CreditBalance 차감 업데이트
  • [ ] 4.5: CreditLedger USE/CANCEL 기록
  • [ ] 4.6: 트랜잭션 처리

Task 5: 테스트 작성

  • [ ] 5.1: 잔액 조회 테스트
  • [ ] 5.2: 크레딧 지급 테스트 (정상/에러)
  • [ ] 5.3: 크레딧 차감/취소 테스트 (정상/잔액부족)
  • [ ] 5.4: 이력 조회 테스트
  • [ ] 5.5: 트랜잭션 롤백 테스트

Task 6: 마무리

  • [ ] 6.1: API 문서화
  • [ ] 6.2: PR 생성

Dev Notes (AI Agent 최적화)

아키텍처 패턴

항목내용
사용할 패턴Repository Pattern + Service Layer
참고 구현기존 CreditService (S52 E-07)
피해야 할 것잔액 업데이트 시 트랜잭션 누락

영향 받는 소스 트리

src/
├── admin/
│   └── credit/
│       ├── credit.admin.controller.ts  # 🆕 신규 생성
│       ├── credit.admin.service.ts     # 🆕 신규 생성
│       └── dto/
│           └── grant-credit.dto.ts     # 🆕 신규 생성
└── tests/
    └── admin/
        └── credit.admin.spec.ts        # 🆕 신규 생성

비즈니스 로직 상세

크레딧 지급 트랜잭션

typescript
// 유사 코드
await prisma.$transaction(async (tx) => {
  // 1. CreditBalance upsert
  const balance = await tx.creditBalance.upsert({
    where: { bizId },
    create: { bizId, balance: amount, totalEarned: amount },
    update: {
      balance: { increment: amount },
      totalEarned: { increment: amount }
    }
  });

  // 2. CreditLedger 기록
  await tx.creditLedger.create({
    data: {
      bizId,
      type: 'EARN',
      amount,
      balanceAfter: balance.balance,
      reason,
      expireAt: expireAt || addDays(new Date(), 90)
    }
  });
});

충돌 감지

항목상태설명
기존 코드 충돌⚠️ 주의기존 CreditService와 역할 분리 확인
API 계약 변경✅ 없음신규 어드민 엔드포인트
DB 스키마 변경✅ 없음기존 테이블 사용

References

출처경로/링크참조 섹션
Epic Spec.context/sprints/s53/epic-specs/E-02.md크레딧 API 설계
테이블 스키마S52 E-07 DDLCreditBalance, CreditLedger
기존 서비스src/credit/credit.service.ts로직 참고

Dev Agent Record

항목
생성 AgentClaude Opus 4.5
생성일2026-01-27
마지막 수정2026-01-27
검증자-

검증 결과: 🔄 PENDING (PO 승인 대기) 검증일: -


생성일: 2026-01-27마지막 수정: 2026-01-27

장사왕 Product Team