deductPoints์ SPRINT2_SPEND_HOOK์ด local balance check ์ดํ โ local 0์ด๋ฉด throw โ hook ๋๋ฌ ๋ชป ํจgetOrCreateAccount ์ )async deductPoints(userId, amount, type, description, referenceType, referenceId) {
// SPRINT11_HOOK_RELOCATED โ central ์ฐ์ ํธ์ถ (local balance check ์ )
try {
const _centralSpend = await callCentralApi('POST', '/spend', {
userId, amount, type, description, referenceType, referenceId,
platform: POINT_PLATFORM,
});
if (_centralSpend) {
return { success:true, spentPoints:amount,
newBalance:_centralSpend.balanceAfter ?? _centralSpend.balance ?? 0,
transaction:_centralSpend.transactionId ? {id: _centralSpend.transactionId}:null,
_source:'central' };
}
} catch (_e) { /* fallback to local */ }
// SPRINT11_HOOK_RELOCATED end
const account = await this.getOrCreateAccount(userId); // ๊ธฐ์กด ์ฝ๋
if (account.balance < amount) throw...
...
}
1. test-hospital local point_account balance๋ฅผ ๊ฐ์ ๋ก 0์ผ๋ก reset
2. POST /api/v1/points/cross-platform/deduct {userId, amount:200}
3. ์๋ต: {success:true, spentPoints:200, newBalance:600, _source:"central"}
4. unified: 800P โ 600P (-200) โ
โ local ์๊ณ 0์ด๋ผ๋ SPRINT11_HOOK_RELOCATED๊ฐ ํจ์ ์์์์ ๋ฐ๋ โ central ์ฐ์ ํธ์ถ โ unified ์ฐจ๊ฐ โ return early. local DB ์ ๊ฑฐ์นจ.
callCentralApi('POST', '/spend') ์ง์ ํธ์ถ ์ ํ ์์น โ
| platform | trigger | sprint | ๊ฒฐ๊ณผ |
|---|---|---|---|
| assistant | admin-points/deduct | #8 | โ -300 |
| legal | product purchase | #8 | โ -200 |
| finance | user spend endpoint | #9 | โ -400 |
| pet | cross-platform/deduct | #10 | โ -250 |
| hospital | cross-platform/deduct (local fix) | #10 | โ -300 |
| hospital (relocated) | cross-platform/deduct (local 0) | #11 | โ -200 (central first proven) |
| shop | (์ ์ ๊ฒ์ฆ) | โ | ๐ก ์ฝ๋ โ , ๋น์ฆ๋์ค trigger ์์กด |
โ 5/6 platform ์ง์ง E2E PASS + hospital ๊ฐ์ (local ์๊ณ 0์ด๋ผ๋ unified ์ฐจ๊ฐ ๊ฐ๋ฅ)
โ MCO ๋ธ๋ก๊ทธ โ message_id 10174