From dc08291932423d3607a996dad043b262af732595 Mon Sep 17 00:00:00 2001 From: leandro Date: Mon, 16 Mar 2026 19:42:56 -0300 Subject: [PATCH] feat(sales): scaffold EF para Delivery Notes Closes #11 --- Models/Models/PhSCustomer.cs | 2 + Models/Models/PhSDeliveryNote.cs | 37 +++++ Models/Models/PhSDeliveryNoteDetail.cs | 33 +++++ Models/Models/PhSQuoteDetail.cs | 2 + Models/Models/PhSQuoteHeader.cs | 2 + .../Models/PhronCareOperationsHubContext.cs | 96 +++++++++++++ Story 9 - Stock Reservation.sql | 135 ++++++++++++++++++ phronCare.sln | 6 + 8 files changed, 313 insertions(+) create mode 100644 Models/Models/PhSDeliveryNote.cs create mode 100644 Models/Models/PhSDeliveryNoteDetail.cs create mode 100644 Story 9 - Stock Reservation.sql diff --git a/Models/Models/PhSCustomer.cs b/Models/Models/PhSCustomer.cs index 2ed7d8e..b2da33d 100644 --- a/Models/Models/PhSCustomer.cs +++ b/Models/Models/PhSCustomer.cs @@ -29,6 +29,8 @@ public partial class PhSCustomer public virtual ICollection PhSCustomerDocuments { get; set; } = new List(); + public virtual ICollection PhSDeliveryNotes { get; set; } = new List(); + public virtual ICollection PhSPatients { get; set; } = new List(); public virtual PhOhTaxCondition? TaxCondition { get; set; } diff --git a/Models/Models/PhSDeliveryNote.cs b/Models/Models/PhSDeliveryNote.cs new file mode 100644 index 0000000..b5662f0 --- /dev/null +++ b/Models/Models/PhSDeliveryNote.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; + +namespace Models.Models; + +public partial class PhSDeliveryNote +{ + public int Id { get; set; } + + public string Deliverynotenumber { get; set; } = null!; + + public int? QuoteId { get; set; } + + public int? SalesinvoiceId { get; set; } + + public DateTime Issuedate { get; set; } + + public int CustomerId { get; set; } + + public string Status { get; set; } = null!; + + public string? Observations { get; set; } + + public string? ExtrainfoJson { get; set; } + + public int Printcount { get; set; } + + public DateTime Createdat { get; set; } + + public DateTime? Modifiedat { get; set; } + + public virtual PhSCustomer Customer { get; set; } = null!; + + public virtual ICollection PhSDeliveryNoteDetails { get; set; } = new List(); + + public virtual PhSQuoteHeader? Quote { get; set; } +} diff --git a/Models/Models/PhSDeliveryNoteDetail.cs b/Models/Models/PhSDeliveryNoteDetail.cs new file mode 100644 index 0000000..667eef9 --- /dev/null +++ b/Models/Models/PhSDeliveryNoteDetail.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace Models.Models; + +public partial class PhSDeliveryNoteDetail +{ + public int Id { get; set; } + + public int DeliverynoteId { get; set; } + + public int LineNumber { get; set; } + + public byte OriginType { get; set; } + + public int? OriginId { get; set; } + + public int? QuoteDetailId { get; set; } + + public string Description { get; set; } = null!; + + public decimal Quantity { get; set; } + + public string Notes { get; set; } = null!; + + public DateTime Createdat { get; set; } + + public DateTime? Modifiedat { get; set; } + + public virtual PhSDeliveryNote Deliverynote { get; set; } = null!; + + public virtual PhSQuoteDetail? QuoteDetail { get; set; } +} diff --git a/Models/Models/PhSQuoteDetail.cs b/Models/Models/PhSQuoteDetail.cs index 202a86c..0fb915b 100644 --- a/Models/Models/PhSQuoteDetail.cs +++ b/Models/Models/PhSQuoteDetail.cs @@ -68,6 +68,8 @@ public partial class PhSQuoteDetail /// public DateTime? Modifiedat { get; set; } + public virtual ICollection PhSDeliveryNoteDetails { get; set; } = new List(); + public virtual PhSProduct Product { get; set; } = null!; public virtual PhSQuoteHeader Quoteheader { get; set; } = null!; diff --git a/Models/Models/PhSQuoteHeader.cs b/Models/Models/PhSQuoteHeader.cs index 3aac24c..90a62c4 100644 --- a/Models/Models/PhSQuoteHeader.cs +++ b/Models/Models/PhSQuoteHeader.cs @@ -130,6 +130,8 @@ public partial class PhSQuoteHeader public virtual PhSPaymentTerm? Paymentterm { get; set; } + public virtual ICollection PhSDeliveryNotes { get; set; } = new List(); + public virtual ICollection PhSQuoteAdjustments { get; set; } = new List(); public virtual ICollection PhSQuoteDetails { get; set; } = new List(); diff --git a/Models/Models/PhronCareOperationsHubContext.cs b/Models/Models/PhronCareOperationsHubContext.cs index 41c901a..b2514c6 100644 --- a/Models/Models/PhronCareOperationsHubContext.cs +++ b/Models/Models/PhronCareOperationsHubContext.cs @@ -57,6 +57,10 @@ public partial class PhronCareOperationsHubContext : DbContext public virtual DbSet PhSCustomerDocuments { get; set; } + public virtual DbSet PhSDeliveryNotes { get; set; } + + public virtual DbSet PhSDeliveryNoteDetails { get; set; } + public virtual DbSet PhSDocumentTypes { get; set; } public virtual DbSet PhSFormSeries { get; set; } @@ -1033,6 +1037,98 @@ public partial class PhronCareOperationsHubContext : DbContext .HasConstraintName("FK_PhS_CustomerDocuments_PhS_DocumentTypes"); }); + modelBuilder.Entity(entity => + { + entity.ToTable("PhS_DeliveryNotes"); + + entity.HasIndex(e => e.CustomerId, "IX_PhS_DeliveryNotes_customer_id"); + + entity.HasIndex(e => e.Issuedate, "IX_PhS_DeliveryNotes_issuedate"); + + entity.HasIndex(e => e.QuoteId, "IX_PhS_DeliveryNotes_quote_id"); + + entity.HasIndex(e => e.Status, "IX_PhS_DeliveryNotes_status"); + + entity.HasIndex(e => e.Deliverynotenumber, "UQ_PhS_DeliveryNotes_deliverynotenumber").IsUnique(); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Createdat) + .HasDefaultValueSql("(getdate())") + .HasColumnType("datetime") + .HasColumnName("createdat"); + entity.Property(e => e.CustomerId).HasColumnName("customer_id"); + entity.Property(e => e.Deliverynotenumber) + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnName("deliverynotenumber"); + entity.Property(e => e.ExtrainfoJson).HasColumnName("extrainfo_json"); + entity.Property(e => e.Issuedate) + .HasColumnType("datetime") + .HasColumnName("issuedate"); + entity.Property(e => e.Modifiedat) + .HasColumnType("datetime") + .HasColumnName("modifiedat"); + entity.Property(e => e.Observations) + .HasMaxLength(1000) + .HasColumnName("observations"); + entity.Property(e => e.Printcount).HasColumnName("printcount"); + entity.Property(e => e.QuoteId).HasColumnName("quote_id"); + entity.Property(e => e.SalesinvoiceId).HasColumnName("salesinvoice_id"); + entity.Property(e => e.Status) + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnName("status"); + + entity.HasOne(d => d.Customer).WithMany(p => p.PhSDeliveryNotes) + .HasForeignKey(d => d.CustomerId) + .OnDelete(DeleteBehavior.ClientSetNull); + + entity.HasOne(d => d.Quote).WithMany(p => p.PhSDeliveryNotes).HasForeignKey(d => d.QuoteId); + }); + + modelBuilder.Entity(entity => + { + entity.ToTable("PhS_DeliveryNoteDetails"); + + entity.HasIndex(e => e.DeliverynoteId, "IX_PhS_DeliveryNoteDetails_deliverynote_id"); + + entity.HasIndex(e => new { e.DeliverynoteId, e.LineNumber }, "IX_PhS_DeliveryNoteDetails_deliverynote_id_line_number"); + + entity.HasIndex(e => new { e.OriginType, e.OriginId }, "IX_PhS_DeliveryNoteDetails_origin_type_origin_id"); + + entity.HasIndex(e => e.QuoteDetailId, "IX_PhS_DeliveryNoteDetails_quote_detail_id"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Createdat) + .HasDefaultValueSql("(getdate())") + .HasColumnType("datetime") + .HasColumnName("createdat"); + entity.Property(e => e.DeliverynoteId).HasColumnName("deliverynote_id"); + entity.Property(e => e.Description) + .HasMaxLength(500) + .HasColumnName("description"); + entity.Property(e => e.LineNumber).HasColumnName("line_number"); + entity.Property(e => e.Modifiedat) + .HasColumnType("datetime") + .HasColumnName("modifiedat"); + entity.Property(e => e.Notes) + .HasMaxLength(1000) + .HasDefaultValue("") + .HasColumnName("notes"); + entity.Property(e => e.OriginId).HasColumnName("origin_id"); + entity.Property(e => e.OriginType).HasColumnName("origin_type"); + entity.Property(e => e.Quantity) + .HasColumnType("decimal(18, 2)") + .HasColumnName("quantity"); + entity.Property(e => e.QuoteDetailId).HasColumnName("quote_detail_id"); + + entity.HasOne(d => d.Deliverynote).WithMany(p => p.PhSDeliveryNoteDetails) + .HasForeignKey(d => d.DeliverynoteId) + .OnDelete(DeleteBehavior.ClientSetNull); + + entity.HasOne(d => d.QuoteDetail).WithMany(p => p.PhSDeliveryNoteDetails).HasForeignKey(d => d.QuoteDetailId); + }); + modelBuilder.Entity(entity => { entity.ToTable("PhS_DocumentTypes"); diff --git a/Story 9 - Stock Reservation.sql b/Story 9 - Stock Reservation.sql new file mode 100644 index 0000000..e89957a --- /dev/null +++ b/Story 9 - Stock Reservation.sql @@ -0,0 +1,135 @@ +/* ========================================================= + VERIFICACIÓN STORY #9 + Expedición -> EnTransito + reservas de stock + ========================================================= */ + +SET NOCOUNT ON; + +DECLARE @ExpeditionNumber VARCHAR(50) = 'X-00000054'; -- cambiar + +DECLARE @ExpeditionId INT; + +SELECT @ExpeditionId = id +FROM dbo.PhLSM_ExpeditionHeaders +WHERE expeditionnumber = @ExpeditionNumber; + +IF @ExpeditionId IS NULL +BEGIN + RAISERROR('Expedición no encontrada',16,1); + RETURN; +END + +PRINT 'ExpeditionId: ' + CAST(@ExpeditionId AS VARCHAR); + +------------------------------------------------------------- +-- 1. CABECERA +------------------------------------------------------------- +PRINT '===== CABECERA ====='; + +SELECT + id, + expeditionnumber, + issuedate, + status, + observations +FROM dbo.PhLSM_ExpeditionHeaders +WHERE id = @ExpeditionId; + + +------------------------------------------------------------- +-- 2. DETALLES +------------------------------------------------------------- +PRINT '===== DETALLES ====='; + +SELECT + d.id, + d.expedition_id, + d.product_id, + d.stockitem_id, + d.quantity, + d.batch, + d.serial, + d.expiration +FROM dbo.PhLSM_ExpeditionDetails d +WHERE d.expedition_id = @ExpeditionId +ORDER BY d.id; + + +------------------------------------------------------------- +-- 3. RESERVAS CREADAS +------------------------------------------------------------- +PRINT '===== RESERVAS ====='; + +SELECT + r.id, + r.source_type, + r.source_id, + r.stockitem_id, + r.reserved_quantity, + r.status, + r.createdat +FROM dbo.PhLSM_StockReservation r +WHERE r.source_type = 1 +AND r.source_id = @ExpeditionId +ORDER BY r.id; + + +------------------------------------------------------------- +-- 4. STOCK ITEMS AFECTADOS +------------------------------------------------------------- +PRINT '===== STOCK ITEMS ====='; + +SELECT + si.id, + si.product_id, + si.location_id, + si.quantity, + si.reserved_quantity, + (si.quantity - si.reserved_quantity) AS available +FROM dbo.PhLSM_StockItem si +WHERE si.id IN +( + SELECT stockitem_id + FROM dbo.PhLSM_ExpeditionDetails + WHERE expedition_id = @ExpeditionId +); + + +------------------------------------------------------------- +-- 5. VALIDACIÓN DETALLE VS RESERVA +------------------------------------------------------------- +PRINT '===== VALIDACION ====='; + +SELECT + d.id AS detail_id, + d.stockitem_id, + d.quantity AS requested, + r.reserved_quantity, + CASE + WHEN r.id IS NULL THEN 'FALTA RESERVA' + WHEN r.reserved_quantity <> d.quantity THEN 'CANTIDAD DISTINTA' + ELSE 'OK' + END AS resultado +FROM dbo.PhLSM_ExpeditionDetails d +LEFT JOIN dbo.PhLSM_StockReservation r + ON r.source_id = d.expedition_id + AND r.stockitem_id = d.stockitem_id + AND r.source_type = 1 + AND r.status = 1 +WHERE d.expedition_id = @ExpeditionId; + + +------------------------------------------------------------- +-- 6. CHEQUEO DE DUPLICADOS +------------------------------------------------------------- +PRINT '===== DUPLICADOS ====='; + +SELECT + stockitem_id, + COUNT(*) AS cantidad +FROM dbo.PhLSM_StockReservation +WHERE source_type = 1 +AND source_id = @ExpeditionId +AND status = 1 +GROUP BY stockitem_id +HAVING COUNT(*) > 1; \ No newline at end of file diff --git a/phronCare.sln b/phronCare.sln index f088fa4..e837413 100644 --- a/phronCare.sln +++ b/phronCare.sln @@ -58,6 +58,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Procedures", "Procedures", PhLSM_Stock_GetAvailabilityByStockItemIds.sql = PhLSM_Stock_GetAvailabilityByStockItemIds.sql EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Verifications", "Verifications", "{85918AF0-7D8E-41B6-9157-BD2ADF05BD64}" + ProjectSection(SolutionItems) = preProject + Story 9 - Stock Reservation.sql = Story 9 - Stock Reservation.sql + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -122,6 +127,7 @@ Global {5826BD19-0018-4F9C-B405-9BAB997CC8C7} = {E93C8350-6A6C-40F1-99C0-14CF7459EA8B} {3C3276F6-7320-4AB8-9C1E-1893E4646FD4} = {E93C8350-6A6C-40F1-99C0-14CF7459EA8B} {E4F7BA13-B838-42D5-AADD-481DD76DDD5E} = {E93C8350-6A6C-40F1-99C0-14CF7459EA8B} + {85918AF0-7D8E-41B6-9157-BD2ADF05BD64} = {E93C8350-6A6C-40F1-99C0-14CF7459EA8B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {92DE3FEB-7D7E-4C78-BE8C-34931CA1DAED}