feat(bp): /battle_pass/item_list — derives product per active season
Adds BattlePassSalesPeriodInfoDto, BattlePassProductDto, BattlePassItemListResponse DTOs, GetItemListAsync on BattlePassService (one product if not premium + CanPurchase, empty if already premium or off-season), and the /battle_pass/item_list controller action. 2 new integration tests; all 408 pass.
This commit is contained in:
@@ -94,6 +94,44 @@ public sealed class BattlePassService : IBattlePassService
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<BattlePassItemListResponse?> GetItemListAsync(long viewerId, CancellationToken ct)
|
||||
{
|
||||
var now = _time.GetUtcNow();
|
||||
var season = await _bp.GetActiveSeasonAsync(now, ct);
|
||||
if (season is null) return null;
|
||||
|
||||
var progress = await _viewerBp.GetOrCreateProgressAsync(viewerId, season.Id, ct);
|
||||
|
||||
var response = new BattlePassItemListResponse
|
||||
{
|
||||
PremiumPassDescription = season.Description,
|
||||
SalesPeriodInfo = new BattlePassSalesPeriodInfoDto
|
||||
{
|
||||
SalesPeriodTime = FormatWireDate(season.EndDate),
|
||||
},
|
||||
Products = new List<BattlePassProductDto>(),
|
||||
};
|
||||
|
||||
// One product per active season; empty if viewer is already premium.
|
||||
if (!progress.IsPremium && season.CanPurchase)
|
||||
{
|
||||
response.Products.Add(new BattlePassProductDto
|
||||
{
|
||||
Id = season.Id * 1000,
|
||||
SeasonId = season.Id,
|
||||
Name = $"{season.Name} Premium Pass",
|
||||
PriceCrystal = season.PriceCrystal,
|
||||
Description = season.Description,
|
||||
SalesPeriodInfo = new BattlePassSalesPeriodInfoDto
|
||||
{
|
||||
SalesPeriodTime = FormatWireDate(season.EndDate),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
internal static int ComputeLevel(IReadOnlyList<BattlePassLevelEntry> curve, int point)
|
||||
{
|
||||
if (curve.Count == 0) return 1;
|
||||
|
||||
Reference in New Issue
Block a user