Adit 정산 시스템 설계 문서
최종 업데이트: 2026-01-27
1. 개요
1.1 정산 시스템의 역할
Adit 정산 시스템은 캠페인 완료 후 광고주로부터 대금을 수령하고 파트너(매체사)에게 정산금을 지급하는 전체 플로우를 관리합니다.
1.2 핵심 참여자
| 참여자 | 역할 |
|---|---|
| 광고주 | 캠페인 비용 지불, 세금계산서 수령 |
| 파트너(매체사) | 콘텐츠 업로드, 정산금 수령, 세금계산서 발행 |
| Adit/대행사 | 중개, 세금계산서 발행/수령, 수수료 정산 |
| 어드민 | 정산 처리, 입금 확인, 송금 처리 |
2. 정산 유형
Adit 정산 (ADIT_SETTLEMENT)
광고주 → [입금] → Adit/대행사 계좌 → [정산금 송금] → 파트너
↓ ↓
세금계산서 수령 세금계산서 수령
(Adit/대행사 발행) (파트너 발행)- 수수료 모델: 캠페인 금액의 N% (파트너별 설정)
- 정산금: 캠페인 금액 - 수수료
3. 3계층 정산 구조
3.1 구조 개요
3.2 정산 모드
| 모드 | 광고주 청구 | 파트너 지급 | 사용 케이스 |
|---|---|---|---|
| 건별 정산 | 캠페인마다 청구서 | 캠페인마다 지급 | 소량 거래, 직정산 |
| 월별 정산 | 월 1회 합산 청구 | 월 1회 합산 지급 | 대량 거래, 정기 정산 |
⚠️
현재 구현: 건별 정산만 구현됨. 월별 정산은 Phase 2에서 구현 예정.
4. 대행사(Agency) 지원
4.1 개념
정산 주체가 Adit(르도드코퍼레이션) 외에 다른 대행사도 될 수 있음.
| 대행사 | 코드 | 정산 계좌 |
|---|---|---|
| 르도드코퍼레이션 (Adit) | ADIT | 카카오뱅크 3333-27-7813548 (최형빈) |
| 미드나잇웨이브 | MNW | 신한은행 110-XXX-XXXXXX (주식회사 미드나잇웨이브) |
4.2 적용 범위
- Campaign.agencyId: 캠페인 담당 대행사
- AdminUser.agencyId: 어드민 소속 대행사
- AdvertiserInvoice.agencyId: 청구서 발행 주체
- 광고주 입금 계좌: 대행사별로 다름
4.3 권한 분리
| 소속 | 볼 수 있는 데이터 |
|---|---|
슈퍼어드민 (agencyId = null) | 모든 대행사 데이터 |
Adit 어드민 (agencyId = 1) | Adit 담당 캠페인/정산만 |
MNW 어드민 (agencyId = 2) | 미드나잇웨이브 담당 캠페인/정산만 |
5. 정산 플로우
5.1 Adit 정산 전체 플로우
캠페인 업로드 완료
Campaign.status = UPLOADED
파트너가 "정산 요청" 클릭
Settlement.status = AWAITING_ADVERTISER_PAYMENT- 내부팀 슬랙 알림 (@adit_set)
어드민이 광고주에게 세금계산서 발행
AdvertiserInvoice생성- 광고주 이메일: "세금계산서가 발행되었습니다"
- 광고주 이메일: "입금 안내" (대행사 계좌 정보)
광고주 입금 확인
Settlement.status = ADVERTISER_PAID- 광고주 이메일: "입금이 확인되었습니다"
- 파트너 이메일: "곧 정산금이 지급됩니다"
파트너에게 세금계산서 요청
Settlement.status = PARTNER_PAYOUT_PROCESSINGPartnerPayout생성- 파트너 이메일: "세금계산서 발행 부탁드립니다"
파트너 세금계산서 수령 확인
PartnerPayout.partnerInvoiceReceivedAt기록
파트너 정산금 송금
Settlement.status = SETTLEMENT_COMPLETEDCampaign.status = COMPLETED- 파트너 이메일: "정산이 완료되었습니다 (₩금액)"
5.2 매체사 직정산 플로우
캠페인 업로드 완료
Campaign.status = UPLOADED
파트너가 "정산 요청" 클릭
Settlement.status = AWAITING_ADVERTISER_PAYMENT- 광고주 이메일: "매체사에 직접 정산해주세요" + 파트너 계좌 정보
파트너가 "입금 확인" 클릭
Settlement.status = SETTLEMENT_COMPLETEDCampaign.status = COMPLETED
5.3 정산 상태 전이
6. DB 스키마
6.1 Agency (대행사)
model Agency {
id BigInt @id @default(autoincrement())
name String // "르도드코퍼레이션"
code String @unique // "ADIT"
businessName String // 사업자등록증상 상호
businessNumber String // 사업자번호
representativeName String // 대표자명
bankName String // "카카오뱅크"
accountNumber String // "3333-27-7813548"
accountHolder String // "최형빈"
email String
isActive Boolean @default(true)
}6.2 AdvertiserInvoice (광고주 청구서)
model AdvertiserInvoice {
id BigInt @id @default(autoincrement())
invoiceNumber String @unique // "INV-2026-01-001"
advertiserId BigInt
agencyId BigInt? // 정산 주체 (null이면 Adit 기본값)
// 금액
subtotal Decimal // 공급가액
taxAmount Decimal // 부가세
totalAmount Decimal // 합계
// 세금계산서
taxInvoiceNumber String?
taxInvoiceFileKey String?
taxInvoiceIssuedAt DateTime?
// 입금
status InvoiceStatus // DRAFT, ISSUED, PAID, OVERDUE, CANCELLED
dueDate DateTime?
paidAt DateTime?
// 입금 계좌 스냅샷
bankName String?
accountNumber String?
accountHolder String?
// Relations
settlements Settlement[]
}6.3 PartnerPayout (파트너 지급)
model PartnerPayout {
id BigInt @id @default(autoincrement())
payoutNumber String @unique // "PAY-2026-01-001"
partnerId BigInt
// 금액
subtotal Decimal // 정산금 합계
taxAmount Decimal // 부가세
totalAmount Decimal // 실지급액
// 파트너 세금계산서
partnerInvoiceNumber String?
partnerInvoiceFileKey String?
partnerInvoiceReceivedAt DateTime?
// 지급
status PayoutStatus // PENDING, INVOICE_RECEIVED, PROCESSING, COMPLETED, CANCELLED
paidAt DateTime?
transactionId String?
// 계좌 스냅샷
bankName String?
accountNumber String?
accountHolder String?
// Relations
settlements Settlement[]
}7. API 엔드포인트
7.1 광고주 청구서 API
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/admin/invoices | 청구서 목록 조회 |
| GET | /api/admin/invoices/:id | 청구서 상세 조회 |
| POST | /api/admin/invoices | 청구서 생성 |
| POST | /api/admin/invoices/:id/issue | 세금계산서 발행 |
| POST | /api/admin/invoices/:id/confirm-payment | 입금 확인 |
| POST | /api/admin/invoices/:id/cancel | 청구서 취소 |
7.2 파트너 지급 API
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/admin/payouts | 지급 목록 조회 |
| GET | /api/admin/payouts/:id | 지급 상세 조회 |
| POST | /api/admin/payouts | 지급 배치 생성 |
| POST | /api/admin/payouts/:id/receive-invoice | 세금계산서 수령 확인 |
| POST | /api/admin/payouts/:id/complete | 송금 완료 |
7.3 대행사 API
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/admin/agencies | 대행사 목록 조회 |
| GET | /api/admin/agencies/:id | 대행사 상세 조회 |
| POST | /api/admin/agencies | 대행사 생성 |
| PUT | /api/admin/agencies/:id | 대행사 수정 |
8. 알림 시스템
8.1 광고주 알림
| 이벤트 | 트리거 | 채널 |
|---|---|---|
INVOICE_ISSUED_ADVERTISER | 세금계산서 발행 | |
PAYMENT_REQUEST_ADVERTISER | 입금 요청 (계좌 안내) | |
PAYMENT_CONFIRMED_ADVERTISER | 입금 확인 완료 | |
DIRECT_SETTLEMENT_REQUEST | 매체사 직정산 안내 |
8.2 파트너 알림
| 이벤트 | 트리거 | 채널 |
|---|---|---|
ADVERTISER_PAID_PARTNER | 광고주 입금 완료 | |
INVOICE_REQUEST_PARTNER | 세금계산서 발행 요청 | |
PAYOUT_COMPLETED_PARTNER | 정산금 송금 완료 |
8.3 내부 알림
| 이벤트 | 트리거 | 채널 |
|---|---|---|
SETTLEMENT_REQUESTED | 파트너 정산 요청 | Slack (@adit_set) |
| 정산 상태 변경 | 각 단계별 | Slack Thread |
9. 구현 현황
9.1 완료 ✅
- Settlement 기본 모델
- 정산 상태 전이 (PENDING → AWAITING → PAID → PROCESSING → COMPLETED)
- 파트너 정산 요청 API
- 어드민 정산 관리 API
- 캠페인 상태 변경 알림 (Slack, Email)
- 슬랙 캠페인별 스레드
9.2 구현 예정 (현재 작업)
- Agency 모델 및 API
- AdminUser.agencyId 확장
- Campaign.agencyId 확장
- AdvertiserInvoice 모델 및 API (건별)
- PartnerPayout 모델 및 API (건별)
- 광고주 정산 알림 (세금계산서, 입금 요청, 입금 확인)
- 파트너 정산 알림 (세금계산서 요청, 송금 완료)
- 어드민 정산 UI 개선
9.3 Phase 2 (추후 구현)
- 월별 일괄 정산
- SettlementConfig (광고주/파트너별 정산 주기 설정)
- 월별 배치 Job (매월 25일 청구서 생성, 말일 지급 배치)
- 정산 대시보드
부록
A. 용어 정의
| 용어 | 설명 |
|---|---|
| Settlement | 캠페인 단위 정산 레코드 |
| AdvertiserInvoice | 광고주에게 발행하는 청구서 |
| PartnerPayout | 파트너에게 지급하는 정산 배치 |
| Agency | 정산 주체 (Adit, 미드나잇웨이브 등) |
| 건별 정산 | 캠페인 1건 = 청구서/지급 1건 |
| 월별 정산 | 한 달치 캠페인 합산하여 청구/지급 |
B. 관련 파일 위치
adit-backend/
├── prisma/schema.prisma # DB 스키마 (확장 계획 주석 포함)
├── src/modules/
│ ├── admin/settlements/ # 어드민 정산 서비스
│ ├── partner/settlements/ # 파트너 정산 서비스
│ ├── admin/invoices/ # 광고주 청구서 (신규)
│ ├── admin/payouts/ # 파트너 지급 (신규)
│ ├── admin/agencies/ # 대행사 관리 (신규)
│ └── notification/ # 알림 서비스
└── src/templates/email/ # 이메일 템플릿