From f6bf3c61e8c2c95dc009836d0297325c0a9a2130 Mon Sep 17 00:00:00 2001 From: leandro Date: Mon, 23 Mar 2026 11:31:33 -0300 Subject: [PATCH 1/5] feat(sales): add delivery note create DTOs closes #35 --- Domain/Dtos/Sales/DeliveryNoteCreateItemRequest.cs | 12 ++++++++++++ Domain/Dtos/Sales/DeliveryNoteCreateRequest.cs | 13 +++++++++++++ Domain/Dtos/Sales/DeliveryNoteCreateResponse.cs | 8 ++++++++ 3 files changed, 33 insertions(+) create mode 100644 Domain/Dtos/Sales/DeliveryNoteCreateItemRequest.cs create mode 100644 Domain/Dtos/Sales/DeliveryNoteCreateRequest.cs create mode 100644 Domain/Dtos/Sales/DeliveryNoteCreateResponse.cs diff --git a/Domain/Dtos/Sales/DeliveryNoteCreateItemRequest.cs b/Domain/Dtos/Sales/DeliveryNoteCreateItemRequest.cs new file mode 100644 index 0000000..0d8d188 --- /dev/null +++ b/Domain/Dtos/Sales/DeliveryNoteCreateItemRequest.cs @@ -0,0 +1,12 @@ +namespace Domain.Dtos.Sales +{ + public class DeliveryNoteCreateItemRequest + { + public byte OriginType { get; set; } + public int? OriginId { get; set; } + public int? QuoteDetailId { get; set; } + public string Description { get; set; } = string.Empty; + public decimal Quantity { get; set; } + public string? Notes { get; set; } + } +} \ No newline at end of file diff --git a/Domain/Dtos/Sales/DeliveryNoteCreateRequest.cs b/Domain/Dtos/Sales/DeliveryNoteCreateRequest.cs new file mode 100644 index 0000000..3ef0e42 --- /dev/null +++ b/Domain/Dtos/Sales/DeliveryNoteCreateRequest.cs @@ -0,0 +1,13 @@ +namespace Domain.Dtos.Sales +{ + public class DeliveryNoteCreateRequest + { + public string DeliveryNoteNumber { get; set; } = string.Empty; + public int? QuoteId { get; set; } + public DateTime IssueDate { get; set; } + public int CustomerId { get; set; } + public string? Observations { get; set; } + public string? ExtraInfoJson { get; set; } + public List Items { get; set; } = new(); + } +} \ No newline at end of file diff --git a/Domain/Dtos/Sales/DeliveryNoteCreateResponse.cs b/Domain/Dtos/Sales/DeliveryNoteCreateResponse.cs new file mode 100644 index 0000000..8d3cef7 --- /dev/null +++ b/Domain/Dtos/Sales/DeliveryNoteCreateResponse.cs @@ -0,0 +1,8 @@ +namespace Domain.Dtos.Sales +{ + public class DeliveryNoteCreateResponse + { + public int Id { get; set; } + public string DeliveryNoteNumber { get; set; } = string.Empty; + } +} \ No newline at end of file From e0bc38d62604d8092ea2660edf711fc56218547c Mon Sep 17 00:00:00 2001 From: leandro Date: Mon, 23 Mar 2026 12:08:57 -0300 Subject: [PATCH 2/5] feat(sales): add delivery note issue core method closes #35 --- Core/Interfaces/IDeliveryNoteDom.cs | 5 ++++ Core/Services/DeliveryNoteService.cs | 40 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/Core/Interfaces/IDeliveryNoteDom.cs b/Core/Interfaces/IDeliveryNoteDom.cs index e63f606..bbeff1e 100644 --- a/Core/Interfaces/IDeliveryNoteDom.cs +++ b/Core/Interfaces/IDeliveryNoteDom.cs @@ -49,4 +49,9 @@ public interface IDeliveryNoteDom /// Puede estar vacía si no existen registros. /// Task> GetDtosByQuoteIdAsync(int quoteId); + + /// + /// Valida y prepara la emisión de un Delivery Note. + /// + Task CreateAndIssueDeliveryNoteAsync(DeliveryNoteCreateRequest request); } diff --git a/Core/Services/DeliveryNoteService.cs b/Core/Services/DeliveryNoteService.cs index 6b4894b..75c7cd9 100644 --- a/Core/Services/DeliveryNoteService.cs +++ b/Core/Services/DeliveryNoteService.cs @@ -1,5 +1,6 @@ using Core.Interfaces; using Domain.Dtos.Sales; +using Domain.Entities; using Domain.Generics; using Models.Interfaces; @@ -60,5 +61,44 @@ namespace Core.Services return _deliveryNoteRepository.GetDtosByQuoteIdAsync(quoteId); } + + public 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 entity = new EDeliveryNote + { + DeliveryNoteNumber = request.DeliveryNoteNumber.Trim(), + QuoteId = request.QuoteId, + IssueDate = request.IssueDate, + CustomerId = request.CustomerId, + Observations = request.Observations, + ExtraInfoJson = request.ExtraInfoJson + }; + + return Task.FromResult(new DeliveryNoteCreateResponse + { + Id = entity.Id, + DeliveryNoteNumber = entity.DeliveryNoteNumber + }); + } } } From 9327a1dc2ac14741a689a4e72bc357ceb1750485 Mon Sep 17 00:00:00 2001 From: leandro Date: Mon, 23 Mar 2026 18:14:00 -0300 Subject: [PATCH 3/5] refactor(sales): align delivery note entities with project mapping strategy closes #35 --- Core/Services/DeliveryNoteService.cs | 8 ++++---- Domain/Entities/EDeliveryNote.cs | 21 +++++++++------------ Domain/Entities/EDeliveryNoteDetail.cs | 6 +++--- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Core/Services/DeliveryNoteService.cs b/Core/Services/DeliveryNoteService.cs index 75c7cd9..c046236 100644 --- a/Core/Services/DeliveryNoteService.cs +++ b/Core/Services/DeliveryNoteService.cs @@ -86,18 +86,18 @@ namespace Core.Services var entity = new EDeliveryNote { - DeliveryNoteNumber = request.DeliveryNoteNumber.Trim(), + Deliverynotenumber = request.DeliveryNoteNumber.Trim(), QuoteId = request.QuoteId, - IssueDate = request.IssueDate, + Issuedate = request.IssueDate, CustomerId = request.CustomerId, Observations = request.Observations, - ExtraInfoJson = request.ExtraInfoJson + ExtrainfoJson = request.ExtraInfoJson }; return Task.FromResult(new DeliveryNoteCreateResponse { Id = entity.Id, - DeliveryNoteNumber = entity.DeliveryNoteNumber + DeliveryNoteNumber = entity.Deliverynotenumber }); } } diff --git a/Domain/Entities/EDeliveryNote.cs b/Domain/Entities/EDeliveryNote.cs index e343237..9f66e89 100644 --- a/Domain/Entities/EDeliveryNote.cs +++ b/Domain/Entities/EDeliveryNote.cs @@ -1,34 +1,31 @@ -using System; -using System.Collections.Generic; - namespace Domain.Entities { public class EDeliveryNote { public int Id { get; set; } - public string DeliveryNoteNumber { get; set; } = string.Empty; + public string Deliverynotenumber { get; set; } = null!; public int? QuoteId { get; set; } - public int? SalesInvoiceId { get; set; } + public int? SalesinvoiceId { get; set; } - public DateTime IssueDate { get; set; } + public DateTime Issuedate { get; set; } public int CustomerId { get; set; } - public string Status { get; set; } = string.Empty; + public string Status { get; set; } = null!; public string? Observations { get; set; } - public string? ExtraInfoJson { get; set; } + public string? ExtrainfoJson { get; set; } - public int PrintCount { get; set; } + public int Printcount { get; set; } - public DateTime CreatedAt { get; set; } + public DateTime Createdat { get; set; } - public DateTime? ModifiedAt { get; set; } + public DateTime? Modifiedat { get; set; } - public List PhSDeliveryNoteDetails { get; set; } = new List(); + public virtual ICollection PhSDeliveryNoteDetails { get; set; } = new List(); } } diff --git a/Domain/Entities/EDeliveryNoteDetail.cs b/Domain/Entities/EDeliveryNoteDetail.cs index 75e1765..ae0b467 100644 --- a/Domain/Entities/EDeliveryNoteDetail.cs +++ b/Domain/Entities/EDeliveryNoteDetail.cs @@ -1,6 +1,6 @@ namespace Domain.Entities { - public class EDeliveryNoteDetail + public partial class EDeliveryNoteDetail { public int Id { get; set; } @@ -24,9 +24,9 @@ public DateTime? Modifiedat { get; set; } - //public virtual PhSDeliveryNote Deliverynote { get; set; } = null!; + //public virtual EDeliveryNote Deliverynote { get; set; } = null!; - //public virtual PhSQuoteDetail? QuoteDetail { get; set; } + //public virtual EQuoteDetail? QuoteDetail { get; set; } } } From ec990897cba29e63f0fc6b23c1cde274b09cf51c Mon Sep 17 00:00:00 2001 From: leandro Date: Tue, 24 Mar 2026 02:59:07 -0300 Subject: [PATCH 4/5] feat(sales): persist delivery note issue in repository closes #35 --- .../Interfaces/IPhSDeliveryNoteRepository.cs | 4 ++++ .../Repositories/PhSDeliveryNoteRepository.cs | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/Models/Interfaces/IPhSDeliveryNoteRepository.cs b/Models/Interfaces/IPhSDeliveryNoteRepository.cs index 77223da..b7793aa 100644 --- a/Models/Interfaces/IPhSDeliveryNoteRepository.cs +++ b/Models/Interfaces/IPhSDeliveryNoteRepository.cs @@ -1,4 +1,5 @@ using Domain.Dtos.Sales; +using Domain.Entities; using Domain.Generics; namespace Models.Interfaces @@ -20,5 +21,8 @@ namespace Models.Interfaces Task GetDtoByIdAsync(int id); Task GetDtoByDeliveryNoteNumberAsync(string deliveryNoteNumber); Task> GetDtosByQuoteIdAsync(int quoteId); + + Task ExistsByDeliveryNoteNumberAsync(string deliveryNoteNumber); + Task CreateAsync(EDeliveryNote entity); } } diff --git a/Models/Repositories/PhSDeliveryNoteRepository.cs b/Models/Repositories/PhSDeliveryNoteRepository.cs index dcf0395..c4d5928 100644 --- a/Models/Repositories/PhSDeliveryNoteRepository.cs +++ b/Models/Repositories/PhSDeliveryNoteRepository.cs @@ -1,4 +1,5 @@ using Domain.Dtos.Sales; +using Domain.Entities; using Domain.Generics; using Microsoft.EntityFrameworkCore; using Models.Helpers; @@ -115,6 +116,23 @@ namespace Models.Repositories return entities.Select(MapDeliveryNoteDto); } + public async Task ExistsByDeliveryNoteNumberAsync(string deliveryNoteNumber) + { + return await _context.PhSDeliveryNotes + .AsNoTracking() + .AnyAsync(x => x.Deliverynotenumber == deliveryNoteNumber); + } + + public async Task CreateAsync(EDeliveryNote entity) + { + var mapped = EntityMapper.MapEntity(entity); + + await _context.PhSDeliveryNotes.AddAsync(mapped); + await _context.SaveChangesAsync(); + + return EntityMapper.MapEntity(mapped); + } + private static DeliveryNoteDto MapDeliveryNoteDto(PhSDeliveryNote source) { return new DeliveryNoteDto From 1b74027195277085c945204bff78b70e12750584 Mon Sep 17 00:00:00 2001 From: leandro Date: Tue, 24 Mar 2026 09:57:52 -0300 Subject: [PATCH 5/5] feat(sales): add delivery note issue endpoint closes #35 --- .../Sales/DeliveryNoteController.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/phronCare.API/Controllers/Sales/DeliveryNoteController.cs b/phronCare.API/Controllers/Sales/DeliveryNoteController.cs index 345431f..c25215c 100644 --- a/phronCare.API/Controllers/Sales/DeliveryNoteController.cs +++ b/phronCare.API/Controllers/Sales/DeliveryNoteController.cs @@ -103,5 +103,28 @@ namespace phronCare.API.Controllers.Sales return StatusCode(500, $"{methodName} Message: {ex.Message}"); } } + + [HttpPost("issue")] + public async Task> Issue([FromBody] DeliveryNoteCreateRequest request) + { + try + { + var result = await _deliveryNoteService.CreateAndIssueDeliveryNoteAsync(request); + return Ok(result); + } + catch (ArgumentException ex) + { + return BadRequest(ex.Message); + } + catch (InvalidOperationException ex) + { + return BadRequest(ex.Message); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } } }