refactor(battlepass): route premium-buy crystal spend through CurrencySpendService

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-29 14:23:50 -04:00
parent ee407befb5
commit d68a85bbc5

View File

@@ -23,19 +23,22 @@ public sealed class BattlePassService : IBattlePassService
private readonly TimeProvider _time;
private readonly SVSimDbContext _db;
private readonly RewardGrantService _rewards;
private readonly ICurrencySpendService _spend;
public BattlePassService(
IBattlePassRepository bp,
IViewerBattlePassRepository viewerBp,
TimeProvider time,
SVSimDbContext db,
RewardGrantService rewards)
RewardGrantService rewards,
ICurrencySpendService spend)
{
_bp = bp;
_viewerBp = viewerBp;
_time = time;
_db = db;
_rewards = rewards;
_spend = spend;
}
public async Task<IReadOnlyDictionary<string, BattlePassLevel>?> GetLevelCurveAsync(CancellationToken ct)
@@ -166,13 +169,13 @@ public sealed class BattlePassService : IBattlePassService
if (progress.IsPremium)
return new BattlePassBuyOutcome(23, Array.Empty<GrantedReward>(), Array.Empty<GrantedReward>());
if (viewer.Currency.Crystals < (ulong)season.PriceCrystal)
var spendResult = await _spend.TrySpendAsync(viewer, SpendCurrency.Crystal, season.PriceCrystal, ct);
if (!spendResult.Success)
return new BattlePassBuyOutcome(22, Array.Empty<GrantedReward>(), Array.Empty<GrantedReward>());
// BeginTransactionAsync is a no-op on the SQLite in-memory test DB but is safe to call.
await using var tx = await _db.Database.BeginTransactionAsync(ct);
viewer.Currency.Crystals -= (ulong)season.PriceCrystal;
progress.IsPremium = true;
// Retroactive grants: every premium reward at level <= current_level not already claimed.
@@ -206,7 +209,7 @@ public sealed class BattlePassService : IBattlePassService
// 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, (int)viewer.Currency.Crystals));
(int)UserGoodsType.Crystal, 0, (int)spendResult.PostStateTotal));
return new BattlePassBuyOutcome(1, achieved, postState);
}