/****** Object: StoredProcedure [dbo].[stp_StatoProd_getByMacchina] Script Date: 02/05/2018 21:15:48 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /************************************* * STORED PROCEDURE stp_StatoProd_getByMacchina * recupera per la macchina indicata lo stato di produzione (pz Buoni / Scarto confermati e tot pezzi prod ad una specifica DataOra) * * modif.: S.E.L. * il: 2018.05.02 **************************************/ ALTER PROCEDURE [dbo].[stp_StatoProd_getByMacchina] ( @idxMacchina NVARCHAR(50) ,@DataOra DATETIME = NULL ) AS SET XACT_ABORT ON; BEGIN TRAN -- recupero ODL corrente... IF @DataOra IS NULL SET @DataOra = GETDATE() -- imposto valori accessori DECLARE @IdxODL INT = 0 DECLARE @DataInizioOdl DATETIME DECLARE @CodArticolo NVARCHAR(50) = 'ND' DECLARE @PzConfBuoni INT = 0 -- TOT Buoni GIA' confermati DECLARE @PzConfScarto INT = 0 -- TOT Scarti GIA' confermati DECLARE @PzRichODL INT = 0 -- Pezzi Richiesti x ODL DECLARE @PzTotODL INT = 0 -- Pezzi Prodotti x ODL fino a DataOra DECLARE @Pz2RecTot INT = 0 -- Pezzi Prodotti da confermare (TOT = BUONI + SCARTO) DECLARE @Pz2RecScarto INT = 0 -- Pezzi scarto registrati da confermare con produzione -- recupero da tab ODL il codice odl stesso e l'articolo data macchina e data/ora... SELECT @IdxODL = ISNULL(IdxODL,0), @CodArticolo = ISNULL(CodArticolo,'-'), @PzRichODL = NumPezzi, @DataInizioOdl = DataInizio FROM ODL WHERE IdxMacchina = @IdxMacchina AND DataInizio <= @DataOra AND ISNULL(DataFine, GETDATE()) >= @DataOra -- calcolo data ora ultima conferma DECLARE @lastConf AS DATETIME DECLARE @startProd AS DATETIME DECLARE @endProd AS DATETIME -- prendo le date di produzione... SET @startProd = (SELECT TOP 1 DataOraRif FROM dbo.TempiCicloRilevati WHERE IdxMacchina = @idxMacchina ORDER BY DataOraRif ASC) --SET @endProd = (SELECT TOP 1 DataOraRif FROM TempiCicloRilevati WHERE IdxMacchina = @idxMacchina ORDER BY DataOraRif DESC) SET @endProd = @DataOra --GETDATE() -- calcolo data! SET @lastConf = ISNULL((SELECT TOP 1 ISNULL(DataRif, @startProd) FROM dbo.DatiConfermati WHERE IdxMacchina = @idxMacchina ORDER BY DataRif DESC), @startProd) -- Per ogni ODL della macchina nel periodo controllo e aggiorno il CodArticolo -- x tutti i tempiciclo sottostanti ;WITH cteOdl AS -- ODL Macchina nel periodo ( SELECT IdxODL, CodArticolo, IdxMacchina, DataInizio, ISNULL(DataFine, @EndProd) AS DataFine, PzPallet FROM dbo.ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio <= @lastConf AND DataFine > @lastConf ) OR ( DataInizio <= @lastConf AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ) UPDATE dbo.TempiCicloRilevati SET CodArticolo = cteOdl.CodArticolo, PzProd = cteOdl.PzPallet, TCMedio = TCMedio * PzProd / cteOdl.PzPallet -- sistemo anche il tempo ciclo in base ai PzPallet FROM cteOdl INNER JOIN dbo.TempiCicloRilevati AS tc ON cteOdl.IdxMacchina = tc.IdxMacchina AND tc.DataOraRif >= cteOdl.DataInizio AND tc.DataOraRif <= cteOdl.DataFine WHERE cteOdl.CodArticolo <> tc.CodArticolo -- UPD solo se CodArticolo non corretto OR cteOdl.PzPallet <> tc.PzProd -- o PzProd -- recupero i dati GLOBALI confermati SELECT @PzConfBuoni = ISNULL(SUM(pezziConf),0), @PzConfScarto= ISNULL(SUM(pezziScar),0) FROM ElencoConfermeProd WHERE idxMacchina = @idxMacchina AND dataFrom >= @DataInizioOdl -- recupero i dati dei pezzi prodotti alla data richiesta SELECT @PzTotODL = ISNULL(SUM(PzProd),0) FROM dbo.TempiCicloRilevati WHERE IdxMacchina = @idxMacchina AND DataOraRif BETWEEN @DataInizioOdl AND @DataOra -- ora recupero gli scarti registrati ma NON confermati con produzione SELECT @Pz2RecScarto = ISNULL(SUM(Qta),0) FROM RegistroScarti WHERE IdxMacchina = @idxMacchina AND DataOra BETWEEN @lastConf AND @DataOra -- potrei mettere dalla data ora inizio ODL: @DataInizioOdl AND DataOraProdRec IS NULL -- calcolo NUOVI pezzi da confermare.... SELECT @Pz2RecTot = @PzTotODL - (@PzConfBuoni + @PzConfScarto) -- ora ritorno TUTTI i dati... SELECT @idxMacchina as idxMacchina ,ISNULL(@PzTotODL,0) AS PzTotODL ,ISNULL(@PzConfScarto,0) AS PzConfScarto ,ISNULL(@PzConfBuoni,0) AS PzConfBuoni ,ISNULL(@PzRichODL,0) AS PzRichODL ,ISNULL(@Pz2RecTot,0) AS Pz2RecTot ,ISNULL(@Pz2RecScarto,0) AS Pz2RecScarto ,@lastConf AS DataFrom ,@endProd AS DataTo COMMIT TRAN RETURN /****** Object: StoredProcedure [dbo].[stp_ConfermaProduzCompleta] Script Date: 02/05/2018 21:10:14 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /************************************* * STORED PROCEDURE stp_ConfermaProduzCompleta * * conferma la produzione per la macchina indicata salvando le informazioni nelle tabelle DatiProduzione e DatiConfermati * * * a) creo i periodi corretti con ODL * b) ciclo nei periodi x caricare dati confermati x periodo * c) Inserisco periodi che non sono coperti da ODL come 'T_OFF' * d) Confermo differenze * * * modif.: Steamware * modif: 2015.05.12 * modif: 2018.01.22 gestione Commessa Esterna e PezziDaRilav **************************************/ ALTER PROCEDURE [dbo].[stp_ConfermaProduzCompleta] ( @idxMacchina NVARCHAR(50), @MatrApp INT, @dataFrom DATETIME, @dataTo DATETIME, @pezziConf INT, @pezziScar INT = 0, -- pezzi scartati (registrati da 2016.11.20) DA INDICARE COME VALORE > 0!!! sennò faccio ABS... @TipoConf INT = 0, -- Tipo intervallo conferma: 0 = periodo intero, 1 = per giorni, 2 = per turni @DataOraApp DATETIME = NULL, -- di norma GETDATE() nel programma - serve per ricalcolo @TestConferma BIT = 1 -- TestConferma : 1 = verifica conf. duplicata e inserisci in ElencoConfermeProd, 0 = nessuna verifica e inserimento ( per ricalcolo ) ) AS BEGIN SET NOCOUNT ON; SET XACT_ABORT ON; DECLARE @CommessaEsterna AS NVARCHAR(50) = '' DECLARE @pezziDaRilav AS INT = 0; -- declare pz da rilav. da mettere poi nei parametri -- 2016.11.17 gestione SCARTI -- fix scarti: DA INDICARE COME VALORE > 0!!! sennò faccio ABS... SELECT @pezziScar = ABS(@pezziScar) -- DECLARE @DataOraApp AS DATETIME; IF @DataOraApp IS NULL SET @DataOraApp = GETDATE() -- salvo data elaborazione x tutte le sotto procedure -- IN PRIMIS CONTROLLO CHE NON CI SIA GIA' ALTRA CONFERMA x quella macchina entro ultimi 2 minuti (non permesso...) -- non faccio ISOLATION perchè solo un approvatore ( da Samuele ) IF NOT EXISTS ( -- se non trovata una conferma entro 2 minuti elaboro conferma SELECT DataOraConf FROM dbo.ElencoConfermeProd WHERE IdxMacchina = @idxMacchina AND DataOraConf >= DATEADD(mi,-2,GETDATE() ) ) OR @TestConferma = 0 BEGIN -- leggo dati ODL x Cod. Ordine esterno SELECT @CommessaEsterna=CommessaAs400 FROM dbo.ODL WHERE IdxMacchina=@IdxMacchina AND @DataTo BETWEEN DataInizio AND ISNULL(DataFine,'21990101') -- INSERISCO record della conferma se @TestConferma = 1 IF @TestConferma = 1 INSERT INTO dbo.ElencoConfermeProd ( DataOraConf, idxMacchina, MatrApp, dataFrom, dataTo, pezziConf, pezziScar, pezziDaRilav, CommessaEsterna, TipoConf ) SELECT @DataOraApp, @idxMacchina, @MatrApp, @dataFrom, @dataTo, @pezziConf, @pezziScar, @pezziDaRilav, @CommessaEsterna , @TipoConf DECLARE @NumPzConteggiati INT = 0 -- num pezzi che risultano dal conteggio automatico , @Periodi INT = 1 -- numero di periodi da confermare (1 solo, giornate, turni...) , @ShiftTurno INT = 6 -- shift turno (dalle 6.00) , @DurataTurno INT = 8 -- durata turno CREATE TABLE #Periodi ( RowNum INT NULL , IdxMacchina NVARCHAR(50) NULL , IdxODL INT NULL , DataFrom DATETIME NULL , DataTo DATETIME NULL , Turno INT NULL , PzProdNC INT NULL ) -- a) Creo la tabella dei periodi dove devo calcolare i tempi di produzione in base al tipo conferma ( giornata, turni ) -- Crea periodi solo dove è presente ODL -- ============================== -- conferma per PERIODO INTERO -- ============================== IF @TipoConf = 0 BEGIN SELECT @Periodi = 1 ;WITH cteODL AS -- prendo tutte ODL nel periodo ( SELECT IdxODL, CodArticolo, IdxMacchina, DataInizio, ISNULL(DataFine, DATEADD(dd,1,@dataTo)) AS DataFine FROM ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio < @dataTo AND DataFine > @dataFrom ) OR ( DataInizio < @dataTo AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ) -- inserisco 1 unica riga (periodo) per ogni ODL INSERT INTO #Periodi SELECT tbl.*, ISNULL(SUM(tcr.PzProd),0) as PzProdNC FROM ( SELECT ROW_NUMBER() OVER(ORDER BY cteODL.DataInizio ASC) AS Row , @idxMacchina as IdxMacchina , IdxOdl , CASE WHEN DataInizio < @dataFrom THEN @dataFrom ELSE DataInizio END as startDate , CASE WHEN @dataTo < DataFine THEN @dataTo ELSE DataFine END as endDate , 0 as Turno FROM cteODL WHERE IdxMacchina = @idxMacchina AND ((DataInizio BETWEEN @dataFrom AND @dataTo) OR (DataFine BETWEEN @dataFrom AND @dataTo)) ) as tbl LEFT OUTER JOIN TempiCicloRilevati tcr ON tbl.idxMacchina = tcr.idxMacchina and tcr.DataOraRif BETWEEN tbl.startDate and tbl.endDate GROUP BY tbl.Row, tbl.IdxMacchina, tbl.IdxODL, tbl.startDate, tbl.endDate, tbl.Turno ORDER BY tbl.startDate END -- ============================== -- conferma per GIORNATE comprese nell'intervallo del periodo (quindi parziale la prima e l'ultima se conferma NON effettuata alle 00.00) -- ============================== ELSE IF @TipoConf = 1 BEGIN SELECT @Periodi = DATEDIFF(DD, @dataFrom, @dataTo) --+ 1 -- aggiungo 1 perché conteggia le DATE PIENE e voglio avere sia primo che ultimo gg... ;WITH ctePrd AS ( SELECT CASE WHEN @dataFrom > DATEADD(DD,n,dbo.f_dateOnly(@dataFrom)) THEN @dataFrom ELSE DATEADD(DD,n,dbo.f_dateOnly(@dataFrom)) END as DtFrom ,CASE WHEN @dataTo < DATEADD(DD,n+1,dbo.f_dateOnly(@dataFrom)) THEN @dataTo ELSE DATEADD(DD,n+1,dbo.f_dateOnly(@dataFrom)) END as DtTo FROM TallyTable WHERE n <= @Periodi ), cteODL AS ( SELECT IdxODL, CodArticolo, IdxMacchina, DataInizio, ISNULL(DataFine, DATEADD(dd,1,@dataTo)) as DataFine FROM ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio < @dataTo AND DataFine > @dataFrom ) OR ( DataInizio < @dataTo AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ) -- ciclo nei periodi (GIORNI) ed inserisco @Periodi righe di periodo... INSERT INTO #Periodi SELECT tbl.*, ISNULL(SUM(tcr.PzProd),0) as PzProdNC FROM ( SELECT ROW_NUMBER() OVER(ORDER BY cteODL.DataInizio ASC) AS Row , @idxMacchina as idxMacchina , IdxOdl , CASE WHEN DataInizio < DtFrom THEN DtFrom ELSE DataInizio END as startDate , CASE WHEN DtTo < DataFine THEN DtTo ELSE DataFine END as endDate , 0 as Turno FROM ctePrd CROSS JOIN cteODL -- CROSS JOIN della produttoria tra ODL del giorno e giorni disponibili WHERE IdxMacchina = @idxMacchina AND ( (DataInizio BETWEEN DtFrom AND DtTo) OR (DataFine BETWEEN DtFrom AND DtTo) OR (DataInizio <= DtFrom AND DataFine >= DtTo) ) ) as tbl LEFT OUTER JOIN TempiCicloRilevati tcr ON tbl.idxMacchina = tcr.idxMacchina and tcr.DataOraRif BETWEEN tbl.startDate and tbl.endDate GROUP BY tbl.Row, tbl.IdxMacchina, tbl.IdxODL, tbl.startDate, tbl.endDate, tbl.Turno ORDER BY tbl.startDate END -- ============================== -- conferma per TURNI INTERI compresi nell'intervallo del periodo -- ============================== ELSE IF @TipoConf = 2 BEGIN SELECT @Periodi = CEILING(CAST(DATEDIFF(HH, @dataFrom, @dataTo) AS FLOAT) / @DurataTurno) + 1 ;WITH ctePrd AS ( SELECT CASE WHEN @dataFrom > DATEADD(HH,@DurataTurno*n+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) THEN @dataFrom ELSE DATEADD(HH,@DurataTurno*n+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) END as DtFrom ,CASE WHEN @dataTo < DATEADD(HH,@DurataTurno*(n+1)+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) THEN @dataTo ELSE DATEADD(HH,@DurataTurno*(n+1)+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) END as DtTo FROM TallyTable WHERE n <= @Periodi ), cteODL AS ( SELECT IdxODL, CodArticolo, IdxMacchina, DataInizio, ISNULL(DataFine, DATEADD(dd,1,@dataTo)) as DataFine FROM ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio < @dataTo AND DataFine > @dataFrom ) OR ( DataInizio < @dataTo AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ) -- ciclo nei periodi (TURNI) ed inserisco @Periodi righe di periodo... INSERT INTO #Periodi SELECT tbl.*, ISNULL(SUM(tcr.PzProd),0) as PzProdNC FROM ( SELECT ROW_NUMBER() OVER(ORDER BY cteODL.DataInizio ASC) AS Row , @idxMacchina AS idxMacchina , IdxOdl , CASE WHEN DataInizio < DtFrom THEN DtFrom ELSE DataInizio END as startDate , CASE WHEN DtTo < DataFine THEN DtTo ELSE DataFine END as endDate , CEILING((DATEPART(HH,CASE WHEN DataInizio < DtFrom THEN DtFrom ELSE DataInizio END)-@ShiftTurno)/@DurataTurno) + 1 as turno FROM ctePrd CROSS JOIN cteODL -- CROSS JOIN della produttoria tra ODL del turno e turni disponibili WHERE IdxMacchina = @idxMacchina AND ( (DataInizio BETWEEN DtFrom AND DtTo) OR (DataFine BETWEEN DtFrom AND DtTo) OR (DataInizio <= DtFrom AND DataFine >= DtTo) ) ) as tbl LEFT OUTER JOIN TempiCicloRilevati tcr ON tbl.idxMacchina = tcr.idxMacchina and tcr.DataOraRif BETWEEN tbl.startDate and tbl.endDate GROUP BY tbl.Row, tbl.IdxMacchina, tbl.IdxODL, tbl.startDate, tbl.endDate, tbl.Turno ORDER BY tbl.startDate END SELECT * FROM #Periodi -- ================================================================ --#region b) -- per ogni PERIODO ho TUTTI gli ODL intersecati: faccio ciclo!!!! -- ================================================================ DECLARE @idxOdl INT ,@Inizio DATETIME ,@Fine DATETIME ,@DataRif DATETIME ,@Turno INT ,@PzProd INT ,@PzProdTot INT ,@IdxStatoP INT = 13 -- HARD CODED!!!! ,@deltaPz INT = 0 -- inizializzo DECLARE @imax INT, @i INT SELECT @imax = COUNT(*) FROM #Periodi SET @i = 1 WHILE (@i <= @imax) BEGIN SELECT @idxOdl = IdxODL , @Inizio = DataFrom , @Fine = DataTo , @DataRif = dbo.f_dateOnly(DataFrom) , @Turno = Turno , @PzProd = PzProdNC FROM #Periodi WHERE RowNum = @i -- SELECT * FROM #Periodi WHERE RowNum = @i IF @Inizio < @Fine -- se Iniz <> Fine e il periodo è coerente BEGIN -- approvo num pz non confermati x gli ODL: EXEC dbo.stp_DatiConf_conferma @idxOdl, @idxMacchina, @MatrApp, @Inizio, @Fine, @Turno, @IdxStatoP, @PzProd, 0, @DataOraApp --select 'stp_DatiConf_conferma' as stp, @idxOdl, @idxMacchina, @MatrApp, @Inizio, @Fine, @Turno, @IdxStatoP, @PzProd -- confermo i tempi splittati: stp_DatiProd_insAllPeriodo EXEC dbo.stp_DatiProd_insAllPeriodo @idxMacchina, @Inizio, @Fine, @DataRif, @Turno, @MatrApp, @DataOraApp --select 'stp_DatiProd_insAllPeriodo' as stp, @idxMacchina, @Inizio, @Fine, @DataRif, @Turno, @MatrApp END SET @i = @i + 1 END -- WHILE --#endregion -- ============================== -- c) CARICO PERIODI SENZA ODL in in DatiProduzione come 'T_OFF' -- ============================== DECLARE @ClasseTempo NVARCHAR(50); DECLARE @DataFirstODL AS DATETIME = '21000101' SET @ClasseTempo = 'T_OFF'; SELECT @DataFirstODL = MIN(DataInizio) FROM dbo.ODL WHERE IdxMacchina = @IdxMacchina IF @TipoConf = 0 BEGIN -- *** DA COMPLETARE SET @ClasseTempo = @ClasseTempo; END -- ============================== -- periodi senza ODL per GIORNATA INTERA -- ============================== ELSE IF @TipoConf = 1 BEGIN ;WITH ctePrd AS -- elenco periodi ( SELECT CASE WHEN @dataFrom > DATEADD(DD,n,dbo.f_dateOnly(@dataFrom)) THEN @dataFrom ELSE DATEADD(DD,n,dbo.f_dateOnly(@dataFrom)) END as DtFrom ,CASE WHEN @dataTo < DATEADD(DD,n+1,dbo.f_dateOnly(@dataFrom)) THEN @dataTo ELSE DATEADD(DD,n+1,dbo.f_dateOnly(@dataFrom)) END as DtTo FROM TallyTable WHERE n <= @Periodi ),cteODLAll AS -- creo periodi ODL + ODL fittizio inizio nel caso non trovi ODL nel periodo ( SELECT 0 AS IdxODL, @IdxMacchina AS IdxMacchina, @dataFrom-1000 AS DataInizio, @dataFrom AS DataFine WHERE @DataFirstODL < @dataFrom -- se il periodo è precedente alla prima ODL non lo considero UNION SELECT IdxODL, IdxMacchina, DataInizio, ISNULL( DataFine, DATEADD(dd,1,@dataTo) ) as DataFine FROM dbo.ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio < @dataTo AND DataFine > @dataFrom ) OR ( DataInizio < @dataTo AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ),cteODL AS ( SELECT ROW_NUMBER() OVER( ORDER BY DataInizio ASC) AS RowNum, IdxODL, IdxMacchina, DataInizio, DataFine FROM cteODLAll ) ,cteNoODL AS -- periodi macchina senza ODL ( SELECT DISTINCT P1.IdxMacchina, P1.DataFine AS DataInizio, ISNULL(P2.DataInizio, @DataTo ) AS DataFine -- , p2.DataInizio as dt2,p2.DataFine as dt3 FROM cteODL AS P1 LEFT JOIN cteODL AS P2 ON P1.RowNum + 1 = P2.RowNum -- aggancio a riga successiva WHERE DATEDIFF( MINUTE, P1.DataFine, ISNULL( P2.DataInizio , @DataTo ) ) > 5 -- solo se diff è positiva e > 5 minuti ) INSERT INTO dbo.DatiProduzione( IdxODL, DataOraApp, DataRif, TurnoRif, CodArticolo, IdxMacchina, TCAssegnato, MatrOpr, MatrApp, DataOraFrom, DataOraTo, TotPzProd, Tempo, ClasseTempo, Causale) SELECT 0 AS idxODL, @DataOraApp, dbo.f_dateOnly(tbl.startDate) AS DataRif, turno, '' AS CodArticolo, idxMacchina, 0 AS TC, @MatrApp, @MatrApp ,startDate, endDate, 0 AS pz, CAST(ISNULL(DATEDIFF(n, startDate, endDate) ,0) AS DECIMAL(18,8)) / 60 AS Tempo , @ClasseTempo, @ClasseTempo FROM ( SELECT DISTINCT idxMacchina , CASE WHEN DataInizio < DtFrom THEN DtFrom ELSE DataInizio END AS startDate , CASE WHEN DtTo < DataFine THEN DtTo ELSE DataFine END AS endDate , 0 AS Turno FROM ctePrd CROSS JOIN cteNoODL -- CROSS JOIN della produttoria tra NoODL del giorno e giorni disponibili WHERE ( ( DataInizio BETWEEN DtFrom AND DtTo ) OR ( DataFine BETWEEN DtFrom AND DtTo ) OR ( DataInizio <= DtFrom AND DataFine >= DtTo ) ) ) AS tbl WHERE startDate < endDate END -- ============================== -- periodi senza ODL per TURNI nell'intervallo del periodo -- ============================== ELSE IF @TipoConf = 2 BEGIN ;WITH ctePrd AS ( SELECT CASE WHEN @dataFrom > DATEADD(HH,@DurataTurno*n+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) THEN @dataFrom ELSE DATEADD(HH,@DurataTurno*n+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) END as DtFrom ,CASE WHEN @dataTo < DATEADD(HH,@DurataTurno*(n+1)+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) THEN @dataTo ELSE DATEADD(HH,@DurataTurno*(n+1)+@ShiftTurno,dbo.f_dateOnly(@dataFrom)) END as DtTo FROM TallyTable WHERE n <= @Periodi ),cteODLAll AS -- creo periodi ODL + ODL fittizio inizio nel caso non trovi ODL nel periodo ( SELECT 0 AS IdxODL, @IdxMacchina AS IdxMacchina, @dataFrom-1000 AS DataInizio, @dataFrom AS DataFine WHERE @DataFirstODL < @dataFrom -- se il periodo è precedente alla prima ODL non lo considero UNION SELECT IdxODL, IdxMacchina, DataInizio, ISNULL( DataFine, DATEADD(dd,1,@dataTo) ) as DataFine FROM dbo.ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio < @dataTo AND DataFine > @dataFrom ) OR ( DataInizio < @dataTo AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ),cteODL AS ( SELECT ROW_NUMBER() OVER( ORDER BY DataInizio ASC) AS RowNum, IdxODL, IdxMacchina, DataInizio, DataFine FROM cteODLAll ) ,cteNoODL AS -- periodi macchina senza ODL ( SELECT DISTINCT P1.IdxMacchina, P1.DataFine AS DataInizio, ISNULL(P2.DataInizio, @DataTo ) AS DataFine -- , p2.DataInizio as dt2,p2.DataFine as dt3 FROM cteODL AS P1 LEFT JOIN cteODL AS P2 ON P1.RowNum + 1 = P2.RowNum -- aggancio a riga successiva WHERE DATEDIFF( MINUTE, P1.DataFine, ISNULL( P2.DataInizio , @DataTo ) ) > 5 -- solo se diff è positiva e > 5 minuti ) INSERT INTO dbo.DatiProduzione( IdxODL, DataOraApp, DataRif, TurnoRif, CodArticolo, IdxMacchina, TCAssegnato, MatrOpr, MatrApp, DataOraFrom, DataOraTo, TotPzProd, Tempo, ClasseTempo, Causale) SELECT 0 AS idxODL, @DataOraApp, dbo.f_dateOnly(tbl.startDate) AS DataRif, turno, '' AS CodArticolo, idxMacchina, 0 AS TC, @MatrApp, @MatrApp ,startDate, endDate, 0 AS pz, CAST(ISNULL(DATEDIFF(n, startDate, endDate) ,0) AS DECIMAL(18,8)) / 60 AS Tempo , @ClasseTempo, @ClasseTempo FROM ( SELECT DISTINCT -- ROW_NUMBER() OVER( ORDER BY cteNoODL.DataInizio ASC) AS RowNum, idxMacchina , CASE WHEN DataInizio < DtFrom THEN DtFrom ELSE DataInizio END as startDate , CASE WHEN DtTo < DataFine THEN DtTo ELSE DataFine END as endDate , CEILING((DATEPART(HH,CASE WHEN DataInizio < DtFrom THEN DtFrom ELSE DataInizio END)-@ShiftTurno)/@DurataTurno) + 1 as turno FROM ctePrd CROSS JOIN cteNoODL -- CROSS JOIN della produttoria tra NoODL del giorno e giorni disponibili WHERE ( ( DataInizio BETWEEN DtFrom AND DtTo ) OR ( DataFine BETWEEN DtFrom AND DtTo ) OR ( DataInizio <= DtFrom AND DataFine >= DtTo ) ) ) AS tbl WHERE startDate < endDate END -- =============================== -- d) INFINE CONFERMO DIFFERENZE -- =============================== -- infine confermo differenze: SELECT @PzProdTot = ISNULL(SUM(TotPzProd),0) FROM dbo.DatiProduzione WHERE IdxMacchina = @idxMacchina AND DataOraFrom >= @dataFrom AND DataOraTo <= @dataTo AND Causale <> 'T_CorrProd' -- escludo cmq le correzioni di produzione ---- Fino al 2015-05-08 --SELECT @PzProdTot = ISNULL(SUM(tcr.PzProd),0) --FROM dbo.TempiCicloRilevati tcr --WHERE tcr.DataOraRif BETWEEN @dataFrom AND @dataTo -- AND IdxMacchina = @idxMacchina -- 2016.11.17 gestione SCARTI -- update x DatiConf: (TUTTO SU ULTIMO ODL... e su adesso) AL NETTO DEGLI SCARTI SELECT @DataRif = @dataTo SELECT @deltaPz = @pezziConf - (@PzProdTot - @pezziScar) IF @idxOdl IS NOT NULL BEGIN -- inverto valore scarti (come negativo) SELECT @pezziScar = - ABS(@pezziScar) EXEC dbo.stp_DatiConf_conferma @idxOdl, @idxMacchina, @MatrApp, @DataRif, @DataRif, 1, @IdxStatoP, @deltaPz, @pezziScar, @DataOraApp --select 'stp_DatiConf_conferma' as stp, @idxOdl, @idxMacchina, @MatrApp, @DataRif, @DataRif, 1, @IdxStatoP, @deltaPz, @pezziScar, @DataOraApp ---- inserisco scartid: (TUTTO SU ULTIMO ODL... e su adesso) EXEC dbo.stp_DatiProd_insert @idxOdl, @idxMacchina, @MatrApp, @DataRif, @DataRif, 1, @pezziScar, 0, 'T_Scarto', @DataOraApp --select 'stp_DatiProd_insert' as stp, @idxOdl, @idxMacchina, @MatrApp, @DataRif, @DataRif, 1, @pezziScar, 0, 'T_Scarto', @DataOraApp ---- update per DatiProd: (TUTTO SU ULTIMO ODL... e su adesso) EXEC dbo.stp_DatiProd_insert @idxOdl, @idxMacchina, @MatrApp, @DataRif, @DataRif, 1, @deltaPz, 0, 'T_CorrProd', @DataOraApp --select 'stp_DatiProd_insert' as stp, @idxOdl, @idxMacchina, @MatrApp, @DataRif, @DataRif, 1, @deltaPz, 0, 'T_CorrProd', @DataOraApp END -- 2018.05.02: ora registro gli scarti come acquisiti... EXEC dbo.stp_RS_recProd @idxMacchina, @dataTo END END /****** Object: StoredProcedure [dbo].[stp_StatoProd_getByMacchina] Script Date: 02/05/2018 22:40:33 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /************************************* * STORED PROCEDURE stp_StatoProd_getByMacchina * recupera per la macchina indicata lo stato di produzione (pz Buoni / Scarto confermati e tot pezzi prod ad una specifica DataOra) * * modif.: S.E.L. * il: 2018.05.02 **************************************/ ALTER PROCEDURE [dbo].[stp_StatoProd_getByMacchina] ( @idxMacchina NVARCHAR(50) ,@DataOra DATETIME = NULL ) AS SET XACT_ABORT ON; BEGIN TRAN -- in primis: se dataora > adesso rimetto adesso SET @DataOra = CASE WHEN ISNULL(@DataOra,GETDATE()) >= GETDATE() THEN GETDATE() ELSE @DataOra END -- imposto valori accessori DECLARE @IdxODL INT = 0 DECLARE @DataInizioOdl DATETIME DECLARE @CodArticolo NVARCHAR(50) = 'ND' DECLARE @PzConfBuoni INT = 0 -- TOT Buoni GIA' confermati DECLARE @PzConfScarto INT = 0 -- TOT Scarti GIA' confermati DECLARE @PzRichODL INT = 0 -- Pezzi Richiesti x ODL DECLARE @PzTotODL INT = 0 -- Pezzi Prodotti x ODL fino a DataOra DECLARE @Pz2RecTot INT = 0 -- Pezzi Prodotti da confermare (TOT = BUONI + SCARTO) DECLARE @Pz2RecScarto INT = 0 -- Pezzi scarto registrati da confermare con produzione -- recupero da tab ODL il codice odl stesso e l'articolo data macchina e data/ora... SELECT @IdxODL = ISNULL(IdxODL,0), @CodArticolo = ISNULL(CodArticolo,'-'), @PzRichODL = NumPezzi, @DataInizioOdl = DataInizio FROM ODL WHERE IdxMacchina = @IdxMacchina AND DataInizio <= @DataOra AND ISNULL(DataFine, GETDATE()) >= @DataOra -- calcolo data ora ultima conferma DECLARE @lastConf AS DATETIME DECLARE @startProd AS DATETIME DECLARE @endProd AS DATETIME -- prendo le date di produzione... SET @startProd = (SELECT TOP 1 DataOraRif FROM dbo.TempiCicloRilevati WHERE IdxMacchina = @idxMacchina ORDER BY DataOraRif ASC) --SET @endProd = (SELECT TOP 1 DataOraRif FROM TempiCicloRilevati WHERE IdxMacchina = @idxMacchina ORDER BY DataOraRif DESC) SET @endProd = @DataOra --GETDATE() -- calcolo data! SET @lastConf = ISNULL((SELECT TOP 1 ISNULL(DataRif, @startProd) FROM dbo.DatiConfermati WHERE IdxMacchina = @idxMacchina ORDER BY DataRif DESC), @startProd) -- Per ogni ODL della macchina nel periodo controllo e aggiorno il CodArticolo -- x tutti i tempiciclo sottostanti ;WITH cteOdl AS -- ODL Macchina nel periodo ( SELECT IdxODL, CodArticolo, IdxMacchina, DataInizio, ISNULL(DataFine, @EndProd) AS DataFine, PzPallet FROM dbo.ODL WHERE IdxMacchina = @idxMacchina AND ( ( DataInizio <= @lastConf AND DataFine > @lastConf ) OR ( DataInizio <= @lastConf AND DataFine IS NULL ) ) -- includo Odl non chiuse solo se nel periodo richiesto ) UPDATE dbo.TempiCicloRilevati SET CodArticolo = cteOdl.CodArticolo, PzProd = cteOdl.PzPallet, TCMedio = TCMedio * PzProd / cteOdl.PzPallet -- sistemo anche il tempo ciclo in base ai PzPallet FROM cteOdl INNER JOIN dbo.TempiCicloRilevati AS tc ON cteOdl.IdxMacchina = tc.IdxMacchina AND tc.DataOraRif >= cteOdl.DataInizio AND tc.DataOraRif <= cteOdl.DataFine WHERE cteOdl.CodArticolo <> tc.CodArticolo -- UPD solo se CodArticolo non corretto OR cteOdl.PzPallet <> tc.PzProd -- o PzProd -- recupero i dati GLOBALI confermati SELECT @PzConfBuoni = ISNULL(SUM(pezziConf),0), @PzConfScarto= ISNULL(SUM(pezziScar),0) FROM ElencoConfermeProd WHERE idxMacchina = @idxMacchina AND dataFrom >= @DataInizioOdl -- recupero i dati dei pezzi prodotti alla data richiesta SELECT @PzTotODL = ISNULL(SUM(PzProd),0) FROM dbo.TempiCicloRilevati WHERE IdxMacchina = @idxMacchina AND DataOraRif BETWEEN @DataInizioOdl AND @DataOra -- ora recupero gli scarti registrati ma NON confermati con produzione SELECT @Pz2RecScarto = ISNULL(SUM(Qta),0) FROM RegistroScarti WHERE IdxMacchina = @idxMacchina AND DataOra BETWEEN @lastConf AND @DataOra -- potrei mettere dalla data ora inizio ODL: @DataInizioOdl AND DataOraProdRec IS NULL -- calcolo NUOVI pezzi da confermare.... SELECT @Pz2RecTot = @PzTotODL - (@PzConfBuoni + @PzConfScarto) -- ora ritorno TUTTI i dati... SELECT @idxMacchina as idxMacchina ,ISNULL(@PzTotODL,0) AS PzTotODL ,ISNULL(@PzConfScarto,0) AS PzConfScarto ,ISNULL(@PzConfBuoni,0) AS PzConfBuoni ,ISNULL(@PzRichODL,0) AS PzRichODL ,ISNULL(@Pz2RecTot,0) AS Pz2RecTot ,ISNULL(@Pz2RecScarto,0) AS Pz2RecScarto ,@lastConf AS DataFrom ,@endProd AS DataTo COMMIT TRAN RETURN