feat(sales): agregar servicio core de lectura para Delivery Note #18
36
Core/Interfaces/IDeliveryNoteDom.cs
Normal file
36
Core/Interfaces/IDeliveryNoteDom.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Servicio de dominio para la gestión de consultas de Delivery Note (Remito Ventas).
|
||||
/// Encapsula el acceso a datos y expone operaciones de lectura para la capa superior.
|
||||
/// </summary>
|
||||
public interface IDeliveryNoteDom
|
||||
{
|
||||
/// <summary>
|
||||
/// Obtiene un Delivery Note por su identificador único.
|
||||
/// </summary>
|
||||
/// <param name="id">Identificador interno del Delivery Note.</param>
|
||||
/// <returns>
|
||||
/// La entidad <see cref="EDeliveryNote"/> si existe; en caso contrario, null.
|
||||
/// </returns>
|
||||
Task<EDeliveryNote?> GetByIdAsync(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene un Delivery Note a partir de su número de documento.
|
||||
/// </summary>
|
||||
/// <param name="deliveryNoteNumber">Número del Delivery Note (ej: DN-00000001).</param>
|
||||
/// <returns>
|
||||
/// La entidad <see cref="EDeliveryNote"/> si existe; en caso contrario, null.
|
||||
/// </returns>
|
||||
Task<EDeliveryNote?> GetByDeliveryNoteNumberAsync(string deliveryNoteNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene todos los Delivery Notes asociados a un presupuesto (Quote).
|
||||
/// </summary>
|
||||
/// <param name="quoteId">Identificador del presupuesto relacionado.</param>
|
||||
/// <returns>
|
||||
/// Colección de <see cref="EDeliveryNote"/> asociadas al presupuesto.
|
||||
/// Puede estar vacía si no existen registros.
|
||||
/// </returns>
|
||||
Task<IEnumerable<EDeliveryNote>> GetByQuoteIdAsync(int quoteId);
|
||||
}
|
||||
35
Core/Services/DeliveryNoteService.cs
Normal file
35
Core/Services/DeliveryNoteService.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Core.Interfaces;
|
||||
using Domain.Entities;
|
||||
using Models.Interfaces;
|
||||
|
||||
namespace Core.Services
|
||||
{
|
||||
public class DeliveryNoteService(IPhSDeliveryNoteRepository deliveryNoteRepository) : IDeliveryNoteDom
|
||||
{
|
||||
private readonly IPhSDeliveryNoteRepository _deliveryNoteRepository = deliveryNoteRepository;
|
||||
|
||||
public Task<EDeliveryNote?> GetByIdAsync(int id)
|
||||
{
|
||||
if (id <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(id), "El identificador del remito es inválido.");
|
||||
|
||||
return _deliveryNoteRepository.GetByIdAsync(id);
|
||||
}
|
||||
|
||||
public Task<EDeliveryNote?> GetByDeliveryNoteNumberAsync(string deliveryNoteNumber)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(deliveryNoteNumber))
|
||||
throw new ArgumentException("El número de remito es obligatorio.", nameof(deliveryNoteNumber));
|
||||
|
||||
return _deliveryNoteRepository.GetByDeliveryNoteNumberAsync(deliveryNoteNumber.Trim());
|
||||
}
|
||||
|
||||
public Task<IEnumerable<EDeliveryNote>> GetByQuoteIdAsync(int quoteId)
|
||||
{
|
||||
if (quoteId <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(quoteId), "El identificador del presupuesto es inválido.");
|
||||
|
||||
return _deliveryNoteRepository.GetByQuoteIdAsync(quoteId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
USE [phronCare_OperationsHub]
|
||||
GO
|
||||
|
||||
SET ANSI_NULLS ON
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON
|
||||
GO
|
||||
|
||||
-- =============================================
|
||||
-- Procedure: PhLSM_Expedition_CheckStockItemConflicts
|
||||
-- Module: Logistics / Stock (PhLSM)
|
||||
-- Purpose: Detect serialized stock items already assigned
|
||||
-- to active expeditions.
|
||||
-- Author: Leandro Rojas
|
||||
-- Created: 2026-03-05
|
||||
-- =============================================
|
||||
|
||||
ALTER PROCEDURE [dbo].[PhLSM_Expedition_CheckStockItemConflicts]
|
||||
(
|
||||
@StockItemIds dbo.PhLSM_StockItemIdList READONLY,
|
||||
@IgnoreExpeditionId INT = NULL
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT
|
||||
d.stockitem_id AS StockitemId,
|
||||
h.id AS ExpeditionId,
|
||||
h.expeditionnumber AS Expeditionnumber,
|
||||
h.status AS Status
|
||||
FROM dbo.PhLSM_ExpeditionDetails d
|
||||
INNER JOIN @StockItemIds ids
|
||||
ON ids.stockitem_id = d.stockitem_id
|
||||
INNER JOIN dbo.PhLSM_ExpeditionHeaders h
|
||||
ON h.id = d.expedition_id
|
||||
INNER JOIN dbo.PhLSM_StockItem si
|
||||
ON si.id = d.stockitem_id
|
||||
WHERE h.status NOT IN (5,6) -- 5=Cerrada, 6=Anulada
|
||||
AND (@IgnoreExpeditionId IS NULL OR h.id <> @IgnoreExpeditionId)
|
||||
AND si.serial IS NOT NULL
|
||||
AND LTRIM(RTRIM(si.serial)) <> '';
|
||||
END
|
||||
GO
|
||||
@ -1,5 +0,0 @@
|
||||
CREATE TYPE dbo.PhLSM_StockItemIdList AS TABLE
|
||||
(
|
||||
stockitem_id INT NOT NULL
|
||||
);
|
||||
GO
|
||||
@ -1,36 +0,0 @@
|
||||
USE [phronCare_OperationsHub]
|
||||
GO
|
||||
|
||||
SET ANSI_NULLS ON
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON
|
||||
GO
|
||||
|
||||
-- =============================================
|
||||
-- Procedure: PhLSM_Stock_GetAvailabilityByStockItemIds
|
||||
-- Module: Logistics / Stock (PhLSM)
|
||||
-- Purpose: Returns quantity and availability data
|
||||
-- for the requested stock items.
|
||||
-- Author: Leandro Rojas
|
||||
-- Created: 2026-03-09
|
||||
-- =============================================
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[PhLSM_Stock_GetAvailabilityByStockItemIds]
|
||||
(
|
||||
@StockItemIds dbo.PhLSM_StockItemIdList READONLY
|
||||
)
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT
|
||||
si.id AS StockitemId,
|
||||
si.quantity AS Quantity,
|
||||
ISNULL(si.reserved_quantity, 0) AS ReservedQuantity,
|
||||
si.quantity - ISNULL(si.reserved_quantity, 0) AS AvailableQuantity,
|
||||
si.serial AS Serial
|
||||
FROM dbo.PhLSM_StockItem si
|
||||
INNER JOIN @StockItemIds ids
|
||||
ON ids.stockitem_id = si.id;
|
||||
END
|
||||
GO
|
||||
@ -1,135 +0,0 @@
|
||||
/* =========================================================
|
||||
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;
|
||||
@ -43,26 +43,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1.5 Documents", "1.5 Docume
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Documents", "Documents\Documents.csproj", "{0EFF27D3-C585-49F3-BBB5-A5E99C52207B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2.Database", "2.Database", "{E93C8350-6A6C-40F1-99C0-14CF7459EA8B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Migrations", "Migrations", "{5826BD19-0018-4F9C-B405-9BAB997CC8C7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Types", "Types", "{3C3276F6-7320-4AB8-9C1E-1893E4646FD4}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
PhLSM_StockItemIdList.sql = PhLSM_StockItemIdList.sql
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Procedures", "Procedures", "{E4F7BA13-B838-42D5-AADD-481DD76DDD5E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
PhLSM_Expedition_CheckStockItemConflicts.sql = PhLSM_Expedition_CheckStockItemConflicts.sql
|
||||
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
|
||||
@ -124,10 +104,6 @@ Global
|
||||
{34FC5538-4779-41F5-8355-7866B1395A4F} = {13328F60-28A6-446D-9935-23866F3F3D9D}
|
||||
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {74280C0B-F2CC-4A3E-86D6-05530F9766D5}
|
||||
{0EFF27D3-C585-49F3-BBB5-A5E99C52207B} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
|
||||
{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}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user