| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- using Application.Abstractions.Cache;
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Application.Features.Config.Get;
- using Domain.Entities.Members.ValueObject;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Rewards.GetToday;
- internal sealed class Handler(IAppDbContext db, ICacheService cache) : IQueryHandler<Query, Response>
- {
- private static readonly TimeZoneInfo KstZone = ResolveKst();
- public async Task<Response> Handle(Query request, CancellationToken ct)
- {
- var today = DateOnly.FromDateTime(TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, KstZone));
- var counters = await db.MemberDailyRewardCounter.AsNoTracking()
- .Where(c => c.MemberID == request.MemberID && c.RewardDate == today)
- .ToListAsync(ct);
- var config = await LoadConfigAsync(ct);
- var actions = new List<ActionSummary>
- {
- BuildSummary(counters, RewardActionType.Post, "게시글", config?.PostDailyCount ?? 0, config?.PostDailyExp ?? 0, config?.PostDailyPoint ?? 0),
- BuildSummary(counters, RewardActionType.Comment, "댓글", config?.CommentDailyCount ?? 0, config?.CommentDailyExp ?? 0, config?.CommentDailyPoint ?? 0),
- BuildSummary(counters, RewardActionType.LikeGiven, "추천(누름)", config?.LikeGivenDailyCount ?? 0, config?.LikeGivenDailyExp ?? 0, 0),
- BuildSummary(counters, RewardActionType.LikeReceived, "추천(받음)", config?.LikeReceivedDailyCount ?? 0, 0, config?.LikeReceivedDailyPoint ?? 0),
- BuildSummary(counters, RewardActionType.Chat, "채팅", config?.ChatDailyCount ?? 0, config?.ChatDailyExp ?? 0, 0)
- };
- var totalExp = counters.Sum(c => c.ExpTotal);
- var totalPoint = counters.Sum(c => c.PointTotal);
- return new Response(today.ToString("yyyy-MM-dd"), totalExp, totalPoint, actions);
- }
- private static ActionSummary BuildSummary(
- List<Domain.Entities.Members.MemberDailyRewardCounter> counters,
- RewardActionType action,
- string name,
- int countCap,
- int expCap,
- int pointCap)
- {
- var c = counters.FirstOrDefault(x => x.ActionType == action);
- var count = c?.Count ?? 0;
- var exp = c?.ExpTotal ?? 0;
- var point = c?.PointTotal ?? 0;
- return new ActionSummary(
- (byte)action,
- name,
- count,
- exp,
- point,
- countCap > 0 ? Math.Max(0, countCap - count) : null,
- expCap > 0 ? Math.Max(0, expCap - exp) : null,
- pointCap > 0 ? Math.Max(0, pointCap - point) : null
- );
- }
- private async Task<Response.RewardConfigView?> LoadConfigAsync(CancellationToken ct)
- {
- var cached = await cache.GetAsync<Features.Config.Get.Response>(CacheKeys.Config, ct);
- if (cached is not null)
- {
- var r = cached.Reward;
- return new Response.RewardConfigView(
- r.PostDailyCount, r.PostDailyExp, r.PostDailyPoint,
- r.CommentDailyCount, r.CommentDailyExp, r.CommentDailyPoint,
- r.LikeGivenDailyCount, r.LikeGivenDailyExp,
- r.LikeReceivedDailyCount, r.LikeReceivedDailyPoint,
- r.ChatDailyCount, r.ChatDailyExp);
- }
- var entity = await db.Config.AsNoTracking().OrderByDescending(c => c.ID).Select(c => c.Reward).FirstOrDefaultAsync(ct);
- if (entity is null)
- {
- return null;
- }
- return new Response.RewardConfigView(
- entity.PostDailyCount, entity.PostDailyExp, entity.PostDailyPoint,
- entity.CommentDailyCount, entity.CommentDailyExp, entity.CommentDailyPoint,
- entity.LikeGivenDailyCount, entity.LikeGivenDailyExp,
- entity.LikeReceivedDailyCount, entity.LikeReceivedDailyPoint,
- entity.ChatDailyCount, entity.ChatDailyExp);
- }
- private static TimeZoneInfo ResolveKst()
- {
- if (TimeZoneInfo.TryFindSystemTimeZoneById("Asia/Seoul", out var tz))
- {
- return tz;
- }
- if (TimeZoneInfo.TryFindSystemTimeZoneById("Korea Standard Time", out tz))
- {
- return tz;
- }
- return TimeZoneInfo.CreateCustomTimeZone("KST", TimeSpan.FromHours(9), "KST", "KST");
- }
- }
|