| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Domain.Entities.Store.ValueObject;
- using Microsoft.EntityFrameworkCore;
- using SharedKernel.Helpers;
- using SharedKernel.Results;
- namespace Application.Features.Admin.Store.Coupon.ExportCodes;
- /// <summary>
- /// CSV 양식 (DB 컬럼명 기준):
- /// ID, Code, Status, IssuedToMemberID, IssuedToMemberName, IssuedToMemberEmail, IssuedAt, UsedAt, CreatedAt
- ///
- /// Status 인코딩 (사용자 결정 — Option A):
- /// 0 = Available (미배포)
- /// 1 = Reserved/Issued/Used (배포된 상태로 묶음)
- ///
- /// 일시는 KST 로 출력 (UTC → Local 변환).
- /// </summary>
- public sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
- {
- private static readonly string[] Header =
- [
- "ID",
- "Code",
- "Status",
- "IssuedToMemberID",
- "IssuedToMemberName",
- "IssuedToMemberEmail",
- "IssuedAt",
- "UsedAt",
- "CreatedAt"
- ];
- public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
- {
- var coupon = await db.Coupon.AsNoTracking()
- .Where(c => c.ID == request.CouponID)
- .Select(c => new { c.ID, c.Name })
- .FirstOrDefaultAsync(ct);
- if (coupon is null)
- {
- return Result.Failure<Response>(Error.NotFound("Coupon.NotFound", "쿠폰을 찾을 수 없습니다."));
- }
- var rows = await db.CouponCode.AsNoTracking()
- .Include(c => c.IssuedToMember)
- .Where(c => c.CouponID == request.CouponID)
- .OrderBy(c => c.ID)
- .Select(c => new
- {
- c.ID,
- c.Code,
- c.Status,
- c.IssuedToMemberID,
- Name = c.IssuedToMember != null ? c.IssuedToMember.Name : null,
- Email = c.IssuedToMember != null ? c.IssuedToMember.Email : null,
- c.IssuedAt,
- c.UsedAt,
- c.CreatedAt
- })
- .ToListAsync(ct);
- var csvRows = new List<string[]> { Header };
- foreach (var r in rows)
- {
- var status = r.Status == CouponCodeStatus.Available ? "0" : "1";
- var memberID = r.IssuedToMemberID?.ToString() ?? "";
- var name = r.Name ?? "";
- var email = r.Email ?? "";
- var issuedAt = r.IssuedAt.HasValue
- ? DateTime.SpecifyKind(r.IssuedAt.Value, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")
- : "";
- var usedAt = r.UsedAt.HasValue
- ? DateTime.SpecifyKind(r.UsedAt.Value, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")
- : "";
- var createdAt = DateTime.SpecifyKind(r.CreatedAt, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
- csvRows.Add([
- r.ID.ToString(),
- r.Code,
- status,
- memberID,
- name,
- email,
- issuedAt,
- usedAt,
- createdAt
- ]);
- }
- var bytes = CsvHelper.WriteUtf8Bom(csvRows);
- var fileName = $"coupon-codes-{request.CouponID}-{DateTime.Now:yyyyMMdd-HHmmss}.csv";
- return Result.Success(new Response(bytes, fileName));
- }
- }
|