using Domain.Dtos.Sales; using Domain.Entities; using Domain.Generics; using Microsoft.EntityFrameworkCore; using Models.Helpers; using Models.Interfaces; using Models.Models; namespace Models.Repositories { public class PhSSalesDocumentRepository(PhronCareOperationsHubContext context) : IPhSSalesDocumentRepository { private readonly PhronCareOperationsHubContext _context = context; public async Task> SearchAsync( int? customerId, string? customerText, int? quoteId, int? documentType, int? status, DateTime? issueDateFrom, DateTime? issueDateTo, int page = 1, int pageSize = 50) { page = page <= 0 ? 1 : page; pageSize = pageSize <= 0 ? 50 : pageSize; var query = _context.PhSSalesDocuments .Include(x => x.Customer) .Include(x => x.BillToCustomer) .AsNoTracking() .AsQueryable(); if (customerId.HasValue && customerId.Value > 0) { query = query.Where(x => x.CustomerId == customerId.Value || x.BillToCustomerId == customerId.Value); } if (!string.IsNullOrWhiteSpace(customerText)) { var normalizedCustomerText = customerText.Trim(); query = query.Where(x => (x.Customer.Name ?? string.Empty).Contains(normalizedCustomerText) || (x.BillToCustomer.Name ?? string.Empty).Contains(normalizedCustomerText)); } if (quoteId.HasValue && quoteId.Value > 0) { query = query.Where(x => x.QuoteId == quoteId.Value); } if (documentType.HasValue && documentType.Value > 0) { query = query.Where(x => x.DocumentType == documentType.Value); } if (status.HasValue && status.Value > 0) { query = query.Where(x => x.Status == status.Value); } if (issueDateFrom.HasValue) { query = query.Where(x => x.IssueDate >= issueDateFrom.Value); } if (issueDateTo.HasValue) { query = query.Where(x => x.IssueDate <= issueDateTo.Value); } var totalItems = await query.CountAsync(); var items = await query .OrderByDescending(x => x.IssueDate) .ThenByDescending(x => x.Id) .Skip((page - 1) * pageSize) .Take(pageSize) .Select(x => new SalesDocumentSummaryDto { Id = x.Id, InternalDocumentNumber = x.InternalDocumentNumber, DocumentType = x.DocumentType, Status = x.Status, QuoteId = x.QuoteId, CustomerId = x.CustomerId, CustomerName = x.Customer.Name ?? string.Empty, BillToCustomerId = x.BillToCustomerId, BillToCustomerName = x.BillToCustomer.Name ?? string.Empty, IssueDate = x.IssueDate, Currency = x.Currency, NetAmount = x.NetAmount, TaxAmount = x.TaxAmount, TotalAmount = x.TotalAmount, PeriodFrom = x.PeriodFrom, PeriodTo = x.PeriodTo, Createdat = x.Createdat, Modifiedat = x.Modifiedat }) .ToListAsync(); return new PagedResult { Items = items, TotalItems = totalItems, Page = page, PageSize = pageSize }; } public async Task CreateAsync(ESalesDocument entity) { var mapped = EntityMapper.MapEntity(entity); await _context.PhSSalesDocuments.AddAsync(mapped); await _context.SaveChangesAsync(); return EntityMapper.MapEntity(mapped); } public async Task> SearchDeliveryNoteCandidatesAsync( int? customerId, string? customerText, string? deliveryNoteNumber, int? quoteId, DateTime? issueDateFrom, DateTime? issueDateTo, int page = 1, int pageSize = 50) { page = page <= 0 ? 1 : page; pageSize = pageSize <= 0 ? 50 : pageSize; var query = _context.PhSDeliveryNotes .Include(x => x.Customer) .Include(x => x.Quote) .Include(x => x.PhSDeliveryNoteDetails) .ThenInclude(d => d.QuoteDetail) .AsNoTracking() .Where(x => x.Status == "Emitido" && x.SalesinvoiceId == null) .AsQueryable(); if (customerId.HasValue && customerId.Value > 0) query = query.Where(x => x.CustomerId == customerId.Value); else if (!string.IsNullOrWhiteSpace(customerText)) query = query.Where(x => (x.Customer.Name ?? string.Empty).Contains(customerText.Trim())); if (!string.IsNullOrWhiteSpace(deliveryNoteNumber)) query = query.Where(x => x.Deliverynotenumber.Contains(deliveryNoteNumber.Trim())); if (quoteId.HasValue && quoteId.Value > 0) query = query.Where(x => x.QuoteId == quoteId.Value); if (issueDateFrom.HasValue) query = query.Where(x => x.Issuedate >= issueDateFrom.Value); if (issueDateTo.HasValue) query = query.Where(x => x.Issuedate <= issueDateTo.Value); var totalItems = await query.CountAsync(); var items = await query .OrderByDescending(x => x.Issuedate) .ThenByDescending(x => x.Id) .Skip((page - 1) * pageSize) .Take(pageSize) .Select(x => new SalesDocumentDeliveryNoteCandidateDto { Id = x.Id, DeliveryNoteNumber = x.Deliverynotenumber, QuoteId = x.QuoteId, QuoteNumber = x.Quote != null ? x.Quote.Quotenumber : null, IssueDate = x.Issuedate, CustomerId = x.CustomerId, CustomerName = x.Customer.Name ?? string.Empty, Status = x.Status, ItemCount = x.PhSDeliveryNoteDetails.Count, ApprovedAmount = x.PhSDeliveryNoteDetails.Sum(d => d.QuoteDetail != null ? (d.QuoteDetail.Approvedamount ?? ((d.QuoteDetail.Approvedunitprice ?? d.QuoteDetail.Unitprice) * d.Quantity)) : 0), ExtraInfoJson = x.ExtrainfoJson }) .ToListAsync(); return new PagedResult { Items = items, TotalItems = totalItems, Page = page, PageSize = pageSize }; } public async Task> GetDeliveryNotesForSalesDocumentAsync(IReadOnlyCollection deliveryNoteIds) { var ids = deliveryNoteIds.Distinct().ToList(); var entities = await _context.PhSDeliveryNotes .Include(x => x.Customer) .Include(x => x.Quote) .Include(x => x.PhSDeliveryNoteDetails) .ThenInclude(d => d.QuoteDetail) .AsNoTracking() .Where(x => ids.Contains(x.Id)) .OrderBy(x => x.Issuedate) .ThenBy(x => x.Id) .ToListAsync(); return entities.Select(MapDeliveryNoteDto).ToList(); } public async Task CreateFromDeliveryNotesAsync(ESalesDocument entity, IReadOnlyCollection deliveryNoteIds) { await using var transaction = await _context.Database.BeginTransactionAsync(); var mapped = EntityMapper.MapEntity(entity); await _context.PhSSalesDocuments.AddAsync(mapped); await _context.SaveChangesAsync(); var ids = deliveryNoteIds.Distinct().ToList(); var deliveryNotes = await _context.PhSDeliveryNotes .Where(x => ids.Contains(x.Id)) .ToListAsync(); foreach (var deliveryNote in deliveryNotes) { deliveryNote.SalesinvoiceId = mapped.Id; deliveryNote.Modifiedat = DateTime.Now; } await _context.SaveChangesAsync(); await transaction.CommitAsync(); return EntityMapper.MapEntity(mapped); } private static DeliveryNoteDto MapDeliveryNoteDto(PhSDeliveryNote source) { return new DeliveryNoteDto { Id = source.Id, DeliveryNoteNumber = source.Deliverynotenumber, CustomerName = source.Customer?.Name ?? string.Empty, QuoteId = source.QuoteId, QuoteNumber = source.Quote?.Quotenumber, SalesInvoiceId = source.SalesinvoiceId, IssueDate = source.Issuedate, CustomerId = source.CustomerId, Status = source.Status, Observations = source.Observations, ExtraInfoJson = source.ExtrainfoJson, PrintCount = source.Printcount, CreatedAt = source.Createdat, ModifiedAt = source.Modifiedat, Items = source.PhSDeliveryNoteDetails .OrderBy(d => d.LineNumber) .ThenBy(d => d.Id) .Select(d => new DeliveryNoteItemDto { Id = d.Id, DeliverynoteId = d.DeliverynoteId, LineNumber = d.LineNumber, OriginType = d.OriginType, OriginId = d.OriginId, QuoteDetailId = d.QuoteDetailId, Description = d.Description ?? string.Empty, Quantity = d.Quantity, ProductId = d.QuoteDetail?.ProductId, ApprovedUnitPrice = d.QuoteDetail?.Approvedunitprice, ApprovedAmount = d.QuoteDetail?.Approvedamount, OriginalUnitPrice = d.QuoteDetail?.Unitprice, Notes = d.Notes, Createdat = d.Createdat, Modifiedat = d.Modifiedat }) .ToList() }; } public async Task GetDtoByIdAsync(int id) { var entity = await _context.PhSSalesDocuments .Include(x => x.Customer) .Include(x => x.BillToCustomer) .Include(x => x.PhSSalesDocumentDetails) .Include(x => x.PhSSalesDocumentCoverages) .AsNoTracking() .FirstOrDefaultAsync(x => x.Id == id); if (entity == null) return null; return new SalesDocumentDto { Id = entity.Id, FormseriesId = entity.FormseriesId, InternalSequenceNumber = entity.InternalSequenceNumber, InternalDocumentNumber = entity.InternalDocumentNumber, DocumentType = entity.DocumentType, FiscalVoucherType = entity.FiscalVoucherType, FiscalVoucherLetter = entity.FiscalVoucherLetter, Status = entity.Status, QuoteId = entity.QuoteId, CustomerId = entity.CustomerId, CustomerName = entity.Customer?.Name ?? string.Empty, BillToCustomerId = entity.BillToCustomerId, BillToCustomerName = entity.BillToCustomer?.Name ?? string.Empty, IssueDate = entity.IssueDate, Currency = entity.Currency, ExchangeRate = entity.ExchangeRate, NetAmount = entity.NetAmount, TaxAmount = entity.TaxAmount, TotalAmount = entity.TotalAmount, Observations = entity.Observations, ExtraInfoJson = entity.ExtraInfoJson, PeriodFrom = entity.PeriodFrom, PeriodTo = entity.PeriodTo, Createdat = entity.Createdat, Modifiedat = entity.Modifiedat, Details = entity.PhSSalesDocumentDetails.Select(x => new SalesDocumentDetailDto { Id = x.Id, SalesDocumentId = x.SalesdocumentId, LineNumber = x.LineNumber, OriginType = x.OriginType, OriginId = x.OriginId, QuoteDetailId = x.QuoteDetailId, ProductId = x.ProductId, Description = x.Description, Quantity = x.Quantity, AuthorizedUnitPrice = x.AuthorizedUnitPrice, AuthorizedAmount = x.AuthorizedAmount, BilledPercentage = x.BilledPercentage, UnitPrice = x.UnitPrice, NetAmount = x.NetAmount, TaxAmount = x.TaxAmount, TotalAmount = x.TotalAmount, OriginSnapshotJson = x.OriginSnapshotJson, Createdat = x.Createdat, Modifiedat = x.Modifiedat }).ToList(), Coverage = entity.PhSSalesDocumentCoverages.Select(x => new SalesDocumentCoverageDto { Id = x.Id, SalesDocumentId = x.SalesdocumentId, SalesDocumentDetailId = x.SalesdocumentdetailId, QuoteId = x.QuoteId, QuoteDetailId = x.QuoteDetailId, CoverageType = x.CoverageType, CoveragePercentage = x.CoveragePercentage, CoverageAmount = x.CoverageAmount, PeriodFrom = x.PeriodFrom, PeriodTo = x.PeriodTo, Notes = x.Notes, Createdat = x.Createdat, Modifiedat = x.Modifiedat }).ToList() }; } } }