Admin APIAdmin Finance API
POST /ai/admin/finance/ledger/business/{businessAccountId}/entry
과거일자 크레딧 이력 기입 (balance_after 자동 재계산)
과거일자 크레딧 이력 기입
가계부처럼 원하는 날짜를 지정해 크레딧 원장에 한 줄을 넣습니다.
기입 지점 이후 행들의 balanceAfter 가 자동으로 재계산되고, 기업 글로벌 잔액도 기입 금액만큼 이동합니다.
기존 credit-tx API 가 "원본 불변 + reverse 행 추가" 규약이라면, ledger API 는
"행을 직접 고치고 이후 잔액을 다시 계산" 규약입니다. 두 경로는 공존하며, ledger API 는
레거시 reverse 쌍에는 손대지 않습니다.
HTTP 요청
POST /ai/admin/finance/ledger/business/{businessAccountId}/entry?adminId={adminId}
Authorization: Bearer {access_token}
Content-Type: application/jsonPath / Query Parameters
| 파라미터 | 위치 | 타입 | 필수 | 설명 |
|---|---|---|---|---|
businessAccountId | path | Long | 예 | 기업 계정 ID |
adminId | query | String | 아니오 | 처리자 ID (생략 시 admin) |
Request Body
{
"occurredAt": "2026-07-03T10:00:00",
"amount": -100000,
"transactionType": null,
"collabNo": 482,
"description": "7월 초 누락분 정정",
"reason": "ETC",
"memo": "정산 대사 중 발견",
"provisional": false
}| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
occurredAt | LocalDateTime | 아니오 | 발생일. 생략 시 현재 시각. 미래 시각은 거부 |
amount | Integer | 예 | 증감액. 양수=증가, 음수=감소. 0 불가 |
transactionType | CreditTransactionType | 아니오 | 생략 시 부호로 CREDIT_ADD / CREDIT_DEDUCT 자동 선택 |
collabNo | Integer | 아니오 | 캠페인 스코프 거래일 때의 캠페인 번호 |
description | String | 아니오 | 비고. 생략 시 어드민 수기 기입 |
reason | CreditTransactionReason | 아니오 | 거래 사유 |
memo | String | 조건부 | reason=ETC 일 때 필수 |
provisional | Boolean | 아니오 | 임시 크레딧 여부. 생략 시 false |
BUDGET_ADJUST / CAMPAIGN_LOCK / CAMPAIGN_UNLOCK 은 예산·락 상태에서 파생되는 타입이라
수기 기입할 수 없습니다 (400).
재계산 동작
기입 지점을 앵커로 삼아, 앵커 직전 행의 balanceAfter 를 시작값으로 이후 행을 다시 더합니다.
앵커 이전 행은 한 줄도 바뀌지 않습니다.
[기입 전]
07-01 +100,000 → 100,000
07-05 -30,000 → 70,000
07-09 -20,000 → 50,000
[07-03 에 -10,000 기입]
07-01 +100,000 → 100,000 (그대로)
07-03 -10,000 → 90,000 ← 신규
07-05 -30,000 → 60,000 ← 재계산
07-09 -20,000 → 40,000 ← 재계산
remainCredit: 50,000 → 40,000 (델타 -10,000 만 이동)BUDGET_ADJUST 행은 잔액을 움직이지 않으므로 합산에서 제외되고 직전 잔액을 그대로 복사합니다.
응답 (200 OK)
{
"status": 200,
"code": null,
"message": "크레딧 이력 기입 완료",
"data": {
"transaction": {
"id": 2311,
"businessId": 10,
"transactionType": "CREDIT_DEDUCT",
"amount": -100000,
"balanceAfter": 90000,
"collabNo": 482,
"candyPaymentId": null,
"description": "7월 초 누락분 정정",
"reason": "ETC",
"memo": "정산 대사 중 발견",
"reverseOfTxId": null,
"createdAt": "2026-08-11T14:02:11",
"occurredAt": "2026-07-03T10:00:00",
"provisional": false,
"provisionalSettledAt": null,
"deletedAt": null,
"createdBy": "admin01"
},
"recalculatedCount": 3,
"newRemainCredit": 40000,
"expectedRemainCredit": 40000,
"balanceMismatch": false
}
}| 필드 | 설명 |
|---|---|
recalculatedCount | balanceAfter 를 다시 쓴 행 수 (신규 행 포함) |
newRemainCredit | 변경 후 실제 기업 잔액 |
expectedRemainCredit | 원장 마지막 행의 balanceAfter — 원장이 말하는 잔액 |
balanceMismatch | 위 두 값이 다르면 true |
balanceMismatch: true 는 이번 기입이 잘못됐다는 뜻이 아니라, 과거 데이터에 이미
드리프트가 있었다는 신호입니다. 재계산은 그 차이를 임의로 덮지 않고(무관한 과거 오차가
현재 잔액으로 튀는 것을 막기 위해) 드러내기만 합니다.
에러
| 상태 | 조건 |
|---|---|
400 | amount=0, 미래 occurredAt, 파생 타입 지정, reason=ETC + memo 누락 |
503 | 동시 요청으로 기업 행 락 경합 (DB_LOCK_ERROR) — 재시도 |
응답은 HTTP 200 으로 내려가고 실제 상태 코드는 body 의 status 필드에 담깁니다 (프로젝트 공통 규약).