퀘스트 목록 페이지 판정 · 다시 읽기 · 캠페인 응원 수를 고유 후원자 기준으로
This commit is contained in:
@@ -1155,6 +1155,8 @@ export async function fundCampaign(input: {
|
||||
const fandomId = campaign.get('fandomId');
|
||||
let goal = 0;
|
||||
let raised = 0;
|
||||
// 처음 후원하는가 — 「응원 중」(donorCount)은 고유 후원자 수다. 후원 건수가 아니다(2026-10-06 실기기).
|
||||
let firstBacker = false;
|
||||
|
||||
const result = await spendPop({
|
||||
uid,
|
||||
@@ -1178,6 +1180,8 @@ export async function fundCampaign(input: {
|
||||
goal = (snap.get('targetPop') as number | undefined)
|
||||
?? (snap.get('goalPop') as number | undefined) ?? 0;
|
||||
raised = (snap.get('raisedPop') as number | undefined) ?? 0;
|
||||
// 후원자 표식(backers/{uid})이 없으면 첫 후원이다. 읽기는 쓰기보다 먼저 — 같은 트랜잭션.
|
||||
firstBacker = !(await tx.get(campaignRef.collection('backers').doc(uid))).exists;
|
||||
// 잔여분으로 깎아 받지 않고 거부한다(B-34 「잔여 목표액까지만 후원 가능」).
|
||||
if (goal > 0 && raised + amount > goal) {
|
||||
fail(ERR.campaignOverGoal, '남은 모금 목표보다 큰 금액입니다.');
|
||||
@@ -1204,7 +1208,7 @@ export async function fundCampaign(input: {
|
||||
}, { merge: true });
|
||||
tx.set(campaignRef, {
|
||||
raisedPop: FieldValue.increment(amount),
|
||||
donorCount: FieldValue.increment(1),
|
||||
...(firstBacker ? { donorCount: FieldValue.increment(1) } : {}),
|
||||
updatedAt: FieldValue.serverTimestamp(),
|
||||
}, { merge: true });
|
||||
},
|
||||
|
||||
@@ -315,6 +315,15 @@ describe('정산 분기', () => {
|
||||
expect(short.get('refundDueAt').toMillis() - Date.now()).toBeGreaterThan(71 * 3600_000);
|
||||
});
|
||||
|
||||
it('「응원 중」(donorCount)은 고유 후원자 수다 — 같은 사람의 두 번째 후원은 늘리지 않는다', async () => {
|
||||
await fundedCampaign('cmp-donors', 1_000, [[A, 100], [B, 50]]);
|
||||
await db().doc('campaigns/cmp-donors').update({ endsAt: Timestamp.fromMillis(Date.now() + 60_000) });
|
||||
await fundCampaign({ uid: A, campaignId: 'cmp-donors', clientSeq: '2', amount: 30 });
|
||||
const snap = await db().doc('campaigns/cmp-donors').get();
|
||||
expect(snap.get('donorCount')).toBe(2);
|
||||
expect(snap.get('raisedPop')).toBe(180);
|
||||
});
|
||||
|
||||
it('마감이 지난 캠페인은 정산 전이라도 후원을 받지 않는다', async () => {
|
||||
await fundedCampaign('cmp-late', 1_000, [[A, 100]]);
|
||||
expect(await code(() => fundCampaign({ uid: A, campaignId: 'cmp-late', clientSeq: '2', amount: 50 })))
|
||||
|
||||
Reference in New Issue
Block a user