/*
Patch cumulativa DB online - ramo Python WMS

Da eseguire una sola volta in SSMS sul database Mediseawall.

Questa patch NON modifica gli oggetti legacy usati dal programma C#.

Include:
- dbo.PyPickingListReservation
- dbo.py_XMag_ViewPackingList
- dbo.py_ViewPackingListRestante
- dbo.py_sp_xExePackingListPallet
- dbo.py_sp_xExePackingListPalletPrenota
- dbo.py_sp_ControllaPrenotazionePackingListPalletNew
- dbo.py_vPreparaPackingListSAMA1
- dbo.py_vPreparaPackingList
- dbo.py_XMag_ViewPackingListStorico
- dbo.py_BarcodePickingListSkip

Nota storico:
dbo.py_vPreparaPackingListSAMA1 usa ANNDOC >= YEAR(GETDATE())
per mantenere visibili solo le picking list dall'inizio dell'anno corrente.
*/

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

/* ============================================================
   1. Stato prenotazione picking list ramo Python
   ============================================================ */

IF OBJECT_ID(N'dbo.PyPickingListReservation', N'U') IS NULL
BEGIN
    CREATE TABLE [dbo].[PyPickingListReservation](
        [ID] [tinyint] NOT NULL,
        [Documento] [varchar](8) NULL,
        [IDOperatore] [int] NULL,
        [ModUtente] [varchar](50) NULL,
        [ModDataOra] [datetime] NULL,
        CONSTRAINT [PK_PyPickingListReservation] PRIMARY KEY CLUSTERED ([ID] ASC),
        CONSTRAINT [CK_PyPickingListReservation_Singleton] CHECK ([ID] = 1)
    ) ON [PRIMARY];
END
GO

IF NOT EXISTS (SELECT 1 FROM dbo.PyPickingListReservation WHERE ID = 1)
BEGIN
    INSERT INTO dbo.PyPickingListReservation (ID, Documento, IDOperatore, ModUtente, ModDataOra)
    VALUES (1, NULL, NULL, NULL, GETDATE());
END
GO

/* ============================================================
   2. Viste operative picking list ramo Python
   ============================================================ */

CREATE OR ALTER VIEW [dbo].[py_XMag_ViewPackingList]
AS
SELECT TOP 10000
    legacy.Pallet,
    legacy.Lotto,
    legacy.Articolo,
    legacy.Descrizione,
    legacy.Qta,
    legacy.Documento,
    legacy.CodNazione,
    legacy.NAZIONE,
    legacy.Stato,
    legacy.PalletCella,
    legacy.Magazzino,
    legacy.Area,
    legacy.Cella,
    legacy.Ordinamento,
    legacy.Ubicazione,
    legacy.DEST,
    CASE
        WHEN pr.Documento IS NOT NULL
         AND pr.Documento = CAST(legacy.Documento AS varchar(8))
        THEN 1
        ELSE 0
    END AS IDStato
FROM dbo.XMag_ViewPackingList legacy
LEFT JOIN dbo.PyPickingListReservation pr
    ON pr.ID = 1
   AND NULLIF(LTRIM(RTRIM(pr.Documento)), '') IS NOT NULL
ORDER BY
    CASE
        WHEN pr.Documento IS NOT NULL
         AND pr.Documento = CAST(legacy.Documento AS varchar(8))
        THEN 1
        ELSE 0
    END DESC,
    legacy.Documento,
    legacy.Ordinamento;
GO

CREATE OR ALTER VIEW [dbo].[py_ViewPackingListRestante]
AS
SELECT
    Pallet,
    Lotto,
    Articolo,
    Descrizione,
    Qta,
    Documento,
    CodNazione,
    NAZIONE,
    Stato,
    PalletCella,
    Magazzino,
    Area,
    Cella,
    Ordinamento,
    Ubicazione,
    DEST,
    IDStato
FROM dbo.py_XMag_ViewPackingList
WHERE Cella <> 9999;
GO

