using Core.Interfaces; using Domain.Dtos.Sales; using Domain.Entities; using Domain.Generics; using Models.Interfaces; namespace Core.Services { public class DeliveryNoteService(IPhSDeliveryNoteRepository deliveryNoteRepository) : IDeliveryNoteDom { private readonly IPhSDeliveryNoteRepository _deliveryNoteRepository = deliveryNoteRepository; public Task> SearchAsync( int? customerId, string? customerText, string? deliveryNoteNumber, int? quoteId, string? quoteNumber, DateTime? issueDateFrom, DateTime? issueDateTo, string? status, int page = 1, int pageSize = 50) { page = page <= 0 ? 1 : page; pageSize = pageSize <= 0 ? 50 : pageSize; return _deliveryNoteRepository.SearchAsync( customerId, string.IsNullOrWhiteSpace(customerText) ? null : customerText.Trim(), string.IsNullOrWhiteSpace(deliveryNoteNumber) ? null : deliveryNoteNumber.Trim(), quoteId, string.IsNullOrWhiteSpace(quoteNumber) ? null : quoteNumber.Trim(), issueDateFrom, issueDateTo, string.IsNullOrWhiteSpace(status) ? null : status.Trim(), page, pageSize); } public Task GetDtoByIdAsync(int id) { if (id <= 0) throw new ArgumentOutOfRangeException(nameof(id), "El identificador del remito es inválido."); return _deliveryNoteRepository.GetDtoByIdAsync(id); } public Task GetDtoByDeliveryNoteNumberAsync(string deliveryNoteNumber) { if (string.IsNullOrWhiteSpace(deliveryNoteNumber)) throw new ArgumentException("El número de remito es obligatorio.", nameof(deliveryNoteNumber)); return _deliveryNoteRepository.GetDtoByDeliveryNoteNumberAsync(deliveryNoteNumber.Trim()); } public Task> GetDtosByQuoteIdAsync(int quoteId) { if (quoteId <= 0) throw new ArgumentOutOfRangeException(nameof(quoteId), "El identificador del presupuesto es inválido."); return _deliveryNoteRepository.GetDtosByQuoteIdAsync(quoteId); } public async Task CreateAndIssueDeliveryNoteAsync(DeliveryNoteCreateRequest request) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrWhiteSpace(request.DeliveryNoteNumber)) throw new ArgumentException("El número de remito es obligatorio.", nameof(request.DeliveryNoteNumber)); if (request.CustomerId <= 0) throw new ArgumentException("Debe seleccionar un cliente.", nameof(request.CustomerId)); if (request.IssueDate == default) throw new ArgumentException("La fecha de emisión es obligatoria.", nameof(request.IssueDate)); if (request.Items is null || request.Items.Count == 0) throw new InvalidOperationException("Debe incluir al menos un ítem."); if (request.Items.Any(i => i.Quantity <= 0)) throw new InvalidOperationException("Todas las cantidades deben ser mayores a cero."); if (request.Items.Any(i => string.IsNullOrWhiteSpace(i.Description))) throw new InvalidOperationException("Todos los ítems deben incluir descripción."); var deliveryNoteNumber = request.DeliveryNoteNumber.Trim(); if (await _deliveryNoteRepository.ExistsByDeliveryNoteNumberAsync(deliveryNoteNumber)) throw new InvalidOperationException($"Ya existe un remito con el número '{deliveryNoteNumber}'."); var now = DateTime.Now; var entity = new EDeliveryNote { Deliverynotenumber = deliveryNoteNumber, QuoteId = request.QuoteId, Issuedate = request.IssueDate, CustomerId = request.CustomerId, Status = "Emitido", Observations = string.IsNullOrWhiteSpace(request.Observations) ? null : request.Observations.Trim(), ExtrainfoJson = string.IsNullOrWhiteSpace(request.ExtraInfoJson) ? null : request.ExtraInfoJson.Trim(), Printcount = 0, Createdat = now, PhSDeliveryNoteDetails = request.Items .Select((item, index) => new EDeliveryNoteDetail { LineNumber = index + 1, OriginType = item.OriginType, OriginId = item.OriginId, QuoteDetailId = item.QuoteDetailId, Description = item.Description.Trim(), Quantity = item.Quantity, Notes = string.IsNullOrWhiteSpace(item.Notes) ? string.Empty : item.Notes.Trim(), Createdat = now }) .ToList() }; var created = await _deliveryNoteRepository.CreateAsync(entity); return new DeliveryNoteCreateResponse { Id = created.Id, DeliveryNoteNumber = created.Deliverynotenumber }; } } }