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:
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user