using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Store.ValueObject; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Admin.Store.Shipment.UpdateStatus; public sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { var shipment = await db.Shipment .Include(s => s.Order) .FirstOrDefaultAsync(s => s.ID == request.ShipmentID, ct); if (shipment is null) { return Result.Failure(Error.NotFound("Shipment.NotFound", "배송 정보를 찾을 수 없습니다.")); } try { switch (request.Action) { case "RegisterTracking": if (string.IsNullOrWhiteSpace(request.Carrier) || string.IsNullOrWhiteSpace(request.TrackingNumber)) { return Result.Failure(Error.Problem("Shipment.TrackingRequired", "택배사와 송장번호를 모두 입력해주세요.")); } shipment.RegisterTracking(request.Carrier, request.TrackingNumber); if (shipment.Order is not null && shipment.Order.Status == OrderStatus.Paid) { shipment.Order.MarkPreparing(); } break; case "InTransit": shipment.MarkInTransit(); if (shipment.Order is not null && shipment.Order.Status is OrderStatus.Paid or OrderStatus.Preparing) { shipment.Order.MarkShipped(); } break; case "Delivered": shipment.MarkDelivered(); if (shipment.Order is not null && shipment.Order.Status is OrderStatus.Paid or OrderStatus.Preparing or OrderStatus.Shipped) { shipment.Order.MarkDelivered(); } break; case "Failed": shipment.MarkFailed(); break; case "UpdateBilling": if (request.ShippingFee is null) { return Result.Failure(Error.Problem("Shipment.ShippingFeeRequired", "배송비를 입력해주세요.")); } if (request.ShippingFee < 0) { return Result.Failure(Error.Problem("Shipment.ShippingFeeNegative", "배송비는 0 이상이어야 합니다.")); } if (request.AdminMemo is { Length: > 500 }) { return Result.Failure(Error.Problem("Shipment.AdminMemoTooLong", "관리자 메모는 500자 이하여야 합니다.")); } shipment.UpdateBillingInfo(request.ShippingFee.Value, request.AdminMemo); break; default: return Result.Failure(Error.Problem("Shipment.UnknownAction", $"알 수 없는 액션: {request.Action}")); } } catch (InvalidOperationException ex) { return Result.Failure(Error.Problem("Shipment.InvalidTransition", ex.Message)); } await db.SaveChangesAsync(ct); return Result.Success(); } }