/* ============================================================
   3. Stored procedure operative ramo Python
   ============================================================ */

CREATE OR ALTER PROCEDURE [dbo].[py_sp_xExePackingListPallet]
    @IDOperatore int,
    @Documento varchar(8),
    @Azione char(1) = 'P',
    @RC int OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    SET @RC = 0;

    DECLARE @Nominativo varchar(50) = '';
    DECLARE @DocumentoAttivo varchar(8) = NULL;
    DECLARE @Description varchar(255) = '';
    DECLARE @Message varchar(255) = '';
    DECLARE @IDResult int = 0;
    DECLARE @ID int = 0;

    SELECT @Nominativo = [Login]
    FROM dbo.Operatori
    WHERE ID = @IDOperatore;

    IF @Nominativo IS NULL
        SET @Nominativo = 'SYSTEM';

    IF @Azione NOT IN ('P', 'S')
    BEGIN
        SET @RC = -10;
        RETURN;
    END;

    IF NOT EXISTS (
        SELECT 1
        FROM dbo.py_XMag_ViewPackingList
        WHERE CAST(Documento AS varchar(8)) = @Documento
    )
    BEGIN
        SET @RC = -20;
        RETURN;
    END;

    IF NOT EXISTS (SELECT 1 FROM dbo.PyPickingListReservation WHERE ID = 1)
    BEGIN
        INSERT INTO dbo.PyPickingListReservation (ID, Documento, IDOperatore, ModUtente, ModDataOra)
        VALUES (1, NULL, NULL, NULL, GETDATE());
    END;

    SELECT @DocumentoAttivo = NULLIF(LTRIM(RTRIM(Documento)), '')
    FROM dbo.PyPickingListReservation
    WHERE ID = 1;

    DECLARE @TargetCelle TABLE (
        IDCella int PRIMARY KEY
    );

    INSERT INTO @TargetCelle (IDCella)
    SELECT DISTINCT Cella
    FROM dbo.py_XMag_ViewPackingList
    WHERE CAST(Documento AS varchar(8)) = @Documento
      AND Cella IS NOT NULL;

    IF @Azione = 'P'
    BEGIN
        IF @DocumentoAttivo = @Documento
            RETURN;

        UPDATE c
        SET c.IDStato = 0,
            c.ModUtente = @Nominativo,
            c.ModDataOra = GETDATE()
        FROM dbo.Celle c
        WHERE ISNULL(c.IDStato, 0) <> 0;

        UPDATE c
        SET c.IDStato = 1,
            c.ModUtente = @Nominativo,
            c.ModDataOra = GETDATE()
        FROM dbo.Celle c
        INNER JOIN @TargetCelle t ON t.IDCella = c.ID;

        UPDATE dbo.PyPickingListReservation
        SET Documento = @Documento,
            IDOperatore = @IDOperatore,
            ModUtente = @Nominativo,
            ModDataOra = GETDATE()
        WHERE ID = 1;

        SELECT TOP 1 @Description = NAZIONE
        FROM dbo.py_XMag_ViewPackingList
        WHERE CAST(Documento AS varchar(8)) = @Documento;

        EXEC dbo.sp_LogPackingList
             @ID = @ID,
             @Code = @Documento,
             @Description = @Description,
             @Message = @Message OUTPUT,
             @IDResult = @IDResult OUTPUT;

        RETURN;
    END;

    IF @Azione = 'S'
    BEGIN
        IF ISNULL(@DocumentoAttivo, '') <> @Documento
            RETURN;

        UPDATE c
        SET c.IDStato = 0,
            c.ModUtente = @Nominativo,
            c.ModDataOra = GETDATE()
        FROM dbo.Celle c
        INNER JOIN @TargetCelle t ON t.IDCella = c.ID;

        UPDATE dbo.PyPickingListReservation
        SET Documento = NULL,
            IDOperatore = @IDOperatore,
            ModUtente = @Nominativo,
            ModDataOra = GETDATE()
        WHERE ID = 1;

        RETURN;
    END;
