refactor(puzzle): route finish rewards through InventoryService

Replace RewardGrantService + HttpContext.RequestServices viewer load with
IInventoryService tx. Single BeginAsync/GrantAsync/CommitAsync wraps all
mission rewards on the win path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-31 16:40:16 -04:00
parent 4ba7d8f6d0
commit a310697830

View File

@@ -1,12 +1,11 @@
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SVSim.Database;
using SVSim.Database.Enums;
using SVSim.Database.Repositories.Globals;
using SVSim.Database.Repositories.Viewer;
using SVSim.Database.Services;
using SVSim.Database.Services.Inventory;
using SVSim.EmulatedEntrypoint.Models.Dtos.Common.BasicPuzzle;
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.BasicPuzzle;
@@ -26,20 +25,20 @@ public class PuzzleController : SVSimController
private readonly IPuzzleCatalogRepository _catalog;
private readonly IPuzzleClearRepository _clears;
private readonly PuzzleMissionEvaluator _evaluator;
private readonly RewardGrantService _rewards;
private readonly IInventoryService _inv;
private readonly ILogger<PuzzleController> _logger;
public PuzzleController(
IPuzzleCatalogRepository catalog,
IPuzzleClearRepository clears,
PuzzleMissionEvaluator evaluator,
RewardGrantService rewards,
IInventoryService inv,
ILogger<PuzzleController> logger)
{
_catalog = catalog;
_clears = clears;
_evaluator = evaluator;
_rewards = rewards;
_inv = inv;
_logger = logger;
}
@@ -175,28 +174,15 @@ public class PuzzleController : SVSimController
if (fresh.Count > 0)
{
// Load viewer with all the collections RewardGrantService might mutate. Split-query
// to avoid the cartesian-explode pitfall (CLAUDE.md "EF split query").
var ctx = HttpContext.RequestServices.GetRequiredService<SVSimDbContext>();
var viewer = await ctx.Viewers
.Include(v => v.Cards).ThenInclude(c => c.Card)
.Include(v => v.Sleeves)
.Include(v => v.Emblems)
.Include(v => v.LeaderSkins)
.Include(v => v.Degrees)
.Include(v => v.MyPageBackgrounds)
.Include(v => v.Items).ThenInclude(i => i.Item)
.AsSplitQuery()
.FirstAsync(v => v.Id == viewerId);
await using var tx = await _inv.BeginAsync(viewerId);
foreach (var status in fresh)
{
IReadOnlyList<GrantedReward> granted;
IReadOnlyList<SVSim.Database.Services.GrantedReward> granted;
try
{
granted = await _rewards.ApplyAsync(
viewer,
(SVSim.Database.Enums.UserGoodsType)status.Mission.RewardType,
granted = await tx.GrantAsync(
(UserGoodsType)status.Mission.RewardType,
status.Mission.RewardDetailId,
status.Mission.RewardNumber);
}
@@ -229,7 +215,7 @@ public class PuzzleController : SVSimController
}
}
await ctx.SaveChangesAsync();
await tx.CommitAsync();
}
response.WinCount = "1";