SaaS APIProgress Table
POST /ai/progress-table/items/bulk/proposal-with-charge
예산 자동 충전 + 제안 일괄 처리
예산 자동 충전 + 제안 일괄 처리
캠페인 예산이 부족한 경우 글로벌 크레딧에서 자동으로 충전한 후, 선택된 인플루언서들의 상태를 PROPOSAL로 변경하고 예산을 LOCK합니다.
처리 흐름
- 선택된 Application들의 총 필요 금액 계산
- 캠페인 가용 예산 확인
- 예산 부족 시 글로벌 크레딧에서 캠페인 예산으로 자동 충전 (
forceCharge=true인 경우) - 각 Application에 대해 예산 LOCK + 상태 PROPOSAL로 변경
- 상세 트래킹 정보 반환
HTTP 요청
POST /ai/progress-table/items/bulk/proposal-with-charge
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body
{
"collabId": 123,
"itemIds": [1, 2, 3],
"forceCharge": true
}Request Body 스키마
| 필드명 | 타입 | 필수 | 설명 |
|---|---|---|---|
collabId | long | 예 | 캠페인 ID (collabNo) |
itemIds | array<long> | 예 | CampaignApplication ID 목록 |
forceCharge | boolean | 아니오 | 예산 부족 시 자동 충전 여부 (기본: true) |
응답
성공 응답 (200 OK)
{
"status": 200,
"code": null,
"message": "3명의 크리에이터에게 제안을 보냈습니다.",
"data": {
"success": true,
"message": "3명의 크리에이터에게 제안을 보냈습니다.",
"totalRequested": 3,
"totalProcessed": 3,
"totalAmount": 1500000,
"budgetBefore": 500000,
"budgetAfter": 0,
"chargedAmount": 1000000,
"globalCreditBefore": 5000000,
"globalCreditAfter": 4000000,
"processedItems": [
{
"applicationId": 1,
"influenceName": "인플루언서A",
"amount": 500000,
"success": true
},
{
"applicationId": 2,
"influenceName": "인플루언서B",
"amount": 500000,
"success": true
},
{
"applicationId": 3,
"influenceName": "인플루언서C",
"amount": 500000,
"success": true
}
],
"failedItems": null
}
}Response Body 스키마
| 필드명 | 타입 | 설명 |
|---|---|---|
success | boolean | 처리 성공 여부 |
message | string | 결과 메시지 |
errorCode | string | 실패 시 에러 코드 |
totalRequested | int | 요청된 총 인원수 |
totalProcessed | int | 성공적으로 처리된 인원수 |
totalAmount | int | 총 차감 금액 |
budgetBefore | int | 처리 전 캠페인 가용 예산 |
budgetAfter | int | 처리 후 캠페인 가용 예산 |
chargedAmount | int | 글로벌 크레딧에서 충전한 금액 (0이면 충전 없음) |
globalCreditBefore | int | 처리 전 글로벌 크레딧 |
globalCreditAfter | int | 처리 후 글로벌 크레딧 |
processedItems | array | 성공한 항목별 처리 결과 |
failedItems | array | 실패 항목 (부분 실패 시) |
ProposalItemResult 스키마
| 필드명 | 타입 | 설명 |
|---|---|---|
applicationId | long | Application ID |
influenceName | string | 인플루언서 이름 |
amount | int | 차감 금액 |
success | boolean | 처리 성공 여부 |
errorMessage | string | 실패 시 에러 메시지 |
에러 응답
| 상태 코드 | 에러 코드 | 설명 |
|---|---|---|
| 400 | LEGACY_CAMPAIGN | 레거시 캠페인은 이 기능을 사용할 수 없습니다 |
| 400 | NO_APPLICATIONS | 처리할 신청 항목이 없습니다 |
| 400 | NO_ELIGIBLE_ITEMS | 처리 가능한 항목이 없습니다 |
| 400 | BUDGET_001 | 캠페인 예산이 부족합니다 (forceCharge=false일 때) |
| 400 | BUDGET_002 | 기업 크레딧이 부족합니다 |
자동 충전이 발생하는 경우
chargedAmount > 0이면 글로벌 크레딧에서 캠페인 예산으로 자동 이체가 발생한 것입니다.
이 경우 CreditTransaction 테이블에 CAMPAIGN_DEPOSIT 타입으로 기록됩니다.
예산 관리 정책
- 크리에이터 제안 시 예산 LOCK은
CampaignBudget테이블에서만 관리됩니다 CreditTransaction은 글로벌 크레딧 ↔ 캠페인 예산 간 이동 시에만 기록됩니다- 제안 취소(UNLOCK) 시에도
CreditTransaction은 기록되지 않습니다