using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using MP.Core.DTO; using MP.Data.DbModels; using MP.Data.Services; using MP_TAB3.Pages; using NLog; using System.Globalization; using System.Net.Security; using static MP_TAB3.Components.ProdAdvDispl; namespace MP_TAB3.Components { public partial class InsManual { #region Public Properties [Parameter] public MappaStatoExplModel? RecMSE { get => currRecMSE; set { // salvo SOLO SE non sono in conferma if (!confProdActive) { currRecMSE = value; } } } #endregion Public Properties #region Protected Properties protected DateTime dtCurr { get => selDtCurr; set { if (selDtCurr != value) { selDtCurr = value; dtMonthStart = new DateTime(value.Year, value.Month, 1); } } } [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; [Inject] protected MessageService MServ { get; set; } = null!; [Inject] protected TabDataService TabDServ { get; set; } = null!; #endregion Protected Properties #region Protected Methods protected void AddNew(bool isWork) { if (RecMSE != null) { string idxMacc = RecMSE.IdxMacchina; DateTime startPeriod = dtCurr.Date; if (ListDay != null) { var lastRec = ListDay.LastOrDefault(); if (lastRec != null && lastRec.FineStato.HasValue) { startPeriod = lastRec.FineStato.Value; } else { startPeriod = dtCurr.Date.AddHours(6); } enableEditTime = ListDay.Count == 0; } else { enableEditTime = true; } // evento da richiesta: default lavora/spenta int idxTipo = isWork ? 1 : 12; // creazione nuovo record ed aggiunta in coda agli esistenti... EditRecord = new InsManualiModel() { IdxMacchina = idxMacc, InizioStato = startPeriod, IdxTipoEv = idxTipo, MatrOpr = MServ.MatrOpr }; } } /// /// Annulla editing /// /// protected void DoCancel() { doSearchArt = false; EditRecord = null; ReloadData(); RecalcDayData(dtCurr); } /// /// impossta record x eliminazione /// /// protected async Task DoDelete(InsManualiModel selRec) { if (!await JSRuntime.InvokeAsync("confirm", $"Sicuro di voler eliminare il record tipo {selRec.IdxTipoEv} | {selRec.InizioStato:yyyy.MM.dd HH:mm} per {selRec.MinProd:N2} min?")) return; // esegue eliminazione del record... await TabDServ.InsManDelete(selRec); doSearchArt = false; EditRecord = null; // rileggo i dati... ReloadData(); RecalcDayData(dtCurr); if (!IsTimeInfoOk(dtCurr, true)) { int numChange = await DoRecalcDay(); } // rileggo i dati... ReloadData(); RecalcDayData(dtCurr); } /// /// imposta record x editing /// /// protected void DoEdit(InsManualiModel? selRec) { doSearchArt = false; if (selRec == null) { enableEditTime = false; } else { enableEditTime = true; if (ListDay != null && ListDay.Count > 0) { var firstRec = ListDay.FirstOrDefault(); if (firstRec != null) { enableEditTime = selRec.InizioStato <= firstRec.InizioStato; } } // altrimenti è vuoto x cui è libero else { enableEditTime = true; } } EditRecord = selRec; } protected async Task DoSave() { doSearchArt = false; // solo se ho record... if (EditRecord != null) { // sistemo i dati... var dayElap = EditRecord.InizioStato.Subtract(EditRecord.InizioStato.Date); EditRecord.MatrOpr = MServ.MatrOpr; EditRecord.InizioStato = dtCurr.Date.Add(dayElap); // imposto altri campi secondo il TIPO di record... if (EditRecord.IsWork) { // controllo min pezzi a 1 EditRecord.PzBuoni = EditRecord.PzBuoni > 0 ? EditRecord.PzBuoni : 1; // calcolo durata EditRecord.MinProd = EditRecord.TCiclo * EditRecord.PzBuoni; } else { EditRecord.CodArticolo = "ND"; EditRecord.PzBuoni = 0; EditRecord.TCiclo = 0; } EditRecord.FineStato = EditRecord.InizioStato.AddMinutes((double)EditRecord.MinProd); // lancio salvataggio sul DB await TabDServ.InsManUpsert(EditRecord); // rileggo i dati... ReloadData(); if (!IsTimeInfoOk(dtCurr, false)) { int numChange = await DoRecalcDay(); } // rileggo i dati... ReloadData(); RecalcDayData(dtCurr); EditRecord = null; } } /// /// traduzione evento da lista... /// /// /// protected string EvDescript(int idxTipoEv) { string answ = "-"; if (ListEvents != null) { var rSel = ListEvents.FirstOrDefault(x => x.value == idxTipoEv); if (rSel != null) { answ = rSel.label; } } return answ; } protected async Task FixMissing() { if (!await JSRuntime.InvokeAsync("confirm", $"Sicuro di voler riempire i periodi mancanti?")) return; // filtra dati odierni x tab editabile... if (ListPeriod != null && ListPeriod.Count > 0) { // chiamo insert con eventi spenta (12) HardCoded... int numAdd = await TabDServ.InsManFillMissing(dtCurr, ListDay, 12, MServ.MatrOpr); // rileggo i dati... ReloadData(); RecalcDayData(dtCurr); } } protected override async Task OnParametersSetAsync() { if (RecMSE != null && RecMSE.IdxMacchina != idxMacc) { idxMacc = RecMSE.IdxMacchina; ReloadData(); } await Task.Delay(1); } #endregion Protected Methods #region Private Fields private int currVal = 0; private Dictionary DateCFF = new Dictionary(); /// /// Lista date + css associato x display calendario /// private Dictionary DateCheck = new Dictionary(); /// /// % record importati /// private double DayImportRatio = 0; /// /// Minuti lavorati (da sequencer) /// private double DayMinLav = 0; /// /// Minuti caricati (da sequencer) /// private double DayMinTot = 0; /// /// OEE giornaliero (ore lav / 24h) /// private double DayOee = 0; /// /// Boolear controllo visualizzazione ricerca articoli /// private bool doSearchArt = false; private DateTime dtMonthStart = new DateTime(2000, 1, 1); private InsManualiModel? EditRecord = null; /// /// Abilitazione edit DataOra inizio (solo x primo record, poi devono essere consecutivi... /// private bool enableEditTime = false; private int expTimeMsec = 1000; private string idxMacc = ""; private int nextVal = 0; private string progressTitle = "Approvazione Giornata"; private List SeqStatus = new List(); private bool showProgress = false; #endregion Private Fields #region Private Properties private bool confProdActive { get; set; } = false; private MappaStatoExplModel? currRecMSE { get; set; } = null; private List? ListDay { get; set; } = new List(); private List? ListDTO { get; set; } = new List(); /// /// Eventi inseribili come fermate /// private List ListEvents { get; set; } = new List(); private List? ListPeriod { get; set; } = new List(); /// /// Eventi inseribili come fermate /// private Dictionary ListTCiclo { get; set; } = new Dictionary(); // private DateTime selDtCurr { get; set; } = DateTime.Today; private bool showDetail { get; set; } = false; #endregion Private Properties #region Private Methods private void CloseDet() { showDetail = false; } private void DisplayDate(DateTime dtSel) { dtCurr = dtSel; showDetail = true; RecalcDayData(dtSel); } /// /// Ricalcolo dati giornalieri /// /// private async Task DoRecalcDay() { int numChange = 0; // prendo i dati odierni, e uno x uno ciclo e sistemo... DateTime lastDate = dtCurr.Date; List ListChange = new List(); if (ListDay != null && ListDay.Count > 0) { foreach (var item in ListDay) { bool isFirst = lastDate.TimeOfDay == new TimeSpan(0); if ((item.InizioStato < lastDate && isFirst) || (item.InizioStato != lastDate && !isFirst)) { item.InizioStato = lastDate; } // controllo se la data fine � ok... if (!item.FineStato.HasValue || Math.Abs(item.InizioStato.AddMinutes((double)item.MinProd).Subtract(item.FineStato.Value).TotalMinutes) > 1) { item.FineStato = item.InizioStato.AddMinutes((double)item.MinProd); item.MatrOpr = MServ.MatrOpr; numChange++; ListChange.Add(item); } lastDate = item.FineStato.Value; } // salvo tutto await TabDServ.InsManUpsert(ListChange); } return numChange; } /// /// Congela la definizione giornaliera di produzione /// /// private async Task FreezeDay() { if (dtCurr.Date >= DateTime.Today) { await JSRuntime.InvokeVoidAsync("alert", $"Impossibile procedere con conferma: la giornata non si è ancora conclusa."); return; } if (!await JSRuntime.InvokeAsync("confirm", $"Sicuro di voler confermare gli eventi della giornata? i valori non saranno più modificabili.")) return; // esegue stored showProgress = true; await Task.Delay(10); bool fatto = false; progressTitle = "Registrazione conferma giornaliera"; currVal = 0; nextVal = 90; await InvokeAsync(StateHasChanged); if (RecMSE != null) { await Task.Delay(10); await InvokeAsync(StateHasChanged); await Task.Delay(10); fatto = await TabDServ.InsManFreezeDay(RecMSE.IdxMacchina, dtCurr); currVal = 90; nextVal = 100; progressTitle = "Ricalcolo Giornata"; await InvokeAsync(StateHasChanged); EditRecord = null; ReloadData(); RecalcDayData(dtCurr); showProgress = false; } return; } private bool IsTimeInfoOk(DateTime reqDate, bool reloadDay) { bool allOk = false; List myListDay = new List(); if (ListDTO != null) { var dayDto = ListDTO.FirstOrDefault(x => x.DataRif == reqDate.Date); if (dayDto != null && ListDay != null && ListPeriod != null) { // se listDay vuoto forzo reload... if (ListDay.Count == 0) { reloadDay = true; } if (reloadDay) { // calcolo eventi giorno myListDay = ListPeriod .Where(x => x.InizioStato.Date == reqDate) .OrderBy(x => x.InizioStato) .ThenBy(x => x.IdxInsMan) .ToList(); } else { myListDay = ListDay; } var firstRec = myListDay.OrderBy(x => x.InizioStato).FirstOrDefault(); var lastRec = myListDay.OrderByDescending(x => x.InizioStato).FirstOrDefault(); var deltaMins = lastRec!.FineStato!.Value.Subtract(firstRec!.InizioStato).TotalMinutes; allOk = Math.Abs(deltaMins - (double)dayDto.MinProdTot) < 1; } } return allOk; } /// /// Restitusice la % formattata in invariant con "." e senza spazi prima della % /// /// /// private string PercWidth(double value) { return value.ToString("P2", CultureInfo.InvariantCulture).Replace(" ", ""); } /// /// Ricalcola dati giornalieri /// /// private void RecalcDayData(DateTime dtSel) { ListDay = new List(); SeqStatus = new List(); DayMinLav = 0; DayMinTot = 0; DayImportRatio = 0; // filtra dati odierni x tab editabile... if (ListPeriod != null && ListPeriod.Count > 0) { // calcolo eventi giorno ListDay = ListPeriod .Where(x => x.InizioStato.Date == dtSel) .OrderBy(x => x.InizioStato) .ThenBy(x => x.IdxInsMan) .ToList(); // ora calcolo il sequencer x mostrare dettaglio orario... SeqStatus = TabDServ.InsManSeqDayStatus(dtCurr, ListDay); // calcolo min lavorati odierni DayMinLav = 0; var recLav = SeqStatus.FirstOrDefault(x => x.IdxTipo == 1); if (recLav != null) { DayMinLav = recLav.Value; DayOee = recLav.ValuePerc; } // minuti totali come record day... DayMinTot = (double)ListDay.Sum(x => x.MinProd); if (dtSel.Date == dtCurr.Date && ListDTO != null) { var dayDto = ListDTO.FirstOrDefault(x => x.DataRif == dtSel.Date); if (dayDto != null) { DayImportRatio = dayDto.RatioImport; } } } } private void ReloadData() { // rileggo dati periodo... ListDTO = new List(); DateTime oggi = DateTime.Today; if (RecMSE != null) { string IdxMacc = RecMSE.IdxMacchina; // valori selezionabili x TCiclo var rawListTCiclo = TabDServ.ListValuesFilt("InsManuali", IdxMacc); ListTCiclo = new Dictionary(); foreach (var item in rawListTCiclo) { string sKey = item.value.Replace(",", "."); decimal chiave = 0; if (decimal.TryParse(sKey, NumberStyles.Any, CultureInfo.InvariantCulture, out chiave)) { ListTCiclo.Add(chiave, item.label); } } // eventi fermate var eventsAll = TabDServ.AnagEventiGetByMacch(IdxMacc); if (eventsAll != null) { ListEvents = eventsAll.Where(x => x.EventoTablet).ToList(); } DateTime MeseStart = new DateTime(dtCurr.Year, dtCurr.Month, 1); DateTime MeseEnd = MeseStart.AddMonths(1); ListPeriod = TabDServ.InsManFilt(IdxMacc, MeseStart, MeseEnd); ListDTO = TabDServ.InsManDayDto(ListPeriod); DateCheck = new Dictionary(); DateCFF = new Dictionary(); string cssImport = "bg-success text-light rounded-circle p-2"; string cssOkDay = "bg-success bg-opacity-50 text-light rounded-circle p-2"; string cssPartDay = "bg-info bg-opacity-25 text-light rounded-circle p-2"; string cssHasData = "bg-warning text-light rounded-circle p-2"; string cssToday = " border border-info rounded-circle p-2"; if (ListDTO != null) { string currCss = ""; foreach (var item in ListDTO) { currCss = ""; // controllo minuti dichiarati... if (item.RatioImport == 1) { currCss = cssImport; } else if (IsTimeInfoOk(item.DataRif.Date, true)) { currCss = item.MinProdTot < 1440 ? cssPartDay : cssOkDay; } else { currCss = item.MinProdTot == 0 ? "" : cssHasData; } DateCheck.Add(item.DataRif, currCss); } } // aggiungo comunque oggi... if (!DateCheck.ContainsKey(oggi)) { DateCheck.Add(oggi, cssToday); } else { DateCheck[oggi] += cssToday; } } } private async Task ReloadMonth(DateTime dtSel) { dtCurr = dtSel; ReloadData(); await Task.Delay(1); } private void SearchArtToggle() { doSearchArt = !doSearchArt; } /// /// Salva selezione articolo /// /// private void SetArtSelected(string codArt) { if (EditRecord != null) { EditRecord.CodArticolo = codArt; doSearchArt = false; } } #endregion Private Methods } }