refactor(leaderskin): route currency spend through CurrencySpendService

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-29 14:17:01 -04:00
parent 1f58461326
commit fb257a544f

View File

@@ -30,12 +30,14 @@ public class LeaderSkinController : 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 LeaderSkinController(SVSimDbContext db, RewardGrantService rewards, TimeProvider time) public LeaderSkinController(SVSimDbContext db, RewardGrantService rewards, TimeProvider time, ICurrencySpendService spend)
{ {
_db = db; _db = db;
_rewards = rewards; _rewards = rewards;
_time = time; _time = time;
_spend = spend;
} }
[HttpPost("set")] [HttpPost("set")]
@@ -175,7 +177,7 @@ public class LeaderSkinController : SVSimController
return BadRequest(new { error = "already_purchased" }); return BadRequest(new { error = "already_purchased" });
var rewardList = new List<RewardListEntry>(); var rewardList = new List<RewardListEntry>();
var debit = DebitProductPrice(viewer, product, request.SalesType); var debit = await DebitProductPrice(viewer, product, request.SalesType);
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);
@@ -206,7 +208,7 @@ public class LeaderSkinController : SVSimController
var viewer = await LoadViewerGraphAsync(viewerId); var viewer = await LoadViewerGraphAsync(viewerId);
var rewardList = new List<RewardListEntry>(); var rewardList = new List<RewardListEntry>();
var debit = DebitSetPrice(viewer, series, request.SalesType); var debit = await DebitSetPrice(viewer, series, request.SalesType);
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);
@@ -332,52 +334,58 @@ public class LeaderSkinController : SVSimController
return false; return false;
} }
private (RewardListEntry? PostState, string? Error) DebitProductPrice( private async Task<(RewardListEntry? PostState, string? Error)> DebitProductPrice(
Viewer viewer, LeaderSkinShopProductEntry product, int salesType) Viewer viewer, LeaderSkinShopProductEntry product, int salesType)
{ {
return salesType switch switch (salesType)
{ {
0 when product.SinglePriceCrystal == 0 && product.SinglePriceRupy == 0 => (null, null), case 0 when product.SinglePriceCrystal == 0 && product.SinglePriceRupy == 0:
0 => (null, "price_not_available_for_currency"), return (null, null);
1 => product.SinglePriceCrystal is null case 0:
? (null, "price_not_available_for_currency") return (null, "price_not_available_for_currency");
: DebitCrystal(viewer, product.SinglePriceCrystal.Value), case 1:
2 => product.SinglePriceRupy is null if (product.SinglePriceCrystal is null) return (null, "price_not_available_for_currency");
? (null, "price_not_available_for_currency") return await DebitCrystal(viewer, product.SinglePriceCrystal.Value);
: DebitRupy(viewer, product.SinglePriceRupy.Value), case 2:
_ => (null, "invalid_sales_type"), if (product.SinglePriceRupy is null) return (null, "price_not_available_for_currency");
}; return await DebitRupy(viewer, product.SinglePriceRupy.Value);
default:
return (null, "invalid_sales_type");
}
} }
private (RewardListEntry? PostState, string? Error) DebitSetPrice( private async Task<(RewardListEntry? PostState, string? Error)> DebitSetPrice(
Viewer viewer, LeaderSkinShopSeriesEntry series, int salesType) Viewer viewer, LeaderSkinShopSeriesEntry series, int salesType)
{ {
return salesType switch switch (salesType)
{ {
0 when series.SetPriceCrystal == 0 && series.SetPriceRupy == 0 => (null, null), case 0 when series.SetPriceCrystal == 0 && series.SetPriceRupy == 0:
0 => (null, "price_not_available_for_currency"), return (null, null);
1 => series.SetPriceCrystal is null case 0:
? (null, "price_not_available_for_currency") return (null, "price_not_available_for_currency");
: DebitCrystal(viewer, series.SetPriceCrystal.Value), case 1:
2 => series.SetPriceRupy is null if (series.SetPriceCrystal is null) return (null, "price_not_available_for_currency");
? (null, "price_not_available_for_currency") return await DebitCrystal(viewer, series.SetPriceCrystal.Value);
: DebitRupy(viewer, series.SetPriceRupy.Value), case 2:
_ => (null, "invalid_sales_type"), if (series.SetPriceRupy is null) return (null, "price_not_available_for_currency");
}; return await DebitRupy(viewer, series.SetPriceRupy.Value);
default:
return (null, "invalid_sales_type");
}
} }
private static (RewardListEntry?, string?) DebitCrystal(Viewer viewer, int amount) private async Task<(RewardListEntry?, string?)> DebitCrystal(Viewer viewer, int amount)
{ {
if (viewer.Currency.Crystals < (ulong)amount) return (null, "insufficient_crystals"); var r = await _spend.TrySpendAsync(viewer, SpendCurrency.Crystal, amount);
viewer.Currency.Crystals -= (ulong)amount; 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);
} }
private static (RewardListEntry?, string?) DebitRupy(Viewer viewer, int amount) private async Task<(RewardListEntry?, string?)> DebitRupy(Viewer viewer, int amount)
{ {
if (viewer.Currency.Rupees < (ulong)amount) return (null, "insufficient_rupees"); var r = await _spend.TrySpendAsync(viewer, SpendCurrency.Rupee, amount);
viewer.Currency.Rupees -= (ulong)amount; 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);
} }
private async Task ApplyRewardsAsync<T>( private async Task ApplyRewardsAsync<T>(