review(bp): post-state reward_list from RewardGrantService, not deltas

Crystal synthesis in BuyPremiumAsync is now unconditional: always remove
any crystal entry ApplyAsync may have added, then append the fresh
post-deduction total. Prevents stale on-screen balances when a retroactive
grant also touches crystal (or when no grants fire and the conditional
guard would have been the only crystal entry).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-26 23:42:06 -04:00
parent 2cb8c271a8
commit 4438e81e37

View File

@@ -198,12 +198,12 @@ public sealed class BattlePassService : IBattlePassService
await _db.SaveChangesAsync(ct);
await tx.CommitAsync(ct);
// Post-state reward_list must also include the crystal balance after the deduction.
if (!postState.Any(r => r.RewardType == (int)UserGoodsType.Crystal))
{
// Post-state reward_list must always include the crystal balance after the deduction.
// Unconditionally overwrite: remove any crystal entry ApplyAsync may have added, then
// append the post-deduction total so the client gets the correct final balance.
postState.RemoveAll(r => r.RewardType == (int)UserGoodsType.Crystal);
postState.Add(new GrantedReward(
(int)UserGoodsType.Crystal, 0, checked((int)viewer.Currency.Crystals)));
}
return new BattlePassBuyOutcome(1, achieved, postState);
}