using Indotalent.Infrastructure.Database; using MediatR; using Microsoft.EntityFrameworkCore; namespace Indotalent.Features.Sales.CreditNote.Cqrs; public class CreditNoteItemResponse { public string? Id { get; set; } public string? ProductId { get; set; } public string? ProductName { get; set; } public decimal UnitPrice { get; set; } public double Quantity { get; set; } public decimal Total { get; set; } } public class GetCreditNoteByIdResponse { public string? Id { get; set; } public string? AutoNumber { get; set; } public DateTime? CreditNoteDate { get; set; } public Data.Enums.CreditNoteStatus CreditNoteStatus { get; set; } public string? Description { get; set; } public string? SalesReturnId { get; set; } public string? SalesReturnNumber { get; set; } public string? CustomerName { get; set; } public string? CustomerStreet { get; set; } public string? CustomerCity { get; set; } public string? CompanyName { get; set; } public string? CompanyStreet { get; set; } public string? CompanyCity { get; set; } public string? CurrencySymbol { get; set; } public decimal BeforeTaxAmount { get; set; } public decimal TaxAmount { get; set; } public decimal AfterTaxAmount { get; set; } public DateTimeOffset? CreatedAt { get; set; } public string? CreatedBy { get; set; } public DateTimeOffset? UpdatedAt { get; set; } public string? UpdatedBy { get; set; } public List Items { get; set; } = new(); } public record GetCreditNoteByIdQuery(string Id) : IRequest; public class GetCreditNoteByIdHandler : IRequestHandler { private readonly AppDbContext _context; public GetCreditNoteByIdHandler(AppDbContext context) => _context = context; public async Task Handle(GetCreditNoteByIdQuery request, CancellationToken cancellationToken) { var company = await _context.Company .AsNoTracking() .Include(x => x.Currency) .OrderByDescending(x => x.IsDefault) .FirstOrDefaultAsync(cancellationToken); var creditNote = await _context.CreditNote .AsNoTracking() .Include(x => x.SalesReturn) .ThenInclude(sr => sr!.DeliveryOrder) .ThenInclude(do_ => do_!.SalesOrder) .ThenInclude(so => so!.Customer) .Include(x => x.SalesReturn) .ThenInclude(sr => sr!.DeliveryOrder) .ThenInclude(do_ => do_!.SalesOrder) .ThenInclude(so => so!.Tax) .FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken); if (creditNote == null) return null; var salesOrder = creditNote.SalesReturn?.DeliveryOrder?.SalesOrder; var taxRate = salesOrder?.Tax?.PercentageValue ?? 0; var transactions = await _context.InventoryTransaction .AsNoTracking() .Include(x => x.Product) .Where(x => x.ModuleId == creditNote.SalesReturnId && x.ModuleName == nameof(Data.Entities.SalesReturn)) .ToListAsync(cancellationToken); var items = new List(); decimal subTotal = 0; foreach (var trans in transactions) { var soItem = await _context.SalesOrderItem .AsNoTracking() .FirstOrDefaultAsync(x => x.SalesOrderId == salesOrder!.Id && x.ProductId == trans.ProductId, cancellationToken); var unitPrice = soItem?.UnitPrice ?? 0; var qty = Math.Abs(trans.Movement ?? 0); var total = unitPrice * (decimal)qty; items.Add(new CreditNoteItemResponse { Id = trans.Id, ProductId = trans.ProductId, ProductName = trans.Product?.Name, UnitPrice = unitPrice, Quantity = qty, Total = total }); subTotal += total; } var taxAmount = subTotal * (decimal)(taxRate / 100); return new GetCreditNoteByIdResponse { Id = creditNote.Id, AutoNumber = creditNote.AutoNumber, CreditNoteDate = creditNote.CreditNoteDate, CreditNoteStatus = creditNote.CreditNoteStatus, Description = creditNote.Description, SalesReturnId = creditNote.SalesReturnId, SalesReturnNumber = creditNote.SalesReturn?.AutoNumber, CustomerName = salesOrder?.Customer?.Name, CustomerStreet = salesOrder?.Customer?.Street, CustomerCity = salesOrder?.Customer?.City, CompanyName = company?.Name, CompanyStreet = company?.StreetAddress, CompanyCity = company?.City, CurrencySymbol = company?.Currency?.Symbol ?? "IDR", BeforeTaxAmount = subTotal, TaxAmount = taxAmount, AfterTaxAmount = subTotal + taxAmount, CreatedAt = creditNote.CreatedAt, CreatedBy = creditNote.CreatedBy, UpdatedAt = creditNote.UpdatedAt, UpdatedBy = creditNote.UpdatedBy, Items = items }; } }