feat(pack): /pack/exchange_gacha_point endpoint
Wires IGachaPointService.TryExchangeAsync into a controller endpoint. Loads the viewer with the full cosmetic-grant graph (Cards, Sleeves, Emblems, Degrees, LeaderSkins, MyPageBackgrounds) plus the gacha-point balance + received marker, with AsSplitQuery to avoid the cartesian explosion documented in project_ef_split_query. Returns BadRequest with the outcome's error code on validation failure, or the post-state reward_list on success. Two integration tests: happy-path verifies card grant + balance debit + received-marker persistence + post-state reward_list shape; insufficient- balance path returns 400. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -163,6 +163,37 @@ public class PackController : SVSimController
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("exchange_gacha_point")]
|
||||
public async Task<ActionResult<ExchangeGachaPointResponse>> ExchangeGachaPoint(
|
||||
ExchangeGachaPointRequest request)
|
||||
{
|
||||
if (!TryGetViewerId(out long viewerId)) return Unauthorized();
|
||||
|
||||
// Load the viewer with the collections the service mutates (balances, received marker,
|
||||
// cards, cosmetics). AsSplitQuery per project_ef_split_query memory.
|
||||
var viewer = await _db.Viewers
|
||||
.Include(v => v.GachaPointBalances)
|
||||
.Include(v => v.GachaPointReceived)
|
||||
.Include(v => v.Cards)
|
||||
.Include(v => v.Sleeves)
|
||||
.Include(v => v.Emblems)
|
||||
.Include(v => v.Degrees)
|
||||
.Include(v => v.LeaderSkins)
|
||||
.Include(v => v.MyPageBackgrounds)
|
||||
.AsSplitQuery()
|
||||
.FirstAsync(v => v.Id == viewerId);
|
||||
|
||||
var outcome = await _gachaPoint.TryExchangeAsync(viewer, request.ParentGachaId, request.CardId);
|
||||
if (!outcome.Success) return BadRequest(new { error = outcome.Error });
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
return new ExchangeGachaPointResponse
|
||||
{
|
||||
RewardList = outcome.RewardList.ToList(),
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("open")]
|
||||
[HttpPost("/tutorial/pack_open")]
|
||||
public async Task<ActionResult<PackOpenResponse>> Open(PackOpenRequest request)
|
||||
|
||||
Reference in New Issue
Block a user