Files
Samuele Locatelli cbd4a90d01 DATA:
- Correzione MSE i MSEModel x naming
- fix e test vari su app CORE (IOC/SPEC/TAB3/MON)
2025-04-14 18:25:00 +02:00

618 lines
21 KiB
C#

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
};
}
}
/// <summary>
/// Annulla editing
/// </summary>
/// <param name="selRec"></param>
protected void DoCancel()
{
doSearchArt = false;
EditRecord = null;
ReloadData();
RecalcDayData(dtCurr);
}
/// <summary>
/// impossta record x eliminazione
/// </summary>
/// <param name="selRec"></param>
protected async Task DoDelete(InsManualiModel selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("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);
}
/// <summary>
/// imposta record x editing
/// </summary>
/// <param name="selRec"></param>
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;
}
}
/// <summary>
/// traduzione evento da lista...
/// </summary>
/// <param name="idxTipoEv"></param>
/// <returns></returns>
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<bool>("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<DateTime, string> DateCFF = new Dictionary<DateTime, string>();
/// <summary>
/// Lista date + css associato x display calendario
/// </summary>
private Dictionary<DateTime, string> DateCheck = new Dictionary<DateTime, string>();
/// <summary>
/// % record importati
/// </summary>
private double DayImportRatio = 0;
/// <summary>
/// Minuti lavorati (da sequencer)
/// </summary>
private double DayMinLav = 0;
/// <summary>
/// Minuti caricati (da sequencer)
/// </summary>
private double DayMinTot = 0;
/// <summary>
/// OEE giornaliero (ore lav / 24h)
/// </summary>
private double DayOee = 0;
/// <summary>
/// Boolear controllo visualizzazione ricerca articoli
/// </summary>
private bool doSearchArt = false;
private DateTime dtMonthStart = new DateTime(2000, 1, 1);
private InsManualiModel? EditRecord = null;
/// <summary>
/// Abilitazione edit DataOra inizio (solo x primo record, poi devono essere consecutivi...
/// </summary>
private bool enableEditTime = false;
private int expTimeMsec = 1000;
private string idxMacc = "";
private int nextVal = 0;
private string progressTitle = "Approvazione Giornata";
private List<ManualStatusDTO> SeqStatus = new List<ManualStatusDTO>();
private bool showProgress = false;
#endregion Private Fields
#region Private Properties
private bool confProdActive { get; set; } = false;
private MappaStatoExplModel? currRecMSE { get; set; } = null;
private List<InsManualiModel>? ListDay { get; set; } = new List<InsManualiModel>();
private List<InsManDayDto>? ListDTO { get; set; } = new List<InsManDayDto>();
/// <summary>
/// Eventi inseribili come fermate
/// </summary>
private List<vSelEventiBCodeModel> ListEvents { get; set; } = new List<vSelEventiBCodeModel>();
private List<InsManualiModel>? ListPeriod { get; set; } = new List<InsManualiModel>();
/// <summary>
/// Eventi inseribili come fermate
/// </summary>
private Dictionary<decimal, string> ListTCiclo { get; set; } = new Dictionary<decimal, string>();
//
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);
}
/// <summary>
/// Ricalcolo dati giornalieri
/// </summary>
/// <returns></returns>
private async Task<int> DoRecalcDay()
{
int numChange = 0;
// prendo i dati odierni, e uno x uno ciclo e sistemo...
DateTime lastDate = dtCurr.Date;
List<InsManualiModel> ListChange = new List<InsManualiModel>();
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;
}
/// <summary>
/// Congela la definizione giornaliera di produzione
/// </summary>
/// <returns></returns>
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<bool>("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<InsManualiModel> myListDay = new List<InsManualiModel>();
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;
}
/// <summary>
/// Restitusice la % formattata in invariant con "." e senza spazi prima della %
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private string PercWidth(double value)
{
return value.ToString("P2", CultureInfo.InvariantCulture).Replace(" ", "");
}
/// <summary>
/// Ricalcola dati giornalieri
/// </summary>
/// <param name="dtSel"></param>
private void RecalcDayData(DateTime dtSel)
{
ListDay = new List<InsManualiModel>();
SeqStatus = new List<ManualStatusDTO>();
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<InsManDayDto>();
DateTime oggi = DateTime.Today;
if (RecMSE != null)
{
string IdxMacc = RecMSE.IdxMacchina;
// valori selezionabili x TCiclo
var rawListTCiclo = TabDServ.ListValuesFilt("InsManuali", IdxMacc);
ListTCiclo = new Dictionary<decimal, string>();
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<DateTime, string>();
DateCFF = new Dictionary<DateTime, string>();
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;
}
/// <summary>
/// Salva selezione articolo
/// </summary>
/// <param name="codArt"></param>
private void SetArtSelected(string codArt)
{
if (EditRecord != null)
{
EditRecord.CodArticolo = codArt;
doSearchArt = false;
}
}
#endregion Private Methods
}
}