Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/credits.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ total=available+reserved이며 사용 확정된 양은 제외한다. 원장은 I
| 성공 확정 N | 0 | -N | SETTLE |
| 실패/취소/만료 해제 N | +N | -N | RELEASE |

지급 출처는 오래된 ID부터 배분하며 배분 관계를 영구 기록한다. 각 출처의 available/reserved/consumed를 구분해 구매분과 무상 지급분을 추적한다. 계정 잔액과 지급 출처·예약·원장이 같은 트랜잭션으로 변경된다. 금액이 아닌 정수 크레딧이며 long 범위 초과와 음수 잔액은 거절한다.
신규 예약은 무료 지급분(SIGNUP·ATTENDANCE·PROMOTION)을 먼저 배분하고 부족한 수량만 유료 지급분(PAYMENT)에서 배분한다. 각 그룹 안에서는 오래된 지급 ID부터 사용한다. 무료 종류별 우선순위는 없고 DB 정렬 후 페이지를 조회하므로 100개를 넘는 지급 건에서도 무료 우선순위를 유지한다. 배분 관계는 영구 기록하며 각 출처의 available/reserved/consumed를 구분해 구매분과 무상 지급분을 추적한다. 계정 잔액과 지급 출처·예약·원장이 같은 트랜잭션으로 변경된다. 금액이 아닌 정수 크레딧이며 long 범위 초과와 음수 잔액은 거절한다.

#130 배포 이전에 만들어진 예약·사용 내역·원장은 재배분하거나 소급 변경하지 않는다. 기존 예약의 재요청은 최초 수량·기한·출처를 유지하며 성공 확정과 실패/취소/만료 해제는 저장된 배분을 따른다. 예약 이후 무료 지급분이 추가돼도 진행 중인 예약을 옮기지 않는다. 실패 시에는 원래 출처로 복원하므로 유료분을 무료분으로 바꾸거나 이중 복원하지 않는다.

예를 들어 유료10개 구매 후 무료3개를 지급받았다면 새 이미지 생성3개는 무료에서만 예약한다. 무료1개와 유료10개로 새 이미지 생성3개를 요청하면 무료1개·유료2개를 예약하고, 성공하면 그대로 확정하며 실패하면 각각 원래 출처로 돌려준다. 이 변경은 차감 출처의 순서이며 이미지 3/무료/1 가격·무기한·사용 보류 정책이나 구매 환불 기능을 변경하지 않는다.

예약 상태는 RESERVED에서 SETTLED 또는 RELEASED로 한 번만 이동한다. 확정 후 해제·해제 후 확정은 충돌한다. 동일 resultKey의 확정 재전송은 기존 성공을 반환한다. 중복 예약은 최초 사용량·기한·최종 상태를 유지하며 연장/새 차감을 하지 않는다. 설정이 바뀌어도 기존 예약 수량은 바뀌지 않는다. 다른 요청 키로 같은 usage/target 시도를 다시 예약할 수도 없다.

Expand Down
6 changes: 6 additions & 0 deletions docs/frontend-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ Refresh는 앱 전체에서 한 번씩 실행되도록 묶는다. StrictMode·
- 잔액은 available/reserved/total 및 보류 여부를 구분한다. 최초 온보딩 완료 시 기본3크레딧, 크레딧 무기한. 지급 내역이 없는 기존 완료 계정은0이며 자동 소급하지 않는다. 구매 취소와 생성 실패 예약 해제는 다른 처리다.
- 구매 환불 신청·자동 회수/보류 해제 API는 아직 없다. 법정 환불 접수·운영 취소 처리 경로는 별도 준비 중이며 일괄 환불 불가를 확정한 것은 아니다.

## 무료 크레딧 우선 차감 (#130)

새 이미지 생성/재생성 비용은 서버가 무료(SIGNUP·ATTENDANCE·PROMOTION)부터 예약하고 부족한 수량만 유료(PAYMENT)에서 예약합니다. 같은 그룹 내에서는 먼저 지급한 순서입니다. API 경로·요청·응답과 이미지 3/무료/1 비용은 바뀌지 않습니다.
프론트는 차감 출처를 선택하거나 환불액을 계산하지 않습니다. 생성 요청 후 기존 GET /api/v1/credits/balance의 paidAvailable·paidReserved·freeAvailable·freeReserved를 다시 조회해 표시합니다. 실패/취소/만료 시에는 원래 출처별로 복원하고 성공 시 최초 배분을 확정합니다.
배포 전 예약과 이미 사용한 내역은 소급 변경하지 않으며 예약 후 무료 보상이 추가돼도 진행 중인 예약은 옮기지 않습니다. 환불 신청·PG 환불 API를 추가하는 작업은 아닙니다. 별도 환경변수·DB 마이그레이션 없이 머지·CD 후 새 예약부터 적용됩니다.

## 필수 문서 동의 (#128)

GET /api/v1/legal/documents는 공개 상태와 필수 문서 두 항목의 버전·해시를 반환합니다.
Expand Down
1 change: 1 addition & 0 deletions docs/payapp-payments.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[실결제 설정·프론트 복구·운영 검증 안내](payapp-live-readiness.md)를 함께 확인한다.
유상/무료 크레딧 모두 무기한으로 사용하는 정책을 반영해 expiry-policy 기본은 NO_EXPIRY로 변경했다.
결제 모듈은 구매 환불 신청·PG 자동 환불·실물 상품을 포함하지 않는다. 가입 지급과 이미지 과금은 별도 크레딧 기능을 재사용한다.
신규 이미지 예약은 무료 지급분을 먼저 사용하고 부족한 수량만 구매 지급분에서 사용한다(#130). 같은 그룹 안에서는 지급 ID 순서를 유지하며 기존 예약·사용 원장은 소급 변경하지 않는다. 구매별 사용량은 계정 전체 잔액이 아니라 저장된 출처별 예약·확정 배분으로 확인한다. [크레딧 예약 계약](credits.md)을 따른다.

## 공개 계약

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
public interface CreditGrantRepository extends JpaRepository<CreditGrant, Long> {
Optional<CreditGrant> findFirstByUserIdAndSourceTypeOrderByIdAsc(Long userId, CreditSource sourceType);
Optional<CreditGrant> findBySourceTypeAndSourceHash(CreditSource type, String hash);
@Query("select g from CreditGrant g where g.userId=:userId and g.available>0 order by g.id")
// Apply priority before pagination; retain grant order within free and paid groups.
@Query("select g from CreditGrant g where g.userId=:userId and g.available>0 "
+ "order by case when g.sourceType=com.mongle.backend.domain.credit.CreditSource.PAYMENT then 1 else 0 end,g.id")
List<CreditGrant> available(@Param("userId") Long userId, Pageable page);
}
Loading