85 lines
3.0 KiB
C#
85 lines
3.0 KiB
C#
using Distribution.Features.Sale;
|
|
using Distribution.Features.Stock;
|
|
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<PagedResponse<PaymentResponse>> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize)
|
|
{
|
|
var total = await repo.GetCountAsync(storeId, saleId);
|
|
var items = await repo.GetAllAsync(storeId, saleId, page, pageSize);
|
|
return new PagedResponse<PaymentResponse>(page, pageSize, total, items.Select(ToResponse).ToList());
|
|
}
|
|
|
|
public async Task<PaymentResponse?> GetByIdAsync(Guid id)
|
|
{
|
|
var payment = await repo.GetByIdAsync(id);
|
|
return payment is null ? null : ToResponse(payment);
|
|
}
|
|
|
|
public async Task<List<PaymentResponse>?> 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<PaymentResponse?> 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");
|
|
|
|
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
|
|
// (testbug.md #28) — fall back to the explicitly supplied user until that's fixed.
|
|
var userId = currentUser.UserId ?? request.CollectedByUserId
|
|
?? throw new InvalidOperationException("CollectedByUserId is required while auth is unavailable");
|
|
|
|
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);
|
|
}
|
|
}
|