END;
GO

CREATE OR ALTER PROCEDURE [dbo].[py_sp_xExePackingListPalletPrenota]
    @IDOperatore int,
    @Documento varchar(8),
    @RC int OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    SET @RC = 0;

    DECLARE @Nominativo varchar(50) = '';

    SELECT @Nominativo = LOGIN
    FROM dbo.Operatori
    WHERE ID = @IDOperatore;

    IF @Nominativo IS NULL
        SET @Nominativo = 'SYSTEM';

    UPDATE c
    SET c.IDStato = 1,
        c.ModUtente = @Nominativo,
        c.ModDataOra = GETDATE()
    FROM dbo.Celle c
    WHERE c.ID IN (
        SELECT DISTINCT Cella
        FROM dbo.py_ViewPackingListRestante
        WHERE CAST(Documento AS varchar(8)) = @Documento
          AND Cella IS NOT NULL
    );
END;
GO

CREATE OR ALTER PROCEDURE [dbo].[py_sp_ControllaPrenotazionePackingListPalletNew]
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @Documento varchar(8) = NULL;
    DECLARE @IDOperatore int = 0;
    DECLARE @Nominativo varchar(50) = 'SYSTEM';
    DECLARE @RC int = 0;

    SELECT
        @Documento = NULLIF(LTRIM(RTRIM(Documento)), ''),
        @IDOperatore = ISNULL(IDOperatore, 0),
        @Nominativo = ISNULL(NULLIF(LTRIM(RTRIM(ModUtente)), ''), 'SYSTEM')
    FROM dbo.PyPickingListReservation
    WHERE ID = 1;

    IF ISNULL(@Documento, '') = ''
        RETURN;

    IF NOT EXISTS (
        SELECT 1
        FROM dbo.py_ViewPackingListRestante
        WHERE CAST(Documento AS varchar(8)) = @Documento
    )
    BEGIN
        UPDATE dbo.Celle
        SET IDStato = 0,
            ModUtente = @Nominativo,
            ModDataOra = GETDATE()
        WHERE ISNULL(IDStato, 0) <> 0;

        UPDATE dbo.PyPickingListReservation
        SET Documento = NULL,
            IDOperatore = @IDOperatore,
            ModUtente = @Nominativo,
            ModDataOra = GETDATE()
        WHERE ID = 1;

        RETURN;
    END;

    UPDATE dbo.Celle
    SET IDStato = 0,
        ModUtente = @Nominativo,
        ModDataOra = GETDATE()
    WHERE ISNULL(IDStato, 0) <> 0;

    IF @IDOperatore <= 0
    BEGIN
        SELECT TOP 1 @IDOperatore = ID
        FROM dbo.Operatori
        WHERE LOGIN = @Nominativo;
    END;

    EXEC dbo.py_sp_xExePackingListPalletPrenota
         @IDOperatore = @IDOperatore,
         @Documento = @Documento,
         @RC = @RC OUTPUT;
END;
GO

/* ============================================================
   4. Viste storico picking list ramo Python
   ============================================================ */

CREATE OR ALTER VIEW [dbo].[py_vPreparaPackingListSAMA1]
AS
SELECT
    SAMA1.dbo.LOTSER.NUMLOT,
    SAMA1.dbo.ARTICO.CODICE,
    SAMA1.dbo.FATRIG.DESCR,
    LEFT(SAMA1.dbo.LOTSER.NUMSER, 6) AS UDC,
    SUM(SAMA1.dbo.LOTSER.QTTGIAI) AS Qta,
    SAMA1.dbo.BAMTES.NUMDOC,
    SAMA1.dbo.BAMTES.DATDOC,
    SAMA1.dbo.BAMTES.ID,
    SAMA1.dbo.BAMTES.DESCRDEST,
    SAMA1.dbo.BAMTES.STATO AS StatoDocumento,
    SAMA1.dbo.NAZIONI.CODICE AS Expr1,
    SAMA1.dbo.MTRASP.CODICE + '  ' + SAMA1.dbo.NAZIONI.DESCR AS NAZIONE,
    SAMA1.dbo.BAMTES.IDMTRASP
