using Distribution.Features.Sale; using Distribution.Infra.Authorization; using Distribution.Infra.UoW; using Distribution.Models; namespace Distribution.Features.Payment; public class PaymentService( IPaymentRepository repo, ISaleRepository saleRepo, IUnitOfWork uow, ICurrentUserService currentUser) { private static PaymentResponse ToResponse(Models.Payment p) => new(p.Id, p.FK_SaleId, p.FK_StoreId, p.Amount, p.Method, p.CollectedAt, p.CollectedBy, p.CreatedAt); public async Task?> GetBySaleIdAsync(Guid saleId) { var sale = await saleRepo.GetByIdAsync(saleId); if (sale is null || !sale.IsActive) return null; var payments = await repo.GetBySaleIdAsync(saleId); return payments.Select(ToResponse).ToList(); } public async Task CreateAsync(Guid saleId, CreatePaymentRequest request, CancellationToken ct = default) { var sale = await saleRepo.GetByIdAsync(saleId); if (sale is null || !sale.IsActive) return null; if (sale.Status == SaleStatus.Cancelled) throw new InvalidOperationException("Cannot record a payment against a cancelled sale"); var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); var payment = new Models.Payment { FK_SaleId = saleId, FK_StoreId = sale.FK_StoreId, Amount = request.Amount, Method = request.Method, CollectedAt = DateTime.Now, CollectedBy = userId }; await uow.BeginAsync(ct); try { await repo.AddAsync(payment); var allPayments = await repo.GetBySaleIdAsync(saleId); var total = allPayments.Sum(p => p.Amount) + request.Amount; sale.PaymentStatus = total == 0 ? PaymentStatus.Pending : total < sale.TotalAmount ? PaymentStatus.PartiallyPaid : PaymentStatus.Paid; saleRepo.Update(sale); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return ToResponse(payment); } }