using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MP.Data.DbModels; using MP.Data.DbModels.Anag; using NLog; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; using static MP.Core.Objects.Enums; namespace MP.Data.Controllers { public class MpIocController { #region Public Constructors public MpIocController(IConfiguration configuration) { _configuration = configuration; string connStr = _configuration.GetConnectionString("MP.Data"); options = new DbContextOptionsBuilder() .UseSqlServer(connStr) .Options; Log.Info("Avviata classe MpIocController"); } #endregion Public Constructors #region Public Methods /// /// Insert record allarme /// /// Data evento /// Id macchina /// area memoria /// indice memoria /// valore status /// valore decodificato /// public async Task AlarmLogInsertAsync(DateTime dtRif, string machineId, string memAddress, int memIndex, int statusVal, string valDecoded) { using var dbCtx = new MoonProContext(options); var DtRif = new SqlParameter("@DtRif", dtRif); var MachineId = new SqlParameter("@MachineId", machineId); var MemAddress = new SqlParameter("@MemAddress", memAddress); var MemIndex = new SqlParameter("@MemIndex", memIndex); var StatusVal = new SqlParameter("@StatusVal", statusVal); var ValDecoded = new SqlParameter("@ValDecoded", valDecoded); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_AL_insertQuery @DtRif, @MachineId, @MemAddress, @MemIndex, @StatusVal, @ValDecoded, ", DtRif, MachineId, MemAddress, MemIndex, StatusVal, ValDecoded); return result != 0; ; } /// /// Restituisce l'anagrafica STATI per intero /// /// public async Task> AnagStatiGetAllAsync() { using var dbCtx = new MoonProContext(options); var dbResult = await dbCtx .DbSetAnagStati .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Restitusice elenco ultimi articoli per macchina /// /// /// /// /// public async Task> ArticoliGetLastByMaccAsync(string idxMacc) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var dbResult = await dbCtx .DbSetArticoli .FromSqlRaw("exec dbo.stp_ART_getLastByMacch @idxMacchina", IdxMacchina) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Apre in automatico un nuovo PODL/ODL chiudendo l'attuale (aperto) /// /// Idx ODL corrente /// Matricola operatore /// idx macchina da confermare /// TempoCiclo richiesto in attrezzaggio /// # pz pallet /// note ODL /// bool per avvio nuovo ODL (def: true) /// Qty da produrre, deve essere >0 /// KeyRich esterno, se vuoto uso vecchia, se KIT sovrascritto con KeyKit /// public async Task AutoStartOdlAsync(int idxOdl, int MatrOpr, string idxMacchina, decimal tCRich, int pzPallet, string note, bool startNewOdl, int qtyRich, string keyRich) { using var dbCtx = new MoonProContext(options); var IdxOdl = new SqlParameter("@idxOdl ", idxOdl); var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); var TCRich = new SqlParameter("@TCRichAttr", tCRich); var PzPallet = new SqlParameter("@PzPallet", pzPallet); var Note = new SqlParameter("@Note", note); var StartNewOdl = new SqlParameter("@StartNewOdl", startNewOdl); var QtyRich = new SqlParameter("@QtyRich", qtyRich); var KeyRichiesta = new SqlParameter("@KeyRichiesta", keyRich); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ODL_AutoStart @idxOdl, @MatrApp, @idxMacchina, @TCRichAttr, @PzPallet, @Note, @StartNewOdl, @QtyRich, @KeyRichiesta", IdxOdl, MatrApp, IdxMacchina, TCRich, PzPallet, Note, StartNewOdl, QtyRich, KeyRichiesta); return result != 0; } /// /// Processing intera catena eventi verifica cambio stato in singola transazione e con unico DbContext /// /// /// /// /// /// /// /// /// /// public async Task CheckCambiaStatoBatchAsync(tipoInputEvento tipoInput, string IdxMacchina, DateTime InizioStato, int IdxTipo, string CodArt, string Value, int MatrOpr, string pallet) { await using var dbCtx = new MoonProContext(options); //await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { var pIdxMacchina = new SqlParameter("@IdxMacchina", IdxMacchina); var pIdxTipo = new SqlParameter("@IdxTipo", IdxTipo); var pInizioStato = new SqlParameter("@InizioStato", InizioStato); var pCodArticolo = new SqlParameter("@codArticolo", CodArt); var pValue = new SqlParameter("@Value", Value); var pMatrOpr = new SqlParameter("@MatrOpr", MatrOpr); var pPallet = new SqlParameter("@pallet", pallet); string opType = tipoInput switch { tipoInputEvento.barcode => "BARCODE", tipoInputEvento.hw => "HW", _ => "ND" }; TransizioneStatiModel? rigaTrans = null; if (opType != "ND") { string sql = tipoInput switch { tipoInputEvento.barcode => "EXEC dbo.stp_TS_getUserForcedTrans @IdxMacchina, @IdxTipo", tipoInputEvento.hw => "EXEC dbo.stp_TS_getByIdxMacchIdxTipoEv @IdxMacchina, @IdxTipo", _ => string.Empty }; // ✅ prima chiamata ASYNC rigaTrans = (await dbCtx.DbSetSMES .FromSqlRaw(sql, pIdxMacchina, pIdxTipo) .AsNoTracking() .ToListAsync() ).FirstOrDefault(); } if (rigaTrans != null && rigaTrans.IdxStato != rigaTrans.next_IdxStato) { var pIdxStato = new SqlParameter("@IdxStato", rigaTrans.next_IdxStato); await dbCtx.Database.ExecuteSqlRawAsync( "EXEC dbo.stp_DDB_InsStatoBatch @IdxMacchina, @InizioStato, @IdxStato, @codArticolo, @Value, @MatrOpr, @pallet", pIdxMacchina, pInizioStato, pIdxStato, pCodArticolo, pValue, pMatrOpr, pPallet); // eseguo solo se evento manuale/barcode if (tipoInput == tipoInputEvento.barcode) { var pMaxAgeSec = new SqlParameter("@maxAgeSec", 0); await dbCtx.Database.ExecuteSqlRawAsync( "EXEC stp_MSE_recalc @maxAgeSec, @idxMacchina", pMaxAgeSec, pIdxMacchina); } } else { Log.Debug($"Nessun cambio stato richiesto | {opType} | {IdxMacchina} | {IdxTipo}"); } // Nessuna eccezione = successo //await tx.CommitAsync(); return true; } catch (Exception ex) { //await tx.RollbackAsync(); // Log dettagliato errore Log.Error(ex, $"Errore in CheckCambiaStatoBatchAsync: {IdxMacchina} | {tipoInput}"); throw; // O return false; se il chiamante gestisce fallimenti } } /// /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma - dtEvent) /// /// idx macchina da confermare /// 0=periodo, 1 = giorno, 2 = turno /// qta pezzi BUONI da confermare /// qta pezzi SCARTO da confermare /// DataOra in cui registrare approvazione /// Matricola operatore /// public async Task ConfermaProdMacchinaAsync(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzScarto, DateTime DataOraApp, int MatrOpr) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataOra = new SqlParameter("@DataOra ", DateTime.Now); var rigaProd = (await dbCtx .DbSetStatoProd .FromSqlRaw("EXEC stp_StatoProd_getByMacchina @IdxMacchina, @DataOra ", IdxMacchina, DataOra) .AsNoTracking() .ToListAsync()) .FirstOrDefault(); //var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); //var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); var DataFrom = new SqlParameter("@dataFrom ", rigaProd.DataFrom); var DataTo = new SqlParameter("@dataTo", DataOraApp); var PezziConf = new SqlParameter("@pezziConf", numPzConfermati); var PezziScar = new SqlParameter("@pezziScar", numPzScarto); var TipoConf = new SqlParameter("@TipoConf", modoConfProd); var DtOraApp = new SqlParameter("@DataOraApp", DataOraApp); var TestConferma = new SqlParameter("@TestConferma", true); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ConfermaProduzCompleta @idxMacchina, @MatrApp, @dataFrom, @dataTo, @pezziConf, @pezziScar, @TipoConf, @DataOraApp, @TestConferma ", IdxMacchina, MatrApp, DataFrom, DataTo, PezziConf, PezziScar, TipoConf, DtOraApp, TestConferma); return result != 0; } /// /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma - dtEvent) /// /// idx macchina da confermare /// 0=periodo, 1 = giorno, 2 = turno /// qta pezzi BUONI da confermare /// qta pezzi LASCIATI da confermare /// qta pezzi SCARTO da confermare /// DataOra in cui registrare approvazione /// Matricola operatore /// public async Task ConfermaProdMacchinaFullAsync(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzLasciati, int numPzScarto, DateTime DataOraApp, int MatrOpr) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataOra = new SqlParameter("@DataOra ", DateTime.Now); var rigaProd = (await dbCtx .DbSetStatoProd .FromSqlRaw("EXEC stp_StatoProd_getByMacchina @IdxMacchina, @DataOra ", IdxMacchina, DataOra) .AsNoTracking() .ToListAsync()) .FirstOrDefault(); //var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); //var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); var DataFrom = new SqlParameter("@dataFrom ", rigaProd.DataFrom); var DataTo = new SqlParameter("@dataTo", DataOraApp); var PezziConf = new SqlParameter("@pezziConf", numPzConfermati); var PezziLasc = new SqlParameter("@pezziLasciati", numPzLasciati); var PezziScar = new SqlParameter("@pezziScar", numPzScarto); var TipoConf = new SqlParameter("@TipoConf", modoConfProd); var DtOraApp = new SqlParameter("@DataOraApp", DataOraApp); var TestConferma = new SqlParameter("@TestConferma", true); var Force = new SqlParameter("@Force", false); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ConfermaProduzCompletaFull @idxMacchina, @MatrApp, @dataFrom, @dataTo, @pezziConf, @pezziLasciati, @pezziScar, @TipoConf, @DataOraApp, @TestConferma,@Force", IdxMacchina, MatrApp, DataFrom, DataTo, PezziConf, PezziLasc, PezziScar, TipoConf, DtOraApp, TestConferma, Force); return result != 0; } /// /// Record ConfFlux dato macchina (oppure tutti se vuoto) /// /// /// public async Task> ConfFluxFiltAsync(string idxMacc) { using var dbCtx = new MoonPro_FluxContext(_configuration); var query = dbCtx.DbSetConfFlux .AsNoTracking() .AsQueryable(); if (!string.IsNullOrEmpty(idxMacc)) query = query.Where(x => x.IdxMacchina == idxMacc); var dbResult = await query.ToListAsync(); return dbResult; } /// /// Elenco da tabella Config /// /// public async Task> ConfigGetAllAsync() { using var dbCtx = new MoonProContext(options); var dbResult = await dbCtx .DbSetConfig .AsNoTracking() .OrderBy(x => x.Chiave) .ToListAsync(); return dbResult; } /// /// Update record config /// /// public async Task ConfigUpdateAsync(ConfigModel updRec) { using var dbCtx = new MoonProContext(options); bool fatto = false; var dbResult = dbCtx .DbSetConfig .Where(x => x.Chiave == updRec.Chiave) .FirstOrDefault(); if (dbResult != null) { dbResult.Valore = updRec.Valore; fatto = dbCtx.SaveChanges() > 0; } return fatto; } /// /// Intera tab dati macchina /// /// public async Task> DatiMacchineGetAllAsync() { using var dbCtx = new MoonProContext(options); var dbResult = await dbCtx .DbSetDatiMacchine .AsNoTracking() .OrderBy(x => x.IdxMacchina) .ToListAsync(); return dbResult; } /// /// Inserimento record in DDB /// /// /// /// /// /// /// /// /// public async Task DDB_InsStatoBatchAsync(string idxMacchina, DateTime inizioStato, int idxStato, string codArt, string value, int matrOpr, string pallet) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var InizioStato = new SqlParameter("@InizioStato", inizioStato); var IdxStato = new SqlParameter("@IdxStato", idxStato); var CodArticolo = new SqlParameter("@codArticolo", codArt); var Value = new SqlParameter("@Value", value); var MatrOpr = new SqlParameter("@MatrOpr", matrOpr); var Pallet = new SqlParameter("@pallet", pallet); var result = await dbCtx .Database .ExecuteSqlRawAsync("exec dbo.stp_DDB_InsStatoBatch @IdxMacchina, @InizioStato, @IdxStato, @codArticolo, @Value, @MatrOpr, @pallet", IdxMacchina, InizioStato, IdxStato, CodArticolo, Value, MatrOpr, Pallet); return result > 0; } /// /// Elenco tabella decodifica articoli / codice decimale /// /// Vuoto = tutti / Singolo CodArt /// public async Task> DecNumArtGetFiltAsync(string codArt = "") { using var dbCtx = new MoonProContext(options); var query = dbCtx.DbSetDecNumArt .AsNoTracking() .AsQueryable(); if (!string.IsNullOrEmpty(codArt)) query = query.Where(x => x.CodArticolo == codArt); var dbResult = await query.ToListAsync(); return dbResult; } /// /// Stored x recuperare ultimi dossier macchina /// /// /// public async Task> DossGetLastByMaccAsync(string idxMacc) { List dbResult = new(); using (var dbCtx = new MoonPro_FluxContext(_configuration)) { var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); dbResult = await dbCtx .DbSetDossiers .FromSqlRaw("exec dbo.stp_DOSS_getLastByMacch @idxMacchina", IdxMacchina) .AsNoTracking() .ToListAsync(); } return dbResult; } /// /// Aggiunta record EventList /// /// /// public async Task EvListInsertAsync(EventListModel newRec) { using var dbCtx = new MoonProContext(options); dbCtx.DbSetEvList.Add(newRec); return await dbCtx.SaveChangesAsync() > 0; } /// /// Aggiunta record MicroStato + EventList /// /// /// /// public async Task EvListMicroStatoInsertAsync(MicroStatoMacchinaModel newRecMsm, EventListModel newRecEv) { // eseguo in transazione... await using var dbCtx = new MoonProContext(options); await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { // inizio con record microstato... var actRec = await dbCtx .DbSetMicroStatoMacc .FindAsync(newRecMsm.IdxMacchina); //.SingleOrDefaultAsync(); if (actRec == null) { dbCtx.DbSetMicroStatoMacc.Add(newRecMsm); } else { actRec.IdxMicroStato = newRecMsm.IdxMicroStato; actRec.InizioStato = newRecMsm.InizioStato; actRec.Value = newRecMsm.Value; // Update() allega l'entità e segna tutti i campi come Modified dbCtx.DbSetMicroStatoMacc.Update(actRec); #if false dbCtx.Entry(actRec).State = EntityState.Modified; #endif } // ora record EVList dbCtx.DbSetEvList.Add(newRecEv); // EF Core 8 raggruppa automaticamente INSERT/UPDATE in un batch var rowsAffected = await dbCtx.SaveChangesAsync(); await tx.CommitAsync(); return rowsAffected > 0; } catch { await tx.RollbackAsync(); throw; } } /// /// Chiamata x stored recupero FluxLog x macchina (first) /// /// /// /// public async Task> FluxLogFirstByMaccAsync(string idxMacc, int numMax) { List dbResult = new(); using var dbCtx = new MoonPro_FluxContext(_configuration); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var NumMax = new SqlParameter("@numMax", numMax); dbResult = await dbCtx .DbSetFluxLog .FromSqlRaw("exec dbo.stp_FL_getFirstByMacc @IdxMacchina, @numMax", IdxMacchina, NumMax) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione) /// /// Data massima x eventi /// Data minima x eventi /// * = tutte, altrimenti solo x una data macchina /// *=tutti, altrimenti solo selezionato /// numero massimo record da restituire /// public async Task> FluxLogGetLastFiltAsync(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec) { List dbResult = new List(); using var dbCtx = new MoonPro_FluxContext(_configuration); dbResult = await dbCtx .DbSetFluxLog .AsNoTracking() .Where(x => (x.dtEvento >= DtMin && x.dtEvento <= DtMax) && (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodFlux == "*" || x.CodFlux == CodFlux)) .OrderByDescending(x => x.dtEvento) .Take(MaxRec) .ToListAsync(); return dbResult; } /// /// Aggiunta record FluxLog /// /// /// public async Task FluxLogInsertAsync(FluxLogModel newRec) { bool fatto = false; using var dbCtx = new MoonPro_FluxContext(_configuration); var currRec = dbCtx .DbSetFluxLog .Add(newRec); await dbCtx.SaveChangesAsync(); return fatto; } /// /// Stored x eseguire Snapshot FluxLog (= Dossier) dato periodo /// /// /// public async Task FluxLogTakeSnapshotLastAsync(string idxMacc, DateTime dataInizio, DateTime dataFine) { bool fatto = false; using var dbCtx = new MoonPro_FluxContext(_configuration); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var DataInizio = new SqlParameter("@DtMin", dataInizio); var DataFine = new SqlParameter("@DtMax", dataFine); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_FL_TakeSnapshotLast @IdxMacchina, @DtMin, @DtMax", IdxMacchina, DataInizio, DataFine); fatto = result > 0; return fatto; } /// /// Upsert record keepalive /// /// /// /// /// public async Task KeepAliveUpsertAsync(string IdxMacc, DateTime OraServer, DateTime OraMacc) { bool fatto = false; using var dbCtx = new MoonProContext(options); var currRec = await dbCtx .DbSetKeepAlive .Where(x => x.IdxMacchina == IdxMacc) .FirstOrDefaultAsync(); if (currRec != null) { currRec.DataOraServer = OraServer; currRec.DataOraMacchina = OraMacc; dbCtx.Entry(currRec).State = EntityState.Modified; } else { KeepAliveModel newRec = new KeepAliveModel() { IdxMacchina = IdxMacc, DataOraMacchina = OraMacc, DataOraServer = OraServer, DataOraStart = DateTime.Now }; dbCtx .DbSetKeepAlive .Add(newRec); } fatto = await dbCtx.SaveChangesAsync() > 0; return fatto; } public async Task> ListLinkFiltAsync(string tipoLink) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); dbResult = await dbCtx .DbSetLinkMenu .Where(x => x.TipoLink == tipoLink) .AsNoTracking() .OrderBy(x => x.Ordine) .ToListAsync(); return dbResult; } /// /// Elenco valori ammessi x tabella/colonna con filtro parametrico /// /// Filtro tabella (se "" tutto) /// Filtro colonna (se "" tutto) /// public async Task> ListValuesFiltAsync(string tabName, string fieldName) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); var query = dbCtx .DbSetListValues .AsNoTracking() .AsQueryable(); if (!string.IsNullOrEmpty(tabName)) query = query.Where(x => x.TableName == tabName); if (!string.IsNullOrEmpty(fieldName)) query = query.Where(x => x.FieldName == fieldName); dbResult = await query.ToListAsync(); return dbResult; } /// /// Intera tabella relazione master/slave in machine (gestione setup master - slave) /// /// public async Task> Macchine2SlaveAsync() { List dbResult = new List(); using var dbCtx = new MoonProContext(options); dbResult = await dbCtx .DbSetM2S .AsNoTracking() .OrderBy(x => x.IdxMacchina) .ToListAsync(); return dbResult; } /// /// Elenco Record Macchine /// /// public async Task> MacchineGetAllAsync() { List dbResult = new List(); using var dbCtx = new MoonProContext(options); dbResult = await dbCtx .DbSetMacchine .ToListAsync(); return dbResult; } public async Task MacchineGetByIdxAsync(string IdxMacchina) { MacchineModel dbResult = null; using var dbCtx = new MoonProContext(options); dbResult = await dbCtx .DbSetMacchine .FirstOrDefaultAsync(x => x.IdxMacchina == IdxMacchina); return dbResult; } /// /// Elenco da tabella Macchine /// /// /// public async Task> MacchineGetFiltAsync(string codGruppo) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); if (codGruppo == "*") { dbResult = await dbCtx .DbSetMacchine .AsNoTracking() .OrderBy(x => x.IdxMacchina) .ToListAsync(); } else { dbResult = await dbCtx .DbSetGrp2Macc .Where(g => g.CodGruppo == codGruppo) .Join(dbCtx.DbSetMacchine, g => g.IdxMacchina, m => m.IdxMacchina, (g, m) => m ) .AsNoTracking() .OrderBy(x => x.IdxMacchina) .ToListAsync(); } return dbResult; } /// /// Upsert Record Macchine ASYNC /// /// public async Task MacchineUpsertAsync(MacchineModel entity) { using var dbCtx = new MoonProContext(options); // Recuperiamo l'entità tracciata dal context var trackedEntity = await dbCtx .DbSetMacchine .FirstOrDefaultAsync(x => x.IdxMacchina == entity.IdxMacchina); if (trackedEntity != null) { // Aggiorna i valori dell'entità tracciata con quelli della nuova dbCtx.Entry(trackedEntity).CurrentValues.SetValues(entity); } else { dbCtx.DbSetMacchine.Update(entity); } bool fatto = await dbCtx.SaveChangesAsync() > 0; return fatto; } /// /// Elenco da tabella Macchine /// /// /// public async Task> MicroStatoMacchinaGetByIdxMaccAsync(string IdxMacc) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); dbResult = await dbCtx .DbSetMicroStatoMacc .Where(x => x.IdxMacchina == IdxMacc) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Aggiornamento record Microstato macchina /// /// /// public async Task MicroStatoMacchinaUpsertAsync(MicroStatoMacchinaModel newRec) { bool fatto = false; using var dbCtx = new MoonProContext(options); var actRec = await dbCtx .DbSetMicroStatoMacc .Where(x => x.IdxMacchina == newRec.IdxMacchina) .AsNoTracking() .FirstOrDefaultAsync(); if (actRec == null) { dbCtx .DbSetMicroStatoMacc .Add(newRec); } else { actRec.IdxMicroStato = newRec.IdxMicroStato; actRec.InizioStato = newRec.InizioStato; actRec.Value = newRec.Value; dbCtx.Entry(actRec).State = EntityState.Modified; } fatto = await dbCtx.SaveChangesAsync() > 0; return fatto; } /// /// Elenco da tabella MappaStatoExplModel /// /// public async Task> MseGetAllAsync(int maxAge = 2000) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); dbResult = await dbCtx .DbSetMSE .FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Generazione automatica ODL /// /// /// public async Task OdlAutoDayGenAsync(string idxMacchina, DateTime dataInizio, DateTime dataFine, string codArticolo) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataInizio = new SqlParameter("@DataInizio", dataInizio); var DataFine = new SqlParameter("@DataFine", dataFine); var CodArticolo = new SqlParameter("@codArticolo", codArticolo); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ODL_AutoDayGener @IdxMacchina, @DataInizio, @DataFine, @codArticolo", IdxMacchina, DataInizio, DataFine, CodArticolo); // indico eseguito! return result > 0; } /// /// Generazione automatica ODL completa /// /// /// public async Task OdlAutoDayGenFullAsync(string idxMacchina, DateTime dataInizio, DateTime dataFine, string codArticolo, int? pzPODL, int? pzPallet, string? keyRichiesta, int? tcAssegnato, string? codGruppo, bool flgCreaPODL, bool flgCheckTC) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataInizio = new SqlParameter("@DataInizio", dataInizio); var DataFine = new SqlParameter("@DataFine", dataFine); var CodArticolo = new SqlParameter("@codArticolo", codArticolo); var PzPODL = new SqlParameter("@PzPODL", pzPODL); var PzPallet = new SqlParameter("@PzPallet", pzPallet); var KeyRichiesta = new SqlParameter("@KeyRichiesta", keyRichiesta); var TCAssegnato = new SqlParameter("@TCAssegnato", tcAssegnato); var CodGruppo = new SqlParameter("@codGruppo", codGruppo); var FlgCreaPODL = new SqlParameter("@flgCreaPODL", flgCreaPODL); var FlgCheckTC = new SqlParameter("@flgCheckTC", flgCheckTC); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ODL_AutoDayGenerFull @IdxMacchina, @DataInizio, @DataFine, @codArticolo, @PzPODL, @PzPallet, @KeyRichiesta, @TCAssegnato, @codGruppo, @flgCreaPODL, @flgCheckTC", IdxMacchina, DataInizio, DataFine, CodArticolo, PzPODL, PzPallet, KeyRichiesta, TCAssegnato, CodGruppo, FlgCreaPODL, FlgCheckTC); return result > 0; } /// /// ODL corrente macchina /// /// /// public async Task OdlCurrByMaccAsync(string idxMacchina) { ODLExpModel answ = new(); using var dbCtx = new MoonProContext(options); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); // attenzione: se la stored resituisce una tabella, il primo elemento va recuperato in RAM!!! var dbRes = (await dbCtx.DbSetODLExp .FromSqlRaw("EXEC stp_ODL_getByMacchina @IdxMacchina", pIdxMacchina) .AsNoTracking() .ToListAsync()) // Esegue la query e scarica i risultati in memoria .FirstOrDefault(); // Prende il primo elemento dalla lista in RAM answ = dbRes ?? new(); return answ; } /// /// Fix ODL per macchine SLAVE /// /// /// /// /// public async Task OdlFixMachineSlave(string idxMacchina, int numDayPrev, int doInsert) { using var dbCtx = new MoonProContext(options); var idxMaccParam = new SqlParameter("@IdxMacchina", idxMacchina ?? ""); var numDayPrevParam = new SqlParameter("@NumDayPrev", numDayPrev); var doInsertParam = new SqlParameter("@DoInsert", doInsert); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ODL_fixMachineSlave @IdxMacchina, @NumDayPrev, @DoInsert", idxMaccParam, numDayPrevParam, doInsertParam); return result != -1; } /// /// Fix ODL per macchine SLAVE Async /// /// /// /// /// public async Task OdlFixMachineSlaveAsync(string idxMacchina, int numDayPrev, int doInsert) { using var dbCtx = new MoonProContext(options); var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); var NumDayPrev = new SqlParameter("@NumDayPrev", numDayPrev); var DoInsert = new SqlParameter("@DoInsert", doInsert); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_ODL_fixMachineSlave @IdxMacchina, @NumDayPrev, @DoInsert", IdxMacc, NumDayPrev, DoInsert); return result != 0; } /// /// ODL corrente macchina /// /// /// public async Task OdlLastByMaccAsync(string idxMacchina) { ODLExpModel answ = new(); using var dbCtx = new MoonProContext(options); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); // attenzione: se la stored resituisce una tabella, il primo elemento va recuperato in RAM!!! var dbRes = (await dbCtx.DbSetODLExp .FromSqlRaw("EXEC stp_ODL_getLastByMacchina @IdxMacchina", pIdxMacchina) .AsNoTracking() .ToListAsync()) // Esegue la query e scarica i risultati in memoria .FirstOrDefault(); // Prende il primo elemento dalla lista in RAM answ = dbRes ?? new(); return answ; } /// /// Elenco ODL data macchina e periodo /// /// /// /// /// public async Task> OdlListByMaccPeriodoAsync(string idxMacchina, DateTime dtStart, DateTime dtEnd) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataFrom = new SqlParameter("@dataFrom", dtStart); var DataTo = new SqlParameter("@dataTo", dtEnd); dbResult = await dbCtx .DbSetODLExp .FromSqlRaw("EXEC stp_ODL_getByMacchinaPeriodo @IdxMacchina, @dataFrom, @dataTo", IdxMacchina, DataFrom, DataTo) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Conteggio PzProd Macchina Async /// /// /// public async Task PezziProdMacchinaAsync(string idxMacchina) { PzProdModel dbResult = new PzProdModel(); using var dbCtx = new MoonProContext(options); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); dbResult = (await dbCtx .DbSetPzProd .FromSqlRaw("EXEC stp_PzProd_getByMacchina @IdxMacchina", pIdxMacchina) .AsNoTracking() .ToListAsync()) .FirstOrDefault(); // recupero da RAM return dbResult; } /// /// Recupero elenco PODL EXPL filtrati x macchina, articolo... /// /// /// /// /// True = aperti (=senza ODL) /// public async Task> POdlGetByMaccArtAsync(string idxMacchina, string codArticolo, string codGruppo, bool onlyFree) { List dbResult = new List(); using var dbCtx = new MoonProContext(options); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var pCodArticolo = new SqlParameter("@CodArticolo", codArticolo); var pCodGruppo = new SqlParameter("@CodGruppo", codGruppo); var pOnlyFree = new SqlParameter("@onlyFree", onlyFree); dbResult = await dbCtx .DbSetPODLExp .FromSqlRaw("EXEC stp_PODL_getByMaccArt @IdxMacchina, @CodArticolo, @CodGruppo, @onlyFree", pIdxMacchina, pCodArticolo, pCodGruppo, pOnlyFree) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Effettua ricalcolo MSE x macchina indicata /// /// idx macchina da confermare /// Num massimo secondi di "vecchiaia" del dato /// public async Task RecalcMseAsync(string idxMacchina, int maxAgeSec) { using var dbCtx = new MoonProContext(options); var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); var MaxAgeSec = new SqlParameter("@maxAgeSec ", maxAgeSec); var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_MSE_recalc @maxAgeSec, @idxMacchina ", MaxAgeSec, IdxMacchina); return result != 0; } /// /// Registra controllo /// /// /// /// /// /// /// public async Task RegControlliInsertAsync(string idxMacchina, int matrOpr, bool esitoOk, string note, DateTime dataOra) { using var dbCtx = new MoonProContext(options); var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); var MatrOpr = new SqlParameter("@MatrOpr", matrOpr); var EsitoOk = new SqlParameter("@EsitoOk", esitoOk); var Note = new SqlParameter("@Note", note); var DataOra = new SqlParameter("@DataOra", dataOra); var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_RC_insert @IdxMacchina, @MatrOpr, @EsitoOk, @Note, @DataOra", IdxMacc, MatrOpr, EsitoOk, Note, DataOra); return result != 0; } /// /// Aggiunta record Registro Dichiarazioni /// /// /// public async Task RegDichiarInsertAsync(RegistroDichiarazioniModel newRec) { using var dbCtx = new MoonProContext(options); var TagCode = new SqlParameter("@TagCode", newRec.TagCode); var IdxMacchina = new SqlParameter("@IdxMacchina", newRec.IdxMacchina); var DtRec = new SqlParameter("@DtRec", newRec.DtRec); var MatrOpr = new SqlParameter("@MatrOpr", newRec.MatrOpr); var ValString = new SqlParameter("@ValString", newRec.ValString); var result = await dbCtx .Database .ExecuteSqlRawAsync("exec dbo.stp_DD_insertQuery @TagCode, @IdxMacchina, @DtRec, @MatrOpr, @ValString", TagCode, IdxMacchina, DtRec, MatrOpr, ValString); return result != 0; } /// /// Update record Registro Dichiarazioni /// /// /// public async Task RegDichiarUpdateAsync(RegistroDichiarazioniModel newRec) { using var dbCtx = new MoonProContext(options); var Original_IdxDich = new SqlParameter("@Original_IdxDich", newRec.IdxDich); var DtRec = new SqlParameter("@DtRec", newRec.DtRec); var TagCode = new SqlParameter("@TagCode", newRec.TagCode); var ValString = new SqlParameter("@ValString", newRec.ValString); var MatrOpr = new SqlParameter("@MatrOpr", newRec.MatrOpr); var result = await dbCtx .Database .ExecuteSqlRawAsync("exec dbo.stp_DD_updateQuery @Original_IdxDich, @DtRec, @TagCode, @ValString, @MatrOpr", Original_IdxDich, DtRec, TagCode, ValString, MatrOpr); return result != 0; } /// /// Aggiunta record RegistroScarti /// /// /// public async Task RegScartiInsertAsync(RegistroScartiModel newRec) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@idxMacchina", newRec.IdxMacchina); var DataOra = new SqlParameter("@DataOra", newRec.DataOra); var Causale = new SqlParameter("@Causale", newRec.Causale); var Qta = new SqlParameter("@Qta", newRec.Qta); var Note = new SqlParameter("@Note", newRec.Note); var MatrOpr = new SqlParameter("@MatrOpr", newRec.MatrOpr); var result = await dbCtx .DbSetRegWithCheck .FromSqlRaw("exec dbo.stp_RS_Insert_withCheck @idxMacchina, @DataOra, @Causale, @Qta, @Note, @MatrOpr", IdxMacchina, DataOra, Causale, Qta, Note, MatrOpr) .AsNoTracking() .ToListAsync(); return result.Count != 0; } /// /// Aggiunta record RemoteRebootLog /// /// Record da inserire /// Esecuzione stored di cleanup /// Parametro max num2keep x stored cleanup /// public async Task RemRebootLogAddAndCleanAsync(RemoteRebootLogModel newRec, bool doClean, int num2keep) { bool fatto = false; using var dbCtx = new MoonProContext(options); // 1. Transazione minima: SOLO INSERT + COMMIT await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { dbCtx.DbSetRemRebLog.Add(newRec); fatto = await dbCtx.SaveChangesAsync() > 0; await tx.CommitAsync(); // 🔑 Commit prima della pulizia } catch { await tx.RollbackAsync(); throw; } // 2. Cleanup "smart" fuori transazione if (doClean && fatto) { try { var param = new SqlParameter("@num2keep", num2keep); await dbCtx.Database.ExecuteSqlRawAsync( "EXEC dbo.stp_RRL_KeepLatest @num2keep, @multiplier", param, new SqlParameter("@multiplier", 2.5f)); // Fisso e poiché è coinvolto MAC address è + alto } catch (Exception ex) { // Log dell'errore, ma NON rilanciare: il record è già salvo Log.Error(ex, "Failed to execute RRL cleanup for {Machine}", newRec.IdxMacchina); } } return fatto; } /// /// Aggiunta record RemoteRebootLog /// /// /// public async Task RemRebootLogAddAsync(RemoteRebootLogModel newRec) { using var dbCtx = new MoonProContext(options); var dbResult = dbCtx .DbSetRemRebLog .Add(newRec); return await dbCtx.SaveChangesAsync() > 0; } /// /// Recupera tutti i record di RemoteRebootLog /// /// public async Task> RemRebootLogGetAllAsync() { using var dbCtx = new MoonProContext(options); var dbResult = await dbCtx .DbSetRemRebLog .AsNoTracking() .OrderByDescending(x => x.IdxReboot) .ToListAsync(); return dbResult; } /// /// Recupera ultimo record x ogni IdxMacchina x avere ultimo attivo /// /// public async Task> RemRebootLogGetLastAsync() { using var dbCtx = new MoonProContext(options); var dbResult = await dbCtx .DbSetRemRebLog .FromSqlRaw("EXEC stp_RRL_getLast") .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Recupera ultimo record x ogni IdxMacchina x avere ultimo attivo /// /// public async Task RemRebootLogKeepLastAsync(int num2keep) { using var dbCtx = new MoonProContext(options); var pNum2Keep = new SqlParameter("@num2keep", num2keep); // La SP gestisce già la logica di soglia (1.5x), ma la specifico x sicurezza var pThresh = new SqlParameter("@threshMult", 1.5); var dbResult = await dbCtx.Database.ExecuteSqlRawAsync( "EXEC dbo.stp_RRL_KeepLatest @num2keep, @threshMult", pNum2Keep, pThresh); return dbResult != 0; } /// /// Aggiunta record SignalLog Async /// /// /// public async Task SignalLogInsertAsync(SignalLogModel newRec) { using var dbCtx = new MoonProContext(options); var currRec = dbCtx .DbSetSignalLog .Add(newRec); return await dbCtx.SaveChangesAsync() > 0; } /// /// Tabella state machine eventi 2 stati data macchina e tipo evento /// /// /// public async Task> SMES_getHwTransitionsAsync(string idxMacchina, int idxTipo) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var IdxTipo = new SqlParameter("@IdxTipo", idxTipo); var dbResult = await dbCtx .DbSetSMES .FromSqlRaw("exec dbo.stp_TS_getByIdxMacchIdxTipoEv @IdxMacchina, @IdxTipo", IdxMacchina, IdxTipo) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Tabella state machine eventi 2 stati data macchina e tipo evento /// /// /// public async Task> SMES_getUserForcedAsync(string idxMacchina, int idxTipo) { await using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var IdxTipo = new SqlParameter("@IdxTipo", idxTipo); var dbResult = await dbCtx .DbSetSMES .FromSqlRaw("exec dbo.stp_TS_getUserForcedTrans @IdxMacchina, @IdxTipo", IdxMacchina, IdxTipo) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Intera tabella state machine ingressi 2 eventi /// /// public List StateMachineIngressi(int idxFam) { List dbResult = new List(); using (var dbCtx = new MoonProContext(options)) { var IdxFamIn = new SqlParameter("@IdxFamigliaIngresso", idxFam); dbResult = dbCtx .DbSetSMI .FromSqlRaw("exec dbo.stp_TRI_getByIdxFamIng @IdxFamigliaIngresso", IdxFamIn) .AsNoTracking() .AsEnumerable() .ToList(); } return dbResult; } /// /// Intera tabella state machine ingressi 2 eventi /// /// public async Task> StateMachineIngressiAsync(int idxFam) { using var dbCtx = new MoonProContext(options); var IdxFamIn = new SqlParameter("@IdxFamigliaIngresso", idxFam); var dbResult = await dbCtx .DbSetSMI .FromSqlRaw("exec dbo.stp_TRI_getByIdxFamIng @IdxFamigliaIngresso", IdxFamIn) .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Stato prod macchina (completo) Async /// /// /// /// public async Task StatoProdMacchinaAsync(string idxMacchina, DateTime dtReq) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataOra = new SqlParameter("@DataOra ", dtReq); var dbResult = (await dbCtx .DbSetStatoProd .FromSqlRaw("EXEC stp_StatoProd_getByMacchina @IdxMacchina, @DataOra ", IdxMacchina, DataOra) .AsNoTracking() .ToListAsync()) .FirstOrDefault(); return dbResult; } /// /// Intera vista v_MSFD in modo ASYNC /// /// public async Task> VMSFDGetAllAsync() { using var dbCtx = new MoonProContext(options); var dbResult = await dbCtx .DbSetMSFD .AsNoTracking() .OrderBy(x => x.IdxMacchina) .ToListAsync(); return dbResult; } /// /// Vista v_MSFD x singola macchina (da stored) - singolo record /// /// /// public async Task VMSFDGetByMaccAsync(string idxMacc) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var dbResult = (await dbCtx .DbSetMSFD .FromSqlRaw("exec dbo.stp_MSFD_getMacc @IdxMacchina", IdxMacchina) .AsNoTracking() .ToListAsync()) .FirstOrDefault(); return dbResult; } /// /// Vista v_MSFD delle machine MULTI filtrato x macchina (da stored) /// /// /// public async Task> VMSFDGetMultiByMaccAsync(string idxMacc) { using var dbCtx = new MoonProContext(options); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var dbResult = await dbCtx .DbSetMSFD .FromSqlRaw("exec dbo.stp_MSFD_getMulti @IdxMacchina", IdxMacchina) .AsNoTracking() .ToListAsync(); return dbResult; } #endregion Public Methods #region Private Fields private static IConfiguration _configuration; private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); private DbContextOptions options; #endregion Private Fields #if false public void Dispose() { _configuration = null; } #endif } }