FROM SAMA1.dbo.NAZIONI
INNER JOIN SAMA1.dbo.BAMTES
    ON SAMA1.dbo.NAZIONI.ID = SAMA1.dbo.BAMTES.IDNAZDEST
RIGHT OUTER JOIN SAMA1.dbo.LOTTIBF
LEFT OUTER JOIN SAMA1.dbo.LOTSER
    ON SAMA1.dbo.LOTTIBF.IDLOTSER = SAMA1.dbo.LOTSER.ID
LEFT OUTER JOIN SAMA1.dbo.ARTICO
    ON SAMA1.dbo.LOTSER.IDARTICO = SAMA1.dbo.ARTICO.ID
LEFT OUTER JOIN SAMA1.dbo.FATRIG
    ON SAMA1.dbo.LOTTIBF.IDFATRIG = SAMA1.dbo.FATRIG.ID
    ON SAMA1.dbo.BAMTES.ID = SAMA1.dbo.FATRIG.IDBAM
LEFT OUTER JOIN SAMA1.sam.EXTUC
    ON LEFT(SAMA1.dbo.LOTSER.NUMSER, 6) = SAMA1.sam.EXTUC.CODICE
LEFT OUTER JOIN SAMA1.dbo.MTRASP
    ON SAMA1.dbo.BAMTES.IDMTRASP = SAMA1.dbo.MTRASP.ID
WHERE
    SAMA1.dbo.BAMTES.ANNDOC >= YEAR(GETDATE())
    AND SAMA1.dbo.BAMTES.STATO IN ('P', 'D')
    AND SAMA1.dbo.LOTSER.NUMLOT <> '00000000000'
GROUP BY
    SAMA1.dbo.LOTSER.NUMLOT,
    SAMA1.dbo.ARTICO.CODICE,
    SAMA1.dbo.FATRIG.DESCR,
    LEFT(SAMA1.dbo.LOTSER.NUMSER, 6),
    SAMA1.dbo.BAMTES.NUMDOC,
    SAMA1.dbo.BAMTES.DATDOC,
    SAMA1.dbo.BAMTES.ID,
    SAMA1.dbo.BAMTES.DESCRDEST,
    SAMA1.dbo.BAMTES.STATO,
    SAMA1.dbo.NAZIONI.CODICE,
    SAMA1.dbo.NAZIONI.DESCR,
    SAMA1.dbo.BAMTES.IDMTRASP,
    SAMA1.dbo.MTRASP.CODICE;
GO

CREATE OR ALTER VIEW [dbo].[py_vPreparaPackingList]
AS
SELECT
    NUMLOT,
    CODICE,
    DESCR,
    UDC,
    Qta,
    NUMDOC,
    DATDOC,
    ID,
    DESCRDEST,
    StatoDocumento,
    Expr1,
    NAZIONE
FROM dbo.py_vPreparaPackingListSAMA1
WHERE NUMLOT <> '';
GO

CREATE OR ALTER VIEW [dbo].[py_XMag_ViewPackingListStorico]
AS
SELECT TOP (100000)
    prep.UDC AS Pallet,
    prep.NUMLOT AS Lotto,
    prep.CODICE AS Articolo,
    prep.DESCR AS Descrizione,
    prep.Qta,
    prep.NUMDOC AS Documento,
    prep.DATDOC AS DataDocumento,
    prep.StatoDocumento,
    prep.Expr1 AS CodNazione,
    prep.NAZIONE,
    CASE
        WHEN prep.Expr1 = 'DE' THEN 10
        WHEN prep.Expr1 = 'TH' THEN
            CASE WHEN SUBSTRING(prep.DESCRDEST, 1, 2) = 'NA' THEN 11 ELSE 13 END
        WHEN prep.Expr1 = 'MEX' THEN 12
        ELSE 4
    END AS Stato,
    ISNULL(g.NumeroPallet, 0) AS PalletCella,
    ISNULL(g.IDMagazzino, 1) AS Magazzino,
    ISNULL(g.IDArea, 5) AS Area,
    ISNULL(g.IDCella, 1000) AS Cella,
    ISNULL(c.Ordinamento, 99999) AS Ordinamento,
    ISNULL(c.Corsia + ' - ' + c.Colonna + ' - ' + c.Fila, 'Non scaff.') AS Ubicazione,
    SUBSTRING(prep.DESCRDEST, 1, 2) AS DEST,
    CASE
        WHEN MAX(CASE
            WHEN pr.Documento IS NOT NULL
             AND pr.Documento = CAST(prep.NUMDOC AS varchar(8))
            THEN 1 ELSE 0 END) = 1
        THEN 1
        ELSE 0
    END AS IDStato
