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, IDbContextFactory ctxFactory, IDbContextFactory ctxFactoryFL) { _ctxFactory = ctxFactory; _ctxFactoryFL = ctxFactoryFL; 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetAnagStati .AsNoTracking() .ToListAsync(); return dbResult; } /// /// Restitusice elenco ultimi articoli per macchina /// /// /// /// /// public async Task> ArticoliGetLastByMaccAsync(string idxMacc) { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); //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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactoryFL.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); bool fatto = false; var dbResult = await dbCtx .DbSetConfig .Where(x => x.Chiave == updRec.Chiave) .FirstOrDefaultAsync(); if (dbResult != null) { dbResult.Valore = updRec.Valore; fatto = await dbCtx.SaveChangesAsync() > 0; } return fatto; } /// /// Intera tab dati macchina /// /// public async Task> DatiMacchineGetAllAsync() { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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) { using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); return await dbCtx .DbSetDossiers .FromSqlRaw("exec dbo.stp_DOSS_getLastByMacch @idxMacchina", IdxMacchina) .AsNoTracking() .ToListAsync(); } /// /// Aggiunta record EventList /// /// /// public async Task EvListInsertAsync(EventListModel newRec) { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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); } // 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) { using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var NumMax = new SqlParameter("@numMax", numMax); return await dbCtx .DbSetFluxLog .FromSqlRaw("exec dbo.stp_FL_getFirstByMacc @IdxMacchina, @numMax", IdxMacchina, NumMax) .AsNoTracking() .ToListAsync(); } /// /// Aggiunta record FluxLog /// /// /// public async Task FluxLogInsertAsync(FluxLogModel newRec) { using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); var currRec = dbCtx .DbSetFluxLog .Add(newRec); return await dbCtx.SaveChangesAsync() > 0; } /// /// Stored x eseguire Snapshot FluxLog (= Dossier) dato periodo /// /// /// public async Task FluxLogTakeSnapshotLastAsync(string idxMacc, DateTime dataInizio, DateTime dataFine) { using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); 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); return result > 0; } /// /// Generazione automatica ODL /// /// /// public async Task OdlAutoDayGenAsync(string idxMacchina, DateTime dataInizio, DateTime dataFine, string codArticolo) { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 Async /// /// /// /// /// public async Task OdlFixMachineSlaveAsync(string idxMacchina, int numDayPrev, int doInsert) { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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; } /// /// Conteggio PzProd Macchina Async /// /// /// public async Task PezziProdMacchinaAsync(string idxMacchina) { PzProdModel dbResult = new PzProdModel(); using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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; } /// /// Aggiunta record RegistroScarti /// /// /// public async Task RegScartiInsertAsync(RegistroScartiModel newRec) { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); // 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; } /// /// Stato prod macchina (completo) Async /// /// /// /// public async Task StatoProdMacchinaAsync(string idxMacchina, DateTime dtReq) { using var dbCtx = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 = _ctxFactory.CreateDbContext(); 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 Protected Fields protected readonly IDbContextFactory _ctxFactory; protected readonly IDbContextFactory _ctxFactoryFL; #endregion Protected Fields #region Private Fields private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); private DbContextOptions optionsFlux; #endregion Private Fields } }