using Domain.Entities; using Domain.Generics; using Models.Interfaces; using System.Reflection; using Transversal.Services; namespace PhronCare.Core.Services.Sales { public class QuoteService( IPhSQuoteHeaderRepository quoteHeaderRepository, IPhSQuoteDetailRepository quoteDetailRepository, IPhSQuoteRoleRepository quoteRoleRepository, IPhSFormSeriesRepository formSeriesRepository ) : IQuoteDom { #region Declaraciones private readonly IPhSQuoteHeaderRepository _quoteHeaderRepository = quoteHeaderRepository; private readonly IPhSQuoteDetailRepository _quoteDetailRepository = quoteDetailRepository; private readonly IPhSQuoteRoleRepository _quoteRoleRepository = quoteRoleRepository; private readonly IPhSFormSeriesRepository _formSeriesRepository = formSeriesRepository; #endregion #region Métodos public async Task> GetAllQuotesAsync(int page = 1, int pageSize = 50) { return await _quoteHeaderRepository.GetAllAsync(page, pageSize); } public async Task GetQuoteByIdAsync(int id) { return await _quoteHeaderRepository.GetByIdAsync(id); } public async Task> GetQuotesByCustomerAsync(int customerId) { var quotes = await _quoteHeaderRepository.GetByCustomerIdAsync(customerId); return quotes; } public async Task> SearchQuotesAsync(int? customerId, string? quoteNumber, int? professionalId, int? institutionId, int? patientId, DateTime? issueDateFrom, DateTime? issueDateTo, string? status, int page = 1, int pageSize = 50) { return await _quoteHeaderRepository.SearchAsync(customerId, quoteNumber, professionalId, institutionId, patientId, issueDateFrom, issueDateTo, status, page, pageSize); } public async Task CreateQuoteAsync(EQuoteHeader quote, int formSeriesId) { // Obtener el próximo número de documento var nextNumber = await _formSeriesRepository.GetNextInternalNumberAsync(formSeriesId); // Asignar el número al presupuesto quote.Quotenumber = nextNumber.ToString(); // Crear el presupuesto var newQuote = await _quoteHeaderRepository.AddAsync(quote); // Crear los detalles asociados if (quote.Details != null) { foreach (var detail in quote.Details) { detail.QuoteheaderId = newQuote.Id; await _quoteDetailRepository.AddAsync(detail); } } // Crear los roles asociados if (quote.Roles != null) { foreach (var role in quote.Roles) { role.QuoteheaderId = newQuote.Id; await _quoteRoleRepository.AddAsync(role); } } return newQuote; } public async Task UpdateQuoteAsync(EQuoteHeader quote) { await _quoteHeaderRepository.UpdateAsync(quote); } public async Task DeleteQuoteAsync(int id) { await _quoteHeaderRepository.DeleteAsync(id); } public async Task ExportFilteredQuotesToExcelAsync(QuoteSearchParams searchParams) { try { // Buscar los presupuestos con los filtros indicados var searchResult = await SearchQuotesAsync( searchParams.CustomerId, searchParams.QuoteNumber, searchParams.ProfessionalId, searchParams.InstitutionId, searchParams.PatientId, searchParams.IssueDateFrom, searchParams.IssueDateTo, searchParams.Status, searchParams.Page, searchParams.PageSize ); // Verificar si hay resultados if (searchResult?.Items == null || !searchResult.Items.Any()) { throw new Exception("No se encontraron presupuestos para exportar."); } // Instanciar exportador var stream = new XLSXExportBase(); // Armar los datos a exportar var quotesData = searchResult.Items.Select(q => new { NúmeroPresupuesto = q.Quotenumber, Estado = q.Status, FechaEmisión = q.Issuedate.ToString("yyyy-MM-dd"), FechaTentativa = q.Estimateddate?.ToString("yyyy-MM-dd"), ImporteEstimado = q.Estimatedamount, ImporteAprobado = q.Approvedamount, Profesional = q.Roles.FirstOrDefault(r => r.Entitytype == "PhS_Professionals")?.Entitytype, Institución = q.Roles.FirstOrDefault(r => r.Entitytype == "PhS_Institutions")?.Entitytype, Paciente = q.Roles.FirstOrDefault(r => r.Entitytype == "PhS_Patients")?.Entitytype }).ToList(); // Generar archivo Excel var excelFile = stream.ExportExcel(quotesData); return excelFile; } catch (Exception ex) { var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; throw new Exception($"{methodName} Message: {ex.Message}", ex); } } #endregion } }