Glowb Dev Docs
Admin APIAdmin Finance API

원장 전체 재계산

기업 원장의 balance_after 와 remain_credit 을 첫 행부터 다시 굴려 한 번에 맞춥니다.

원장 전체 재계산

기업 원장의 balanceAfter 를 첫 행부터 끝까지 다시 계산하고, 기업 잔액(remainCredit)을 원장 마지막 값에 맞춥니다.

기존 수정·삭제 API(PUT /ledger/{txId} 등)는 고친 행 이후만 다시 계산합니다. 이 API는 앵커 없이 전 구간을 다시 계산합니다.

언제 쓰나

  • 원장과 기업 잔액이 어긋나 있을 때 (과거 데이터 정리, 마이그레이션 후 보정)
  • 과거 내역을 여러 건 넣은 뒤 한 번에 정리할 때
  • 원장 도입 이전 이월분(기초 잔액)이 틀려서 바로잡을 때

지금까지 이런 상황에서 DB 에 직접 UPDATE ... SUM(amount) OVER (...) 를 돌렸다면, 이 API 로 대체하세요. 손으로 쓴 쿼리는 BUDGET_ADJUST 행을 합산에서 빼지 않아 잔액이 어긋나기 쉽고, TB_BUSINESS.remain_credit 도 함께 갱신되지 않습니다.

HTTP 요청

POST /ai/admin/finance/ledger/business/{businessAccountId}/recalculate
Authorization: Bearer {access_token}

Path Parameters

파라미터타입필수설명
businessAccountIdLong예기업 계정 id

Query Parameters

파라미터타입필수기본값설명
applyboolean아니오falsefalse 면 미리보기(아무것도 저장 안 함). true 여야 실제로 저장
adminIdString아니오—처리자 ID (로그 기록용)

apply 를 빠뜨리면 아무 일도 일어나지 않습니다. 기업 원장을 통째로 다시 쓰는 작업이라 미리보기를 기본으로 뒀습니다. 화면에서는 "미리보기 → 결과 확인 → 적용" 2단계로 붙여주세요.

계산 규칙

항목규칙
정렬occurredAt ASC, id ASC
대상소프트 삭제되지 않은 행 (deletedAt IS NULL)
합산 제외BUDGET_ADJUST — 예산 수정 audit 행이라 amount 가 0 이 아니어도 잔액을 움직이지 않음
시작값첫 행에서 역산한 이월분 = 첫 행.balanceAfter - 첫 행.amount

이월분(기초 잔액)이란

원장은 나중에 도입됐습니다. 그 이전의 충전·차감은 행이 없고 결과만 기업 잔액에 남아 있습니다. 그래서 첫 행의 balanceAfter 가 그 행의 amount 보다 큽니다.

행타입amountbalanceAfter
1CREDIT_ADD+50,000150,000
2CAMPAIGN_DEPOSIT-30,000120,000
3CREDIT_ADD+20,000140,000

첫 행의 150,000 - 50,000 = 100,000 이 원장에 행으로 없는 이월분입니다. 재계산은 이 값에서 출발하므로 기존 잔액이 보존됩니다.

이월분이 틀렸을 때

이 API 는 이월분을 바꾸지 않습니다. 지금 값을 그대로 쓰고 아래로 굴리기만 합니다. 이월분 자체가 틀렸다면 첫 행 잔액 지정 API 를 쓰세요. 응답 형태는 같습니다.

응답

성공 (200 OK)

{
  "status": 200,
  "code": null,
  "message": "원장 재계산 미리보기",
  "data": {
    "businessAccountId": 418,
    "openingBalance": 100000,
    "firstTxId": 451,
    "openingOverridden": false,
    "applied": false,
    "scannedCount": 168,
    "mismatchedCount": 12,
    "remainCreditBefore": 140000,
    "remainCreditAfter": 120000,
    "skippedEmptyLedger": false,
    "diffs": [
      {
        "txId": 619,
        "occurredAt": "2026-08-05T17:55:06",
        "transactionType": "CAMPAIGN_DEPOSIT",
        "amount": -30000,
        "balanceAfterBefore": 999,
        "balanceAfterCalculated": 120000
      }
    ],
    "diffsTruncated": 0
  }
}

필드

필드타입설명
openingBalanceint이번 계산에 쓴 이월분(시작값)
firstTxIdLong원장 첫 행 id. 원장이 비었으면 null
openingOverriddenboolean이월분을 덮어썼는가. 이 API 에서는 항상 false (첫 행 잔액 지정에서만 true)
appliedboolean실제로 저장했는가. false 면 미리보기
scannedCountint훑은 행 수
mismatchedCountint계산값과 달랐던 행 수. 0 이면 원장이 이미 맞습니다
remainCreditBefore / remainCreditAfterInteger기업 잔액 변화. applied=false 면 "바뀔 값"
skippedEmptyLedgerboolean원장에 행이 없어 잔액을 건드리지 않았는가
diffsarray어긋난 행 샘플 (최대 100건)
diffsTruncatedint샘플에 못 담고 잘린 행 수

에러

상태 코드설명
404기업을 찾을 수 없음

화면 연동 순서

  1. apply 없이 호출 → mismatchedCount 와 diffs 로 무엇이 어긋났는지 표시
  2. 확인되면 apply=true 로 실행
  3. openingBalance 자체가 틀렸다면 첫 행 잔액 지정 API 로 먼저 바로잡기

현재 첫 행보다 더 오래된 행을 새로 넣으면 첫 행이 바뀝니다. 그러면 이월분도 새 첫 행 기준으로 다시 역산되므로 값이 달라질 수 있습니다. 응답의 firstTxId 로 첫 행이 무엇인지 확인하세요.

안전장치

  • 원장에 행이 없으면 잔액을 건드리지 않습니다 (0 으로 밀면 원장 밖에서 들어온 잔액이 사라짐)
  • apply=true 시 기업 행을 잠급니다 (동시에 들어온 거래가 덮어써지지 않도록)
  • 미리보기는 읽기 전용 트랜잭션이라 저장 경로가 아예 없습니다

API 테스트

On this page