FROM dbo.Celle c
INNER JOIN dbo.XMag_GiacenzaPallet g
    ON c.ID = g.IDCella
RIGHT OUTER JOIN dbo.py_vPreparaPackingList prep
    ON g.BarcodePallet COLLATE SQL_Latin1_General_CP1_CI_AS = prep.UDC
LEFT JOIN dbo.PyPickingListReservation pr
    ON pr.ID = 1
   AND NULLIF(LTRIM(RTRIM(pr.Documento)), '') IS NOT NULL
GROUP BY
    prep.Expr1,
    prep.NAZIONE,
    prep.UDC,
    prep.NUMDOC,
    prep.DATDOC,
    prep.StatoDocumento,
    prep.NUMLOT,
    prep.CODICE,
    prep.DESCR,
    prep.Qta,
    g.NumeroPallet,
    g.IDMagazzino,
    g.IDArea,
    g.IDCella,
    c.Ordinamento,
    c.Corsia,
    c.Colonna,
    c.Fila,
    prep.DESCRDEST;
GO

/* ============================================================
   5. Tabella salta UDC barcode picking list
   ============================================================ */

IF OBJECT_ID(N'dbo.py_BarcodePickingListSkip', N'U') IS NULL
BEGIN
    CREATE TABLE dbo.py_BarcodePickingListSkip (
        ID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_py_BarcodePickingListSkip PRIMARY KEY,
        Documento varchar(50) COLLATE Latin1_General_CI_AS NOT NULL,
        Pallet varchar(50) COLLATE Latin1_General_CI_AS NOT NULL,
        IDStato int NOT NULL,
        IDOperatore int NOT NULL,
        DataOra datetime2(0) NOT NULL CONSTRAINT DF_py_BarcodePickingListSkip_DataOra DEFAULT SYSDATETIME(),
        Motivo nvarchar(200) NULL,
        Risolto bit NOT NULL CONSTRAINT DF_py_BarcodePickingListSkip_Risolto DEFAULT 0,
        RisoltoDa int NULL,
        RisoltoDataOra datetime2(0) NULL
    );
END;
GO

IF NOT EXISTS (
    SELECT 1
    FROM sys.indexes
    WHERE name = N'UX_py_BarcodePickingListSkip_Open'
      AND object_id = OBJECT_ID(N'dbo.py_BarcodePickingListSkip', N'U')
)
BEGIN
    CREATE UNIQUE INDEX UX_py_BarcodePickingListSkip_Open
        ON dbo.py_BarcodePickingListSkip (Documento, Pallet, IDStato)
        WHERE Risolto = 0;
END;
GO

IF NOT EXISTS (
    SELECT 1
    FROM sys.indexes
    WHERE name = N'IX_py_BarcodePickingListSkip_Queue'
      AND object_id = OBJECT_ID(N'dbo.py_BarcodePickingListSkip', N'U')
)
BEGIN
    CREATE INDEX IX_py_BarcodePickingListSkip_Queue
        ON dbo.py_BarcodePickingListSkip (IDStato, Documento, Pallet, Risolto);
END;
GO

PRINT 'Patch cumulativa Python WMS completata.';
GO
