using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Store.ValueObject; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Admin.Store.Coupon.Delete; public sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { if (request.IDs is null || request.IDs.Length == 0) { return Result.Failure(Error.Problem("Coupon.NoIDs", "삭제할 쿠폰을 선택해 주세요.")); } // 발급(Issued)/사용(Used) 코드가 있으면 삭제 거부 var issuedCodeCoupons = await db.CouponCode .Where(c => request.IDs.Contains(c.CouponID) && (c.Status == CouponCodeStatus.Issued || c.Status == CouponCodeStatus.Used)) .Select(c => c.CouponID) .Distinct() .ToListAsync(ct); if (issuedCodeCoupons.Count > 0) { return Result.Failure(Error.Conflict("Coupon.InUse", $"이미 발급되거나 사용된 코드가 있는 쿠폰은 삭제할 수 없습니다. (쿠폰 ID: {string.Join(", ", issuedCodeCoupons)})")); } var coupons = await db.Coupon.Where(c => request.IDs.Contains(c.ID)).ToListAsync(ct); if (coupons.Count == 0) { return Result.Failure(Error.NotFound("Coupon.NotFound", "삭제할 쿠폰을 찾을 수 없습니다.")); } // CouponCode 는 CASCADE 로 자동 삭제됨 (EF Configuration 에서 DeleteBehavior.Cascade) db.Coupon.RemoveRange(coupons); await db.SaveChangesAsync(ct); return Result.Success(); } }