GET /ai/admin/finance/business/{businessAccountId}
기업 파이낸스 상세 (요약 + 캠페인 리스트 + 글로벌 타임라인)
기업 파이낸스 상세
기업의 잔액·LOCK·누적 충전/입금 합계와, 해당 기업의 캠페인 리스트, 그리고 크레딧 타임라인을 반환합니다.
globalTimeline 은 이름과 달리 이 기업의 모든 크레딧 거래를 담습니다. 예전에는
collab_no IS NULL 인 글로벌 거래만 내렸으나, 캠페인 입금·차감도 함께 보이도록 필터를 없앴습니다.
캠페인 스코프 거래에는 collabNo 와 collabTitle 이 채워집니다.
HTTP 요청
GET /ai/admin/finance/business/{businessAccountId}
Authorization: Bearer {access_token}Path Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
businessAccountId | Long | 예 | 기업 PK (Business.businessAccountId) |
Query Parameters
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
tag | String | 아니오 | 주면 타임라인을 그 분류 태그 행으로 좁히고, balanceAfter 를 태그 안에서 0 부터 누적한 값으로 바꿔 내려줍니다. DB 는 건드리지 않습니다. 생략하면 기존과 동일 |
응답 (200 OK)
{
"status": 200,
"code": null,
"message": "기업 상세 조회 완료",
"data": {
"summary": {
"businessAccountId": 12,
"memberId": "brandA",
"businessName": "A브랜드",
"remainCredit": 1500000,
"totalLocked": 300000
},
"totalCharged": 3000000,
"totalDeposited": 1500000,
"campaigns": [
{
"collabNo": 482,
"title": "여름 신상 캠페인",
"productName": "선크림 50ml",
"businessAccountId": 12,
"businessName": "A브랜드",
"totalDeposited": 500000,
"totalLocked": 300000
}
],
"globalTimeline": [
{
"sourceKey": "creditTx:1042",
"type": "CARD_PAYMENT",
"amount": 1000000,
"balanceAfter": 1500000,
"collabNo": null,
"collabTitle": null,
"candyPaymentId": "order_abc",
"paymentStatus": "APPROVED",
"paymentCancelled": false,
"receiptCandyUrl": "https://pay.candypay.co.kr/receipt/candy/...",
"receiptPerMethodUrls": "https://pay.candypay.co.kr/receipt/card/...",
"occurredAt": "2026-05-20T10:11:00",
"description": "결제 충전",
"reason": null,
"memo": null,
"provisional": false,
"reverseOfTxId": null,
"reversed": false,
"createdBy": "brandA",
"createdByName": "A브랜드"
},
{
"sourceKey": "creditTx:1043",
"type": "CAMPAIGN_DEPOSIT",
"amount": -3000000,
"balanceAfter": -1500000,
"collabNo": 482,
"collabTitle": "여름 신상 캠페인",
"candyPaymentId": null,
"paymentStatus": null,
"paymentCancelled": null,
"receiptCandyUrl": null,
"receiptPerMethodUrls": null,
"occurredAt": "2026-05-21T14:02:00",
"description": "캠페인 결제",
"reason": null,
"memo": "관리자 대리 결제 (미충전)",
"provisional": true,
"reverseOfTxId": null,
"reversed": false,
"createdBy": "ADMIN",
"createdByName": "관리자"
}
]
}
}Response 스키마
BusinessFinanceDetailDto
| 필드 | 타입 | 설명 |
|---|---|---|
summary | BusinessFinanceSummaryDto | 요약 |
totalCharged | Integer | PAYMENT 양수 amount 누적 |
totalDeposited | Integer | CAMPAIGN_DEPOSIT abs 누적 |
campaigns | CollabFinanceSummaryDto[] | 이 기업의 캠페인 리스트 (최신순) |
globalTimeline | FinanceTimelineEntryDto[] | 이 기업의 크레딧 거래 이력 전체 (캠페인 스코프 포함, 최신순) |
tag | String | 적용된 분류 태그. tag 없이 조회하면 null |
tagInflow | Integer | 이 태그의 유입 합. 태그 없이 조회하면 null |
tagOutflow | Integer | 이 태그의 유출 합. 태그 없이 조회하면 null |
tagNetBalance | Integer | 순액 = tagInflow - tagOutflow. 태그별 순액을 다 더해도 기업 전체 잔액과 맞지 않습니다(미분류·이월분 제외) |
FinanceTimelineEntryDto
| 필드 | 타입 | 설명 |
|---|---|---|
sourceKey | String | 출처 식별자 (creditTx:{id} / budgetLock:{id} / budgetUnlock:{id}) |
type | FinanceTimelineEntryType | 분류 (CARD_PAYMENT / CREDIT_ADD / ... — 자세한 매핑은 index 참조) |
amount | Integer | 양수=증가, 음수=감소 |
balanceAfter | Integer | CreditTransaction 출처일 때 잔액 스냅샷. 음수일 수 있습니다 (아래 참조) |
collabNo | Integer? | 캠페인 번호. 글로벌 거래는 null |
collabTitle | String? | 캠페인명. collabNo 가 있는 행에만 채워집니다 |
candyPaymentId | String? | 결제 ID (CandyPayment.orderId) |
paymentStatus | String? | 캔디페이 결제 상태 — PENDING / APPROVED / FAILED / CANCELLED / PARTIAL_CANCELLED |
paymentCancelled | Boolean? | 취소 여부 (CANCELLED 또는 PARTIAL_CANCELLED) |
receiptCandyUrl | String? | 캔디페이 통합 영수증 URL |
receiptPerMethodUrls | String? | 결제수단별 영수증/카드 매출전표 URL. 여러 건이면 콤마 구분 |
occurredAt | LocalDateTime | 거래/이벤트 시각 |
description | String? | 표준 라벨 (아래 참조) |
reason | CreditTransactionReason? | 어드민 수동 거래 사유 |
memo | String? | 상세 문구 + 어드민 자유 메모. 어드민 전용 — 기업 응답에는 내려가지 않습니다 |
provisional | Boolean | 실입금이 뒷받침되지 않는 행 (= 미수). 어드민 전용 |
reverseOfTxId | Long? | 이 row 가 reverse 행이면 원본 tx id |
reversed | Boolean | 이 row 가 다른 reverse 에 의해 취소되었는지 (UI 취소선) |
createdBy | String? | 처리자 raw 식별자 (기업 memberId / ADMIN 등). 추적용 |
createdByName | String? | 처리자 표시명 — 화면에는 이 값을 씁니다 |
tag | String | 관리자가 붙인 분류 태그. 없으면 null. 예산 lock/unlock 파생 행은 항상 null |
createdByName 규칙
createdBy 에는 기업 memberId, 에이전시 memberId, ADMIN 리터럴, 어드민 식별자가 섞여 들어갑니다.
그대로 보여주면 누가 처리한 건지 알 수 없어 표시명을 함께 내립니다.
| createdBy | createdByName |
|---|---|
ADMIN / admin | 관리자 |
SYSTEM / system | 시스템 |
| 기업·에이전시 memberId | 해당 기업명 |
| 그 외 (어드민 식별자 등) | 관리자 |
기업으로 찾히지 않으면 어드민으로 봅니다 — 크레딧 원장은 기업 장부라 기업이 아닌 식별자가 남았다면
어드민 경로에서 생성된 행입니다. 원본 식별자는 createdBy 에 그대로 남으므로 추적에는 영향이 없습니다.
결제 상태와 영수증
candyPaymentId 가 있는 행은 CandyPayment 를 조회해 결제 상태와 영수증 URL 을 함께 내립니다.
결제 건이 남아 있지 않으면 네 필드 모두 null 입니다.
취소 전용 영수증 필드는 없습니다.
결제 취소 시 상태만 CANCELLED 로 바뀌고 receiptCandyUrl / receiptPerMethodUrls 는 그대로
유지됩니다. 취소건도 같은 URL 을 그대로 내려받습니다.
같은 URL 이 여는 캔디페이 영수증 페이지가 취소 상태를 반영하는지는 캔디페이 쪽 동작이라 백엔드가
보장하지 않습니다. (PG 영수증은 보통 현재 거래 상태로 렌더하므로 취소 표시로 바뀔 가능성이 높지만
확인된 바는 없습니다.) 화면 라벨은 paymentStatus / paymentCancelled 기준으로 정하세요.
description 과 memo
description 은 기업 화면에도 그대로 노출되므로 고정된 표준 라벨만 들어갑니다.
상세 문구는 memo 로 분리되어 어드민에게만 보입니다.
| description | 언제 | memo 예시 |
|---|---|---|
결제 충전 | 기업이 카드로 크레딧 충전 | — |
크레딧 충전 / 크레딧 사용 | 어드민이 글로벌 크레딧을 수동 조정 | 어드민이 입력한 메모 |
캠페인 크레딧 충전 | 제안 시 글로벌 크레딧에서 캠페인 예산으로 자동 충전 | 일괄 제안 - 5명, 200000원 |
캠페인 결제 | 캠페인 초기 결제 | 관리자 대리 결제 / 관리자 대리 결제 (미충전) |
캠페인 잔액 환급 | 캠페인 종료 시 미사용 예산 환급 | — |
마이너스 잔액과 provisional
어드민이 캠페인을 결제됨으로 바꿀 때 기업 잔액이 부족하면, 부족한 만큼 잔액이 마이너스로
남습니다. 그 CAMPAIGN_DEPOSIT 행에 provisional: true 가 붙고 balanceAfter 가 음수가 됩니다.
마이너스 잔액 = 아직 받지 못한 금액(미수) 입니다. 실입금이 확인되어 어드민이 그만큼 크레딧을 충전하면 마이너스가 메워지며 0 이상으로 회복됩니다. 캠페인은 이미 결제됨 상태이므로 별도 처리는 필요 없습니다.
provisional: true 인 CAMPAIGN_DEPOSIT 행을 모으면 미수 캠페인 목록이 됩니다.
provisional 과 memo 는 어드민 전용이라 기업·에이전시 응답에는 포함되지 않습니다
(에이전시는 예외적으로 본인이 지급하며 입력한 AGENCY_GRANT 행의 memo 만 봅니다).
에러
| 상태 | 설명 |
|---|---|
404 | 기업을 찾을 수 없음 |