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 System.Text.Json;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using SVSim.Database;
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Enums;
|
||||||
using SVSim.Database.Repositories.Globals;
|
using SVSim.Database.Repositories.Globals;
|
||||||
using SVSim.Database.Repositories.Viewer;
|
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.Common.BasicPuzzle;
|
||||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
|
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
|
||||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.BasicPuzzle;
|
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.BasicPuzzle;
|
||||||
@@ -26,20 +25,20 @@ public class PuzzleController : SVSimController
|
|||||||
private readonly IPuzzleCatalogRepository _catalog;
|
private readonly IPuzzleCatalogRepository _catalog;
|
||||||
private readonly IPuzzleClearRepository _clears;
|
private readonly IPuzzleClearRepository _clears;
|
||||||
private readonly PuzzleMissionEvaluator _evaluator;
|
private readonly PuzzleMissionEvaluator _evaluator;
|
||||||
private readonly RewardGrantService _rewards;
|
private readonly IInventoryService _inv;
|
||||||
private readonly ILogger<PuzzleController> _logger;
|
private readonly ILogger<PuzzleController> _logger;
|
||||||
|
|
||||||
public PuzzleController(
|
public PuzzleController(
|
||||||
IPuzzleCatalogRepository catalog,
|
IPuzzleCatalogRepository catalog,
|
||||||
IPuzzleClearRepository clears,
|
IPuzzleClearRepository clears,
|
||||||
PuzzleMissionEvaluator evaluator,
|
PuzzleMissionEvaluator evaluator,
|
||||||
RewardGrantService rewards,
|
IInventoryService inv,
|
||||||
ILogger<PuzzleController> logger)
|
ILogger<PuzzleController> logger)
|
||||||
{
|
{
|
||||||
_catalog = catalog;
|
_catalog = catalog;
|
||||||
_clears = clears;
|
_clears = clears;
|
||||||
_evaluator = evaluator;
|
_evaluator = evaluator;
|
||||||
_rewards = rewards;
|
_inv = inv;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,28 +174,15 @@ public class PuzzleController : SVSimController
|
|||||||
|
|
||||||
if (fresh.Count > 0)
|
if (fresh.Count > 0)
|
||||||
{
|
{
|
||||||
// Load viewer with all the collections RewardGrantService might mutate. Split-query
|
await using var tx = await _inv.BeginAsync(viewerId);
|
||||||
// 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);
|
|
||||||
|
|
||||||
foreach (var status in fresh)
|
foreach (var status in fresh)
|
||||||
{
|
{
|
||||||
IReadOnlyList<GrantedReward> granted;
|
IReadOnlyList<SVSim.Database.Services.GrantedReward> granted;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
granted = await _rewards.ApplyAsync(
|
granted = await tx.GrantAsync(
|
||||||
viewer,
|
(UserGoodsType)status.Mission.RewardType,
|
||||||
(SVSim.Database.Enums.UserGoodsType)status.Mission.RewardType,
|
|
||||||
status.Mission.RewardDetailId,
|
status.Mission.RewardDetailId,
|
||||||
status.Mission.RewardNumber);
|
status.Mission.RewardNumber);
|
||||||
}
|
}
|
||||||
@@ -229,7 +215,7 @@ public class PuzzleController : SVSimController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await ctx.SaveChangesAsync();
|
await tx.CommitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
response.WinCount = "1";
|
response.WinCount = "1";
|
||||||
|
|||||||
Reference in New Issue
Block a user