| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Domain.Entities.Members.Logs;
- using Domain.Entities.Members.ValueObject;
- using Domain.Entities.Store.ValueObject;
- using Microsoft.EntityFrameworkCore;
- using SharedKernel.Results;
- namespace Application.Features.Api.Member.Items.Use;
- internal sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result<Response>>
- {
- public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
- {
- var now = DateTime.UtcNow;
- var item = await db.MemberItem.FirstOrDefaultAsync(i => i.ID == request.MemberItemID, ct);
- if (item is null || item.MemberID != request.MemberID)
- {
- return Result.Failure<Response>(Error.NotFound("MemberItem.NotFound", "보유 아이템을 찾을 수 없습니다."));
- }
- if (!item.IsAvailable)
- {
- return Result.Failure<Response>(Error.Conflict("MemberItem.Unavailable", "이미 사용했거나 회수된 아이템입니다."));
- }
- string detail;
- switch (item.Kind)
- {
- case ItemKind.ChatBanLift:
- {
- var bans = await db.ChatBan
- .Where(b => b.MemberID == request.MemberID && (b.ExpiresAt == null || b.ExpiresAt > now))
- .ToListAsync(ct);
- if (bans.Count == 0)
- {
- return Result.Failure<Response>(Error.Problem("MemberItem.NoActiveBan", "해제할 채팅 제재가 없습니다."));
- }
- foreach (var ban in bans)
- {
- ban.Lift(now);
- }
- detail = $"채팅 제재 {bans.Count}건 해제";
- break;
- }
- case ItemKind.PostReset:
- {
- var affected = await db.Post
- .Where(p => p.MemberID == request.MemberID && !p.IsDeleted && p.Reports == 0 && p.Comments == 0)
- .ExecuteUpdateAsync(s => s
- .SetProperty(p => p.IsDeleted, true)
- .SetProperty(p => p.DeletedAt, now), ct);
- if (affected == 0)
- {
- return Result.Failure<Response>(Error.Problem("MemberItem.NoResettablePost", "초기화할 글이 없습니다. (신고·댓글 없는 본인 글만 대상)"));
- }
- detail = $"예전 글 {affected}건 초기화";
- break;
- }
- case ItemKind.ExpBooster:
- {
- detail = $"경험치 부스터 {item.DurationDays}일 활성화";
- break;
- }
- default:
- return Result.Failure<Response>(Error.Problem("MemberItem.NotDirectlyUsable",
- "이 아이템은 해당 기능(쪽지 보내기·프로필 변경) 이용 시 자동으로 사용됩니다."));
- }
- item.MarkUsed(now);
- db.MemberItemUsageLog.Add(MemberItemUsageLog.Create(item.MemberID, item.ID, item.ProductID, item.Kind, MemberItemUsageAction.Used, detail));
- await db.SaveChangesAsync(ct);
- return Result.Success(new Response(item.Kind, detail));
- }
- }
|