refactor(itempurchase): route currency spend (not items) through CurrencySpendService
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,12 +23,14 @@ public class ItemPurchaseController : SVSimController
|
|||||||
private readonly SVSimDbContext _db;
|
private readonly SVSimDbContext _db;
|
||||||
private readonly RewardGrantService _rewards;
|
private readonly RewardGrantService _rewards;
|
||||||
private readonly TimeProvider _time;
|
private readonly TimeProvider _time;
|
||||||
|
private readonly ICurrencySpendService _spend;
|
||||||
|
|
||||||
public ItemPurchaseController(SVSimDbContext db, RewardGrantService rewards, TimeProvider time)
|
public ItemPurchaseController(SVSimDbContext db, RewardGrantService rewards, TimeProvider time, ICurrencySpendService spend)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_rewards = rewards;
|
_rewards = rewards;
|
||||||
_time = time;
|
_time = time;
|
||||||
|
_spend = spend;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("info")]
|
[HttpPost("info")]
|
||||||
@@ -117,7 +119,7 @@ public class ItemPurchaseController : SVSimController
|
|||||||
var rewardList = new List<RewardListEntry>();
|
var rewardList = new List<RewardListEntry>();
|
||||||
|
|
||||||
// Debit the require side. RewardGrantService is grant-only, so handle this inline.
|
// Debit the require side. RewardGrantService is grant-only, so handle this inline.
|
||||||
var debit = TryDebit(viewer, (UserGoodsType)entry.RequireItemType, entry.RequireItemId, entry.RequireItemNum);
|
var debit = await TryDebit(viewer, (UserGoodsType)entry.RequireItemType, entry.RequireItemId, entry.RequireItemNum);
|
||||||
if (debit.Error is not null) return BadRequest(new { error = debit.Error });
|
if (debit.Error is not null) return BadRequest(new { error = debit.Error });
|
||||||
if (debit.PostState is not null) rewardList.Add(debit.PostState);
|
if (debit.PostState is not null) rewardList.Add(debit.PostState);
|
||||||
|
|
||||||
@@ -160,29 +162,29 @@ public class ItemPurchaseController : SVSimController
|
|||||||
/// from the viewer, returning a post-state-aware <see cref="RewardListEntry"/> the client
|
/// from the viewer, returning a post-state-aware <see cref="RewardListEntry"/> the client
|
||||||
/// uses to refresh its cached count. Returns an error string on insufficient balance.
|
/// uses to refresh its cached count. Returns an error string on insufficient balance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static (RewardListEntry? PostState, string? Error) TryDebit(
|
private async Task<(RewardListEntry? PostState, string? Error)> TryDebit(
|
||||||
Viewer viewer, UserGoodsType type, long detailId, int num)
|
Viewer viewer, UserGoodsType type, long detailId, int num)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case UserGoodsType.RedEther:
|
case UserGoodsType.RedEther:
|
||||||
if (viewer.Currency.RedEther < (ulong)num)
|
{
|
||||||
return (null, "insufficient_red_ether");
|
var r = await _spend.TrySpendAsync(viewer, SpendCurrency.RedEther, num);
|
||||||
viewer.Currency.RedEther -= (ulong)num;
|
if (!r.Success) return (null, "insufficient_red_ether");
|
||||||
return (new RewardListEntry { RewardType = 1, RewardId = 0, RewardNum = (int)viewer.Currency.RedEther }, null);
|
return (new RewardListEntry { RewardType = 1, RewardId = 0, RewardNum = (int)r.PostStateTotal }, null);
|
||||||
|
}
|
||||||
case UserGoodsType.Crystal:
|
case UserGoodsType.Crystal:
|
||||||
if (viewer.Currency.Crystals < (ulong)num)
|
{
|
||||||
return (null, "insufficient_crystals");
|
var r = await _spend.TrySpendAsync(viewer, SpendCurrency.Crystal, num);
|
||||||
viewer.Currency.Crystals -= (ulong)num;
|
if (!r.Success) return (null, "insufficient_crystals");
|
||||||
return (new RewardListEntry { RewardType = 2, RewardId = 0, RewardNum = (int)viewer.Currency.Crystals }, null);
|
return (new RewardListEntry { RewardType = 2, RewardId = 0, RewardNum = (int)r.PostStateTotal }, null);
|
||||||
|
}
|
||||||
case UserGoodsType.Rupy:
|
case UserGoodsType.Rupy:
|
||||||
if (viewer.Currency.Rupees < (ulong)num)
|
{
|
||||||
return (null, "insufficient_rupees");
|
var r = await _spend.TrySpendAsync(viewer, SpendCurrency.Rupee, num);
|
||||||
viewer.Currency.Rupees -= (ulong)num;
|
if (!r.Success) return (null, "insufficient_rupees");
|
||||||
return (new RewardListEntry { RewardType = 9, RewardId = 0, RewardNum = (int)viewer.Currency.Rupees }, null);
|
return (new RewardListEntry { RewardType = 9, RewardId = 0, RewardNum = (int)r.PostStateTotal }, null);
|
||||||
|
}
|
||||||
case UserGoodsType.Item:
|
case UserGoodsType.Item:
|
||||||
var owned = viewer.Items.FirstOrDefault(i => i.Item.Id == (int)detailId);
|
var owned = viewer.Items.FirstOrDefault(i => i.Item.Id == (int)detailId);
|
||||||
if (owned is null || owned.Count < num)
|
if (owned is null || owned.Count < num)
|
||||||
|
|||||||
Reference in New Issue
Block a user