Files
2026-04-11 09:47:17 +02:00

1907 lines
73 KiB
C#

using global::Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Core.Objects;
using MP.Data;
using MP.Data.DbModels;
using MP.Data.Services;
using NLog;
using System.Text;
using static MP.Core.Objects.Enums;
namespace MP_TAB3.Components
{
public partial class OdlMan
{
#region Public Properties
[Parameter]
public EventCallback<string> E_MachSel { get; set; }
/// <summary>
/// Post update restituisco nuova lista dati
/// </summary>
[Parameter]
public EventCallback<List<MappaStatoExplModel>> E_Updated { get; set; }
[Parameter]
public MappaStatoExplModel? RecMSE
{
get => currRecMSE;
set
{
// salvo SOLO SE non sono in conferma
if (!setupActive && !isProcessing)
{
currRecMSE = value;
}
}
}
#endregion Public Properties
#region Protected Properties
/// <summary>
/// Dati produzione rilevati
/// </summary>
protected StatoProdModel? datiProdAct { get; set; } = null;
/// <summary>
/// Restituisce il codice IdxMacchina dell'altra tavola (se multi) altrimenti la stessa macchina...
/// </summary>
protected string idxMaccAltraTav
{
get
{
string answ = "";
try
{
// verifico se SIA una tavola (ha char "#")
int iSharp = IdxMaccSel.IndexOf('#');
if (iSharp > 0)
{
// ora verifico SE ALTRA TAVOLA ha ODL...
string nomeTav = IdxMaccSel.Substring(iSharp);
string altraTav = nomeTav.Substring(0, nomeTav.Length - 1);
altraTav += nomeTav.EndsWith("1") ? "2" : "1";
// sistemo nome
answ = IdxMaccSel.Replace(nomeTav, altraTav);
}
}
catch
{ }
return answ;
}
}
protected int IdxPOdlSel
{
get => idxPOdlSel;
set
{
setupActive = value != 0;
if (idxPOdlSel != value)
{
idxPOdlSel = value;
showOdlDetail = value > 0;
var pUpd = Task.Run(async () =>
{
await ReloadPOdlDetailData();
});
pUpd.Wait();
}
}
}
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
protected List<vSelOdlModel> ListODL { get; set; } = new List<vSelOdlModel>();
protected List<vSelOdlModel> ListODLAll { get; set; } = new List<vSelOdlModel>();
[Inject]
protected MailService MailServ { get; set; } = null!;
[Inject]
protected MessageService MsgServ { get; set; } = null!;
[Inject]
protected NavigationManager NavMan { get; set; } = null!;
/// <summary>
/// Verifica ODL OK (ovvero caricato x macchina...)
/// </summary>
protected bool odlOk
{
get => IdxOdl > 0;
}
[Inject]
protected StatusData SDService { get; set; } = null!;
protected string SearchPodl
{
get => searchPodl;
set
{
if (searchPodl != value)
{
searchPodl = value;
var pUpd = Task.Run(async () =>
{
await ReloadData(true);
});
pUpd.Wait();
}
}
}
protected bool ShowAll
{
get => showAll;
set
{
if (showAll != value)
{
showAll = value;
var pUpd = Task.Run(async () =>
{
await ReloadData(true);
});
pUpd.Wait();
}
}
}
[Inject]
protected SharedMemService SMServ { get; set; } = null!;
[Inject]
protected TabDataService TabDServ { get; set; } = null!;
/// <summary>
/// Verifica se la tavola SIA in fase di attrezzaggio, ovvero SE:
/// - sia un impianto MULTI (= con + tavole)
/// - sia già attrezzata
/// </summary>
protected bool tavHasOdl
{
get
{
bool answ = false;
// se è multi controllo
if (isMulti)
{
answ = !emptyOdlMacc;
}
return answ;
}
}
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Gestione display avanzamento step
/// </summary>
/// <param name="currStep"></param>
protected async Task advStep(int currStep)
{
currVal = currStep;
nextVal = currVal + 1;
await InvokeAsync(StateHasChanged);
}
protected async Task CheckAttr()
{
// verifico attrezzaggio su macchina corrente o se multi su parent
string idxMacc2check = isMulti ? IdxMaccParent : IdxMaccSel;
StatoMacchineModel rigaStato = TabDServ.StatoMacchina(idxMacc2check);
// calcolo stato attrezzaggio, hard coded!!!
if (isMulti)
{
inAttr = (rigaStato.IdxStato == 2 && tavHasOdl);
}
else
{
inAttr = rigaStato.IdxStato == 2;
}
// se in attr --> carico podlCurr...
if (inAttr && RecMSE != null)
{
await ReloadXDL(true);
}
else
{
// rileggo ODL
await updateIdxOdl();
}
}
/// <summary>
/// Restituisce il codice IdxMacchina dell'impianto PARENT (se multi) altrimenti la stessa macchina...
/// </summary>
protected string getIdxMaccParent()
{
string answ = IdxMaccSel;
// se fosse multi controllo
if (isMulti)
{
// verifico se SIA una tavola (ha char "#")
int iSharp = IdxMaccSel.IndexOf('#');
if (iSharp > 0)
{
// sistemo nome
answ = IdxMaccSel.Substring(0, iSharp);
}
}
return answ;
}
protected void GoToMachDetail()
{
// navigo!
NavMan.NavigateTo($"machine-detail");
}
/// <summary>
/// Annulla setup ODL (come se avesse fatto FINE PROD)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected async Task OdlAnnullaSetup()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler annullare il setup ODL in corso, equivalente a registrare solo la fine produzione?"))
return;
// prima di tutto svuoto dati prod
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
// preparo gestione progress display
MaxVal = 10;
int currStep = 0;
await advStep(currStep);
// leggo idxOdl da ultimo odl attivo x macchina
var odlLast = await TabDServ.OdlCurrByMacc(IdxMaccSel, true);
int idxODLCurr = odlLast.IdxOdl;
int idxEvento = 7; // !!!HARD CODED
await advStep(currStep++);
try
{
// confermo prod vecchio ODL
await confermaProdOdl(true);
await advStep(currStep++);
// processo x macchina selezionata
await TabDServ.OdlFineProd(idxODLCurr, IdxMaccSel, DateTime.Now);
await Task.Delay(50);
await advStep(currStep++);
string evText = "Registrata ANNULLAMENTO ATTREZZAGGIO per ODL {0}";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, idxODLCurr));
await processaEvento(IdxMaccSel, idxEvento, sb.ToString(), idxODLCurr, DateTime.Now);
await advStep(currStep++);
// resetta PODL e rimuove ODL x poi TOGLIERE info di setup su macchina corrente
await TabDServ.OdlClearSetup(idxODLCurr, IdxMaccSel);
await advStep(currStep++);
// se è multi processo ANCHE x altra tavola...
if (isMulti)
{
sb.AppendLine("---");
var tabOdlAltra = await TabDServ.OdlCurrByMacc(idxMaccAltraTav, true);
int idxOdlAltra = tabOdlAltra.IdxOdl;
await Task.Delay(50);
await TabDServ.OdlFineProd(idxOdlAltra, idxMaccAltraTav, DateTime.Now);
sb.AppendLine(String.Format(evText, idxOdlAltra));
await processaEvento(idxMaccAltraTav, idxEvento, String.Format(evText, idxOdlAltra), idxOdlAltra, DateTime.Now);
// resetta PODL e rimuove ODL x poi TOGLIERE info di setup su macchina corrente
await TabDServ.OdlClearSetup(idxOdlAltra, idxMaccAltraTav);
await advStep(currStep++);
}
await advStep(currStep++);
// se è master --> chiamo update child!
if (isMaster)
{
// hard coded 60gg last
await TabDServ.OdlFixMachineSlave(IdxMaccSel, 60, 1);
}
await advStep(currStep++);
// cancella dati correnti ODL
DoRemoveCurrOdlData(false);
await advStep(currStep++);
}
catch
{ }
RecMSE = null;
await InvokeAsync(StateHasChanged);
// refresh finale
checkAll();
await RefreshData();
await CheckAttr();
await advStep(currStep++);
await FlushMpIoOdlCache();
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Effettua ripresa ODL su tavola
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected async Task OdlReopenTav()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler riprendere in carico l'ODL precedente?"))
return;
// prima di tutto svuoto dati prod
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
MaxVal = 3;
int currStep = 0;
await advStep(currStep);
// chiamo stored x riprendere ODL (toglie data chiusura...)
var rowRes = await TabDServ.OdlReopenOdlMacc(IdxMaccSel);
if (rowRes != null && rowRes.IdxOdl > 0)
{
// messaggio utente
string evText = "Registrato riapertura ODL {0} | art {1}";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, rowRes.IdxOdl, rowRes.CodArticolo));
lblOut = sb.ToString();
}
await advStep(currStep++);
RecMSE = null;
await InvokeAsync(StateHasChanged);
// update button x setup da altra tavola...
checkAll();
// faccio refresh e riporto
await RefreshData();
await CheckAttr();
await advStep(currStep++);
await FlushMpIoOdlCache();
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
// chiudo update...
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Effettua split ODL da ALTRA tavola su tav corrente
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected async Task OdlSetSameAsOtherTav()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler impostare lo stesso ODL dell'altra tavola?"))
return;
// prima di tutto svuoto dati prod
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
MaxVal = 3;
int currStep = 0;
await advStep(currStep);
// se ho ODL su altra macchina...
if (IdxOdlAltra > 0)
{
await TabDServ.OdlDividiDaAltraTavola(IdxOdlAltra, MatrOpr, IdxMaccSel);
// messaggio utente
string evText = "Registrata inizio attrezzaggio da split ODL {0} (come da altra tavola)";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, IdxOdlAltra));
lblOut = sb.ToString();
}
await advStep(currStep++);
RecMSE = null;
await InvokeAsync(StateHasChanged);
// update button x setup da altra tavola...
checkAll();
// faccio refresh e riporto
await RefreshData();
await CheckAttr();
await advStep(currStep++);
await FlushMpIoOdlCache();
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
// chiudo update...
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Registrazione Fine Setup / Inizio Produzione
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected async Task OdlSetupEnd()
{
TimeSpan estDur = TimeSpan.FromMinutes((double)tcRichAttr * currPodl.NumPezzi);
string stima = estDur.TotalHours > 1 ? $"{estDur.TotalHours:N1} ore" : $"{estDur.TotalMinutes:N1} min";
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"PODL: {currPodl.IdxPromessa}{Environment.NewLine}Art: [{currPodl.CodArticolo}] {currPodl.DescArticolo}{Environment.NewLine}Pezzi: {currPodl.NumPezzi} * TCiclo: {tcRichAttr:N3}min{Environment.NewLine}Tempo stimato: {stima}{Environment.NewLine}{Environment.NewLine}Confermi la chiusura della fase di attrezzaggio?"))
return;
// prima di tutto svuoto dati prod
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
// preparo gestione progress display
MaxVal = 8;
int currStep = 0;
await advStep(currStep);
await confermaProdOdl(true);
await advStep(currStep++);
// se vedesse TCRich a zero lo reimposta a quello assegnato...
if (tcRichAttr == 0)
{
tcRichAttr = currPodl.Tcassegnato;
}
// leggo idxOdl da ultimo odl attivo x macchina
var currOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, false);
int idxODLStart = currOdl.IdxOdl;
int idxEvento = 1; // !!!HARD CODED
// aggiorno note e tempo setup
await TabDServ.OdlUpdate(idxODLStart, MatrOpr, tcRichAttr, PzPallet, noteAttr);
// se abilitata gestione check TCiclo
if (approvTCEnabled)
{
// controllo se TC Assegnato != TCRichiesto allora invio email x verifiche...
if (currOdl.Tcassegnato != tcRichAttr)
{
// invio email!
await SendWarnTcChangeReq(idxODLStart, currOdl.Tcassegnato, tcRichAttr);
}
}
await advStep(currStep++);
// processo chiusura setup
string evText = "Registrata inizio produzione per ODL {0}";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, idxODLStart));
await processaEvento(IdxMaccSel, idxEvento, sb.ToString(), idxODLStart, DateTime.Now);
// indico INIZIO SETUP su REDIS come EXE della macchina...
string ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now);
TabDServ.addTask4Machine(IdxMaccSel, taskType.stopSetup, $"TS:{ts}|MATR:{MatrOpr}|ODL:{idxODLStart}");
await advStep(currStep++);
// se è multi processo chiusura setup x altra tavola...
if (isMulti)
{
sb.AppendLine("---");
var tabOdlAltra = await TabDServ.OdlCurrByMacc(idxMaccAltraTav, true);
int idxOdlAltra = tabOdlAltra.IdxOdl;
sb.AppendLine(String.Format(evText, idxOdlAltra));
await processaEvento(idxMaccAltraTav, idxEvento, String.Format(evText, idxOdlAltra), idxOdlAltra, DateTime.Now);
// invio su seconda tavola
TabDServ.addTask4Machine(idxMaccAltraTav, taskType.stopSetup, $"TS:{ts}|MATR: {MatrOpr}| Master Machine: {IdxMaccSel}");
}
await advStep(currStep++);
// se è master --> chiamo update child!
if (isMaster)
{
// invio eventi ad IOB slave...
var slaveList = SMServ.ListM2S
.Where(x => x.IdxMacchina.Equals(IdxMaccSel, StringComparison.InvariantCultureIgnoreCase))
.ToList();
foreach (var machine in slaveList)
{
// invio chiusura attrezzaggio
ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now);
string outData = $"TS:{ts}|MATR:{MatrOpr}|ODL:{idxODLStart}";
await processaEvento(machine.IdxMacchinaSlave, idxEvento, sb.ToString(), idxODLStart, DateTime.Now);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.fixStopSetup, outData);
}
// hard coded 60gg last
await TabDServ.OdlFixMachineSlave(IdxMaccSel, 60, 1);
}
await advStep(currStep++);
// se c'è gestione SchedaTecnica --> chiamo procedura update x lotti
if (enableSchedaTecnica)
{
await TabDServ.ElencoLottiUpsertByOdl(idxODLStart, true);
}
await advStep(currStep++);
// riporto stringa
lblOut = sb.ToString().Replace("---", "<br/>");
// update buttons...
checkAll();
// reset vari
IdxPOdlSel = 0;
inAttr = false;
RecMSE = null;
await InvokeAsync(StateHasChanged);
// faccio refresh e riporto
await RefreshData();
await CheckAttr();
await advStep(currStep++);
await FlushMpIoOdlCache();
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
// chiudo update...
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Dichiarazione inizio attrezzaggio PODL indicato
/// </summary>
/// <returns></returns>
protected async Task OdlSetupStart()
{
TimeSpan estDur = TimeSpan.FromMinutes((double)tcRichAttr * currPodl.NumPezzi);
string stima = estDur.TotalHours > 1 ? $"{estDur.TotalHours:N1} ore" : $"{estDur.TotalMinutes:N1} min";
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"PODL: {currPodl.IdxPromessa}{Environment.NewLine}Art: [{currPodl.CodArticolo}] {currPodl.DescArticolo}{Environment.NewLine}Pezzi: {currPodl.NumPezzi} * TCiclo: {tcRichAttr:N3}min{Environment.NewLine}Tempo stimato: {stima}{Environment.NewLine}{Environment.NewLine}Confermi inizio della fase di attrezzaggio?"))
return;
/***************************************************
* comprende gestione machineSlave x fix ODL master --> slave
***************************************************/
// preparo gestione progress display
MaxVal = 10;
int currStep = 0;
// elimino dati status...
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
SDService.MachProdStRem(IdxMaccParent);
if (isMulti)
{
try
{
StatoMacchineModel rigaStato = TabDServ.StatoMacchina(IdxMaccParent);
// controllo se NON SONO già in attrezzaggio...
inAttr = (rigaStato.IdxStato == 2);
}
catch
{ }
}
await advStep(currStep);
DateTime adesso = DateTime.Now;
await advStep(currStep++);
// proseguo
int idxODL_curr = 0;
await confermaProdOdl(false);
await advStep(currStep++);
if (IdxPOdlSel > 0)
{
// se vedesse TCRich a zero lo reimposta a quello assegnato...
if (tcRichAttr == 0)
{
tcRichAttr = currPodl.Tcassegnato;
}
if (enableSplitODL && !forceCloseOdl)
{
// splitto VECCHIO ODL (se fosse rimasto qualcosa da produrre e ne sia rimasto uno.......)
try
{
var currOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, false);
int idxODLTemp = currOdl.IdxOdl;
decimal tcAss = currOdl.Tcassegnato;
await TabDServ.OdlSplit(idxODLTemp, MatrOpr, IdxMaccSel, tcAss, PzPallet, $"inizio attrezzaggio, Sospensione ODL {idxODLTemp}, generato residuo con pari TCiclo: {tcAss}", false, 0);
// se fosse multi processo ANCHE x altra tavola...
if (isMulti)
{
var otherOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, false);
int idxODLAlt = otherOdl.IdxOdl;
decimal tcAssAlt = otherOdl.Tcassegnato;
await TabDServ.OdlSplit(idxODLAlt, MatrOpr, idxMaccAltraTav, tcAssAlt, PzPallet, $"Inizio attrezzaggio, Sospensione ODL {idxODLAlt}, generato residuo con pari TCiclo: {tcAssAlt}", false, 0);
}
}
catch (Exception exc)
{
Log.Error($"Error StartSetup.01{Environment.NewLine}{exc}");
}
}
await advStep(currStep++);
// fix idxmacchina selezionata (x ogni macchina, singola o multi...)
currPodl.IdxMacchina = IdxMaccSel;
// 2018.07.24 verifico se devo lavorare come ODL classico o come RPO (Richiesta /
// Promessa / ODL)
if (enableRPO)
{
// creo nuovo ODL da promessa ed associo
await TabDServ.PODL_startSetup(currPodl, MatrOpr, tcRichAttr, PzPallet, noteAttr, adesso);
// salvo ODL attrezzato
var newOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, true);
idxODL_curr = newOdl.IdxOdl;
}
// ODL classico
else
{
// avvio NUOVO ODL
await TabDServ.OdlInizioSetup(IdxPOdlSel, MatrOpr, IdxMaccSel, tcRichAttr, PzPallet, noteAttr);
// salvo ODL Current
idxODL_curr = IdxPOdlSel;
}
await advStep(currStep++);
// process evento
int idxEvento = 2; // !!!HARD CODED
string evText = "Registrato inizio attrezzaggio per ODL {0}";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, idxODL_curr));
DateTime dtEvAttr = DateTime.Now;
await processaEvento(IdxMaccSel, idxEvento, sb.ToString(), idxODL_curr, dtEvAttr);
await advStep(currStep++);
// aggiungo articolo, commessa, richiesta pezzi...
try
{
await DoSendTaskOdl(idxODL_curr);
await advStep(currStep++);
}
catch (Exception exc)
{
Log.Error($"Eccezione in invio task4machine{Environment.NewLine}{exc}");
}
// se fosse multi CHIUDO ODL x altra tavola...
if (isMulti)
{
// se NON sono in attrezzaggio// riattrezzaggio...
if (!inAttr && !showSplitOdlRiattr)
{
int idxOdlAltra = 0;
try
{
var tabOdlAltra = await TabDServ.OdlCurrByMacc(idxMaccAltraTav, true);
idxOdlAltra = tabOdlAltra.IdxOdl;
}
catch (Exception exc)
{
Log.Error($"Errore Durante recupero idxOdlAltra {Environment.NewLine}{exc}");
}
// procedo se ho ODL
if (idxOdlAltra > 0)
{
sb.AppendLine("---");
await TabDServ.OdlFineProd(idxOdlAltra, idxMaccAltraTav, dtEvAttr);
//await Task.Delay(50);
evText = $"Registrato inizio attrezzaggio per ODL {idxOdlAltra} (setup seconda tavola)";
sb.AppendLine(evText);
// attrezzo con ritardo
await processaEvento(idxMaccAltraTav, idxEvento, evText, idxOdlAltra, dtEvAttr.AddMilliseconds(50));
}
lblOut = sb.ToString().Replace("---", "<br/>");
}
// update buttons...
checkAll();
}
await advStep(currStep++);
// se fosse master --> chiamo update child!
if (isMaster)
{
// hard coded 60gg last
await TabDServ.OdlFixMachineSlave(IdxMaccSel, 60, 1);
}
await advStep(currStep++);
// resetto contapezzi redis...
await TabDServ.saveCounter(IdxMaccSel, "0");
// imposto ODL su redis...
TabDServ.saveCurrODL(IdxMaccSel, idxODL_curr);
await advStep(currStep++);
}
else
{
lblOut = "Selezionare un ORDINE valido!";
}
// refresh finale
var tmpTCR = tcRichAttr;
// faccio refresh e riporto
await TabDServ.FlushOdlCache();
IdxPOdlSel = 0;
RecMSE = null;
await FlushMpIoOdlCache();
await InvokeAsync(StateHasChanged);
await RefreshData();
await CheckAttr();
inAttr = true;
tcRichAttr = tmpTCR;
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
protected override void OnInitialized()
{
//baseLang = SMServ.GetConf("baseLang");
numDayOdl = SMServ.GetConfInt("numDaySelOdl");
forceCloseOdl = SMServ.GetConfBool("chkCloseOdl");
confRett = SMServ.GetConfBool("confRett");
enableSplitODL = SMServ.GetConfBool("enableSplitODL");
modoConfProd = SMServ.GetConfInt("modoConfProd");
enableRPO = SMServ.GetConfBool("enableRPO");
enableAnnullaSetup = SMServ.GetConfBool("enableAnnullaSetup");
enableSchedaTecnica = SMServ.GetConfBool("enableSchedaTecnica");
enableFixSetup = SMServ.GetConfBool("OptEnableFixSetup");
showChkCloseOdlVal = SMServ.GetConfBool("showChkCloseOdl");
showReopenOdlTav = SMServ.GetConfBool("showReopenOdlTav");
showSplitOdlOnTav = SMServ.GetConfBool("showSplitOdlOnTav");
enableRiattrezzaggio = SMServ.GetConfBool("enableRiattrezzaggio");
showOdlProvv = SMServ.GetConfBool("showOdlProvv");
gPeriodReopenOdlTav = SMServ.GetConfInt("gPeriodReopenOdlTav");
approvTCEnabled = SMServ.GetConfBool("OptAdmApprTempiEnabled");
string rawEmailDest = SMServ.GetConf("_adminEmail");
ShowAll = SMServ.GetConfBool("TAB_ShowAllPOdl");
emailAdmDest = rawEmailDest.Split(',').ToList();
}
protected override async Task OnParametersSetAsync()
{
if (!setupActive && !isProcessing)
{
if (RecMSE != null && !RecMSE.MostlyEquals(lastRecMSE))
{
if (string.IsNullOrEmpty(IdxMaccSel))
{
IdxMaccSel = RecMSE.IdxMacchina;
}
isMulti = SMServ.DictMacchMulti[RecMSE.IdxMacchina] == 1;
if (isMulti)
{
var idxMSel = MsgServ.UserPrefGet(IdxMaccSel);
if (!string.IsNullOrEmpty(idxMSel))
{
IdxMaccSel = idxMSel;
}
}
IdxMaccParent = getIdxMaccParent();
checkAll();
// verifica stato InAttr
await CheckAttr();
//salvo lastRec...
lastRecMSE = RecMSE;
await ReloadData(true);
}
}
// verifica conferma produzione
datiProdAct = await TabDServ.StatoProdMacchinaAsync(IdxMaccSel, DateTime.Now);
await checkConfProd();
}
/// <summary>
/// Chiusura produzione ODL corrente
/// </summary>
/// <returns></returns>
protected async Task ProdEnd()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi fine produzione?"))
return;
// prima di tutto svuoto dati prod
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
// preparo gestione progress display
MaxVal = 7;
int currStep = 0;
await advStep(currStep);
// leggo idxOdl da ultimo odl attivo x macchina
var currOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, false);
SDService.MachProdStRem(IdxMaccSel);
int idxODLCurr = currOdl.IdxOdl;
int idxEvento = 7;
// !!!HARD CODED confermo prod vecchio ODL
await confermaProdOdl(false);
await advStep(currStep++);
// se chk flaggato ovvero richiesta di chiudere ODL procedo come prima (chiudendo ODL
// senza averne altri...)
if (forceCloseOdl)
{
// aggiungo try/catch x capire se sia qui che si "impasta" in chiusura ODL
try
{
// processo x macchina selezionata
await TabDServ.OdlFineProd(idxODLCurr, IdxMaccSel, DateTime.Now);
await Task.Delay(50);
string evText = "Registrata fine produzione per ODL {0}";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, idxODLCurr));
await processaEvento(IdxMaccSel, idxEvento, sb.ToString(), idxODLCurr, DateTime.Now);
await advStep(currStep++);
// se è multi processo ANCHE x altra tavola...
if (isMulti)
{
sb.AppendLine("---");
var tabOdlAltra = await TabDServ.OdlCurrByMacc(idxMaccAltraTav, true);
int idxOdlAltra = tabOdlAltra.IdxOdl;
await TabDServ.OdlFineProd(idxOdlAltra, idxMaccAltraTav, DateTime.Now);
await Task.Delay(50);
sb.AppendLine(String.Format(evText, idxOdlAltra));
await processaEvento(idxMaccAltraTav, idxEvento, String.Format(evText, idxOdlAltra), idxOdlAltra, DateTime.Now);
}
await advStep(currStep++);
// se è master --> chiamo update child!
if (isMaster)
{
// hard coded 60gg last
await TabDServ.OdlFixMachineSlave(IdxMaccSel, 60, 1);
}
await advStep(currStep++);
// riporto stringa
lblOut = sb.ToString().Replace("---", "<br/>");
}
catch (Exception exc)
{
Log.Error($"Eccezione in operazione chiusura ODL!{Environment.NewLine}{exc}");
// navigo!
NavMan.NavigateTo($"machine-detail");
}
}
// altrimenti split ODL x completare IN FUTURO la produzione...
else
{
try
{
// effettuo split su nuovo ODL
await TabDServ.OdlSplit(idxODLCurr, MatrOpr, IdxMaccSel, currOdl.Tcassegnato, PzPallet, $"Fine Produzione, Sospensione ODL {idxODLCurr}, generato residuo con pari TCiclo: {currOdl.Tcassegnato}", false, 0);
// processo chiusura setup
await processaEvento(IdxMaccSel, idxEvento, $"Registrata fine produzione per ODL {idxODLCurr}, nuovo ODL per quantità residua", idxODLCurr, DateTime.Now);
await advStep(currStep++);
// se è multi processo ANCHE x altra tavola...
if (isMulti)
{
var tabOdlAltra = await TabDServ.OdlCurrByMacc(idxMaccAltraTav, true);
int idxOdlAltra = tabOdlAltra.IdxOdl;
// effettuo split su nuovo ODL
await TabDServ.OdlSplit(idxOdlAltra, MatrOpr, idxMaccAltraTav, tabOdlAltra.Tcassegnato, PzPallet, $"Fine Produzione, Sospensione ODL {idxOdlAltra}, generato residuo con pari TCiclo: {tabOdlAltra.Tcassegnato}", false, 0);
// processo chiusura setup
await processaEvento(idxMaccAltraTav, idxEvento, $"Registrata fine produzione per ODL {idxOdlAltra}, nuovo ODL per quantità residua", idxOdlAltra, DateTime.Now);
}
await advStep(currStep++);
// se è master --> chiamo update child!
if (isMaster)
{
// hard coded 60gg last
await TabDServ.OdlFixMachineSlave(IdxMaccSel, 60, 1);
}
await advStep(currStep++);
}
catch (Exception exc)
{
Log.Error($"Eccezione in operazione Chiusura + Split ODL su nuovo! {Environment.NewLine}{exc}");
// navigo!
NavMan.NavigateTo($"machine-detail");
}
}
// aggiunto esplicita endProd
TabDServ.addTask4Machine(IdxMaccSel, taskType.endProd, "");
if (isMaster)
{
// calcolo gli slave...
var slaveList = SMServ.ListM2S
.Where(x => x.IdxMacchina.Equals(IdxMaccSel, StringComparison.InvariantCultureIgnoreCase))
.ToList();
foreach (var machine in slaveList)
{
// invio task x end produzione...
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.endProd, "");
}
}
await advStep(currStep++);
await FlushMpIoOdlCache();
// faccio refresh e riporto
IdxPOdlSel = 0;
RecMSE = null;
await InvokeAsync(StateHasChanged);
currOdl = new ODLExpModel();
inAttr = false;
IdxPOdlSel = 0;
forceCloseOdl = true;
//await Task.Delay(250);
await RefreshData();
await CheckAttr();
await advStep(currStep++);
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
protected async Task refreshAfterFixOdl(bool has2Refr)
{
if (has2Refr)
{
// prima di tutto svuoto dati prod
SDService.MachProdStRem(IdxMaccSel);
// update buttons...
checkAll();
// reset vari
IdxPOdlSel = 0;
inAttr = false;
IdxPOdlSel = 0;
await RefreshData();
await CheckAttr();
await InvokeAsync(StateHasChanged);
}
}
protected async Task RefreshData()
{
// refresh tabella dati tablet...
RecMSE = null;
// rileggo e salvo..
var ListMSE = await SDService.MseGetAll(true);
if (ListMSE != null)
{
// salvo in LocalStorage...
await MsgServ.SaveMse(ListMSE);
// aggiorno MSE attuale
RecMSE = ListMSE.Find(x => x.IdxMacchina == IdxMaccSel);
await E_Updated.InvokeAsync(ListMSE);
}
// update dati liste ODL
await ReloadData(true);
}
protected void SaveTCRich(decimal newTCRich)
{
tcRichAttr = newTCRich;
}
protected void SearchPodlReset()
{
SearchPodl = "";
}
protected async Task SendFixEndSetup()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi invio FIX chiusura attrezzaggio ad impianto?"))
return;
// prima di tutto svuoto dati prod
SDService.MachProdStRem(IdxMaccSel);
string ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now);
string outData = $"TS:{ts}|MATR:{MatrOpr}|ODL:{IdxOdl}";
TabDServ.addTask4Machine(IdxMaccSel, taskType.fixStopSetup, outData);
outData = "Inserita richiesta invio Fix chiusura attrezzaggio " + outData;
lblOut = outData;
// se è master --> chiamo update child!
if (isMaster)
{
// invio eventi ad IOB slave...
var slaveList = SMServ.ListM2S
.Where(x => x.IdxMacchina.Equals(IdxMaccSel, StringComparison.InvariantCultureIgnoreCase))
.ToList();
foreach (var machine in slaveList)
{
// invio chiusura attrezzaggio
outData = $"TS:{ts}|MATR:{MatrOpr}|ODL:{IdxOdl}|master machine:{IdxMaccSel}";
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.fixStopSetup, outData);
}
}
}
protected async Task SendWarnTcChangeReq(int idxOdl, decimal tcAss, decimal tcRich)
{
// carico altri parametri email...
string oggetto = $"{SMServ.GetConf("Cliente")} | {SMServ.GetConf("oggettoChgTc")}"; ;
string corpoChgTc = SMServ.GetConf("corpoChgTc");
string mittente = SMServ.GetConf("_fromEmail");
string baseUrlAdmin = SMServ.GetConf("baseUrlAdmin");
string pageUrlApprODL = SMServ.GetConf("pageUrlApprODL");
string pageUrl = $"{baseUrlAdmin}{pageUrlApprODL}";
string corpo = $"<b>ODL: {idxOdl} | TC Assegnato: {tcAss:N3} | TC Rich: {tcRich}</b>{Environment.NewLine}{Environment.NewLine}";
corpo += string.Format(corpoChgTc, Environment.NewLine, pageUrl);
corpo = corpo.Replace($"{Environment.NewLine}", "<br/>");
MailKitMailData mData = new MailKitMailData()
{
From = mittente,
To = emailAdmDest,
Subject = oggetto,
Body = corpo
};
bool done = await MailServ.SendAsync(mData);
if (done)
{
Log.Info($"Inviata email notifica TC da approvare per ODL {idxOdl} inviato a {string.Join(",", emailAdmDest)}");
}
else
{
Log.Error($"Errore in invio email notifica TC da approvare per ODL {idxOdl} | tentato invio a {string.Join(",", emailAdmDest)}");
}
}
protected async Task SetMacc(string selIdxMacc)
{
// imposto macchina
IdxMaccSel = selIdxMacc;
// recupero dati
RecMSE = TabDServ.MseGetSub(IdxMaccParent, selIdxMacc, true);
await ReloadData(true);
await CheckAttr();
if (showOdlDetail || inAttr)
{
isProcessing = true;
await ReloadXDL(true);
isProcessing = false;
}
await E_MachSel.InvokeAsync(selIdxMacc);
}
protected async Task ShowRiattrezzaggio()
{
showSplitOdlRiattr = !showSplitOdlRiattr;
if (showSplitOdlRiattr)
{
await ReloadXDL(true);
}
}
/// <summary>
/// Esegue split ODL corrente
/// </summary>
/// <returns></returns>
protected async Task SplitOdl()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi richiesta riattrezzaggio ODL, con conseguente chiusura ODL corrente + split nuovo ODL con TC {tcRichAttr:N3}?"))
return;
// prima di tutto svuoto dati prod
isProcessing = true;
SDService.MachProdStRem(IdxMaccSel);
// preparo gestione progress display
MaxVal = 10;
int currStep = 0;
await advStep(currStep);
// se vedesse TCRich a zero lo reimposta a quello assegnato...
if (tcRichAttr == 0)
{
tcRichAttr = currPodl.Tcassegnato;
}
// leggo idxOdl da ultimo odl attivo x macchina
var currOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, false);
int idxODLSplit = currOdl.IdxOdl;
int idxEvento = 1; // !!!HARD CODED
await advStep(currStep++);
// confermo prod vecchio ODL
await confermaProdOdl(false);
await advStep(currStep++);
// effettuo split su nuovo ODL
await TabDServ.OdlSplit(idxODLSplit, MatrOpr, IdxMaccSel, tcRichAttr, PzPallet, noteAttr, true, 0);
await advStep(currStep++);
// se c'è gestione SchedaTecnica --> chiamo procedura update x lotti
if (enableSchedaTecnica)
{
await TabDServ.ElencoLottiUpsertByOdl(idxODLSplit, true);
}
await advStep(currStep++);
// processo chiusura setup
string evText = "Registrato Riattrezzaggio ODL (old :{0})";
StringBuilder sb = new StringBuilder();
sb.AppendLine(String.Format(evText, idxODLSplit));
await processaEvento(IdxMaccSel, idxEvento, sb.ToString(), idxODLSplit, DateTime.Now);
await advStep(currStep++);
// update buttons...
checkAll();
// reset vari
IdxPOdlSel = 0;
inAttr = false;
RecMSE = null;
await advStep(currStep++);
// faccio refresh e riporto
await RefreshData();
await CheckAttr();
await advStep(currStep++);
showSplitOdlRiattr = false;
await ReloadXDL(true);
// invio richiesta reset NUOVO ODL...
if (IdxOdl > 0)
{
await DoSendTaskOdl(IdxOdl);
}
await advStep(currStep++);
// notifica...
if (isMulti)
{
await E_MachSel.InvokeAsync(idxMaccAltraTav);
await Task.Delay(delayUpd);
}
else
{
TabDServ.NotifyDataInvalidated(IdxMaccSel);
}
await E_MachSel.InvokeAsync(IdxMaccSel);
// chiudo update...
isProcessing = false;
await InvokeAsync(StateHasChanged);
}
protected async Task ToggleOdlDetail()
{
showOdlDetail = !showOdlDetail;
// se devo mostrare, carico dati ODL!
if (showOdlDetail)
{
await ReloadXDL(true);
}
}
protected string Traduci(string lemma)
{
return SMServ.Traduci($"{baseLang}_{lemma}".ToUpper());
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private bool approvTCEnabled = false;
private bool confRett = true;
private double currVal = 0;
/// <summary>
/// Tempo di delay x simulare cambio idxMaccSub
/// </summary>
private int delayUpd = 1000;
private List<string> emailAdmDest = new List<string>();
private bool enableAnnullaSetup = false;
private bool enableFixSetup = false;
private bool enableRiattrezzaggio = false;
private bool enableRPO = true;
private bool enableSchedaTecnica = false;
private bool enableSplitODL = false;
private int expTimeMsec = 500;
private bool forceCloseOdl = true;
private int gPeriodReopenOdlTav = 1;
private int idxPOdlSel = 0;
private bool isMaster = false;
private bool isMulti = false;
private bool isProcessing = false;
private bool isSlave = false;
private int lastIdxPOdl = 0;
private string lblOut = "";
private int MaxVal = 10;
private int modoConfProd = 0;
private double nextVal = 0;
private string noteAttr = "";
private int numDayOdl = 5;
private int PzPallet = 0;
private string searchPodl = "";
private bool showAll = false;
private bool showChkCloseOdlVal = false;
private bool showOdlDetail = false;
private bool showOdlProvv = false;
private bool showPOdlData = true;
private bool showReopenOdlTav = false;
private bool showSplitOdlOnTav = false;
private bool showSplitOdlRiattr = false;
#endregion Private Fields
#region Private Properties
private bool annullaSetupVisible
{
get
{
bool answ = inAttr && enableAnnullaSetup && RecMSE != null && RecMSE.PezziConf == 0;
// forzato: se è doppia tavola è SEMPRE false...
if (isMulti)
{
answ = false;
}
// 2024.04.15 deciso con Gian di togliere la possibilità di annullare su doppia tavola (problema di doppio reset con conferme aperte su altra tavola)
//DateTime adesso = DateTime.Now;
//if (isMulti)
//{
// var pUpd = Task.Run(async () =>
// {
// // controllo ANCHE che la tav correntemente selezionata NON abbia pezzi da confermare
// datiProdAct = await TabDServ.StatoProdMacchinaAsync(IdxMaccMain, adesso);
// answ = datiProdAct.PzConfBuoni == 0 && datiProdAct.Pz2RecScarto == 0;
// });
// pUpd.Wait();
//}
return answ;
}
}
private string baseLang
{
get => MsgServ.UserPrefGet("Lang");
}
private bool cancelSetupEnabled
{
//get => InAttr && enableSchedaTecnica && enableAnnullaSetup;
get => inAttr && enableAnnullaSetup;
}
private ODLExpModel currOdl { get; set; } = new ODLExpModel();
private PODLExpModel currPodl { get; set; } = new PODLExpModel();
private MappaStatoExplModel? currRecMSE { get; set; } = null;
/// <summary>
/// Verifica se l'ALTRA macchina NON abbia ODL valido (== 0)
/// </summary>
private bool emptyOdlAltraMacc
{
get => IdxOdlAltra == 0;
}
/// <summary>
/// Verifica se la macchina NON abbia ODL valido (== 0)
/// </summary>
private bool emptyOdlMacc
{
get => IdxOdl == 0;
}
private bool endProdDisabled
{
get => !odlOk || needConfProd;
}
/// <summary>
/// Variabile idxMacc parent x selezione ODL
/// </summary>
private string IdxMaccParent { get; set; } = "";
private string IdxMaccSel { get; set; } = "";
/// <summary>
/// Valore calcolato key ODL corrente...
/// </summary>
private int IdxOdl { get; set; } = 0;
/// <summary>
/// Valore calcolato key ODL altra tavola attivo...
/// </summary>
private int IdxOdlAltra { get; set; } = 0;
private bool inAttr { get; set; } = false;
private bool isLoading { get; set; } = false;
private MappaStatoExplModel? lastRecMSE { get; set; } = null;
private string lblWarnBody
{
get => odlOk ? Traduci("ConfProdBeforeContinueBody") : Traduci("setOdlBeforeContinueBody");
}
private string lblWarnHead
{
get => odlOk ? Traduci("ConfProdBeforeContinueHead") : Traduci("setOdlBeforeContinueHead");
}
private int MatrOpr
{
get => MsgServ.MatrOpr;
}
private bool needConfProd { get; set; } = false;
private int numPz2Conf
{
get
{
int answ = -1;
if (datiProdAct != null)
{
answ = datiProdAct.Pz2RecTot;
}
else
{
answ = RecMSE != null ? RecMSE.PezziProd - RecMSE.PezziConf : 0;
}
return answ;
}
}
private int numRil2Conf
{
get
{
int answ = -1;
if (datiProdAct != null)
{
answ = datiProdAct.Pz2RecRilav;
}
return answ;
}
}
private int numSca2Conf
{
get
{
int answ = -1;
if (datiProdAct != null)
{
answ = datiProdAct.Pz2RecScarto;
}
return answ;
}
}
private bool setupActive { get; set; } = false;
/// <summary>
/// Verifica visibilità btn riprendi ODL su 2° tavola SE:
/// - sia un impianto MULTI (= con + tavole)
/// - sia disattrezzata la tavola
/// - in tab congif: se sia abilitato la ripresa ODL sulla seconda tavola
/// - in tab config: sia il grace period
/// - NON SIANO passati i minuti indicati dalla chiusura
/// </summary>
private bool showReopOdlTav
{
get
{
bool answ = false;
// se è multi controllo
if (isMulti)
{
// verifico se NON HA ODL...
if (emptyOdlMacc)
{
if (!emptyOdlAltraMacc)
{
// verifico SE siamo nel gracePeriod... chiuso da meno di 1h
DateTime adesso = DateTime.Now;
DateTime dtChiusura = DateTime.Now.AddHours(-1);
try
{
var lastOdl = TabDServ.OdlLastByMacc(IdxMaccSel, true);
if (lastOdl != null)
{
dtChiusura = lastOdl.DataFine ?? DateTime.Now.AddHours(-1);
}
}
catch
{ }
// ora verifico SE E SOLO SE è ANCORA in attrezzaggio ora verifico SE
// ALTRA TAVOLA ha ODL...
if (dtChiusura.AddMinutes(gPeriodReopenOdlTav) > adesso)
{
answ = showReopenOdlTav;
}
}
}
}
return answ;
}
}
/// <summary>
/// Verifica visibilità btn split ODL su 2° tavola SE:
/// - sia un impianto MULTI (= con + tavole)
/// - sia già attrezzata la prima tavola
/// - in tab Congif: se sia abilitato lo split ODL sulla seconda tavola
/// - la macchina SIA ANCORA in attrezzaggio (2019.07.08) = 2
/// </summary>
private bool showSplitOdlOnTavVal
{
get
{
bool answ = false;
// se è multi controllo
if (isMulti)
{
// verifico se NON HA ODL ma ce l'ha altra tavola...
if (emptyOdlMacc)
{
// ora verifico SE ALTRA TAVOLA ha ODL...
if (!emptyOdlAltraMacc)
{
answ = showSplitOdlOnTav;
}
}
}
return answ;
}
}
private decimal tcRichAttr { get; set; } = 0;
private string txtBtnOdlDetail
{
get => showOdlDetail ? "Nascondi Dettaglio PODL" : "MOSTRA Dettaglio ODL Corrente";
}
private string txtForceCloseOdl
{
get => forceCloseOdl ? Traduci("ForceCloseODL") : Traduci("SplitCurrODL");
}
#endregion Private Properties
#region Private Methods
private void checkAll()
{
if (string.IsNullOrEmpty(IdxMaccParent))
{
if (isMulti)
{
IdxMaccParent = getIdxMaccParent();
}
else
{
IdxMaccParent = IdxMaccSel;
}
}
}
private async Task checkConfProd()
{
// calcolo conferma prod...
needConfProd = RecMSE != null && datiProdAct != null;
if (datiProdAct != null)
{
needConfProd = (datiProdAct.Pz2RecTot > 0 || datiProdAct.Pz2RecScarto > 0 || datiProdAct.Pz2RecRilav > 0) && !isSlave;
// se è multi controllo anche altra tavola...
if (isMulti && !needConfProd)
{
// verifica conferma produzione
var datiProdAltra = await TabDServ.StatoProdMacchinaAsync(idxMaccAltraTav, DateTime.Now);
needConfProd = (datiProdAltra.Pz2RecTot > 0 || datiProdAltra.Pz2RecScarto > 0 || datiProdAltra.Pz2RecRilav > 0) && !isSlave;
}
if (needConfProd)
{
StateHasChanged();
}
}
}
/// <summary>
/// verifica se sia necessario confermare la prod dell'ODL precedente prima di chiudere e lo
/// fa in automatico...
/// </summary>
/// <param name="confZero">boolean, true = deve confermare 0 pezzi (es. in setup)</param>
private async Task confermaProdOdl(bool confZero)
{
// 2016.11.17 NOTA: introdotti scarti, li confermiamo SEMPRE a zero se in setup, per da
// valutare SE a FINE ATTREZZAGGIO chiedere num pezzi e num scarti (saldo zero buoni) da inserire...
bool fatto = false;
DateTime adesso = DateTime.Now;
if (confZero)
{
// confermo produzione ZERO pezzi (in setup)
if (confRett)
{
// confermo al netto dei pezzi lasciati...
fatto = TabDServ.ConfermaProdMacchinaFull(IdxMaccSel, modoConfProd, 0, 0, 0, adesso, MatrOpr);
}
else
{
fatto = TabDServ.ConfermaProdMacchina(IdxMaccSel, modoConfProd, 0, 0, adesso, MatrOpr);
}
}
else // se NON sono in setup verifico se ho pz da confermare
{
// recupero pz da confermare
datiProdAct = await TabDServ.StatoProdMacchinaAsync(IdxMaccSel, adesso);
await checkConfProd();
if (datiProdAct.Pz2RecTot > 0)
{
// confermo produzione ZERO pezzi (in setup)
if (confRett)
{
// confermo al netto dei pezzi lasciati...
fatto = TabDServ.ConfermaProdMacchinaFull(IdxMaccSel, modoConfProd, datiProdAct.Pz2RecTot, 0, 0, adesso, MatrOpr);
}
else
{
fatto = TabDServ.ConfermaProdMacchina(IdxMaccSel, modoConfProd, datiProdAct.Pz2RecTot, 0, adesso, MatrOpr);
}
}
}
}
/// <summary>
/// Rimozione dati e parametri (TAB e su PLC) x ODL corrente
/// </summary>
private void DoRemoveCurrOdlData(bool nav2detail)
{
// invio task x end produzione...
string setArtVal = "NO ART";
string setPzCommVal = "0";
string setCommVal = $"NO ODL";
// FIXME TODO: scrivere come sotto? testare valvital x linea LASCO
TabDServ.addTask4Machine(IdxMaccSel, taskType.endProd, "");
TabDServ.addTask4Machine(IdxMaccSel, taskType.setArt, setArtVal);
TabDServ.addTask4Machine(IdxMaccSel, taskType.setPzComm, setPzCommVal);
TabDServ.addTask4Machine(IdxMaccSel, taskType.setComm, setCommVal);
// se è master --> chiamo update child!
if (isMaster)
{
// calcolo gli slave...
var slaveList = SMServ.ListM2S
.Where(x => x.IdxMacchina.Equals(IdxMaccSel, StringComparison.InvariantCultureIgnoreCase))
.ToList();
foreach (var machine in slaveList)
{
// invio task x end produzione...
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.endProd, "");
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setArt, setArtVal);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setPzComm, setPzCommVal);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setComm, setCommVal);
}
}
// se richiesto rimando a pagina dettaglio...
if (nav2detail)
{
NavMan.NavigateTo("machine-detail", true);
}
}
/// <summary>
/// Invio set informazioni x segnalare setupODL
/// </summary>
/// <param name="idxODL_curr"></param>
/// <returns></returns>
private async Task DoSendTaskOdl(int idxODL_curr)
{
// indico INIZIO SETUP su REDIS come EXE della macchina...
string ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now);
string outData = $"TS:{ts}|MATR:{MatrOpr}|ODL:{idxODL_curr}";
var datiODL = await TabDServ.OdlCurrByMacc(IdxMaccSel, true);
string setArtVal = $"{datiODL.CodArticolo}";
string setPzCommVal = $"{datiODL.NumPezzi}";
string setCommVal = $"ODL{datiODL.IdxOdl:00000000}";
// FIXME TODO: scrivere come sotto? testare valvital x linea LASCO
TabDServ.addTask4Machine(IdxMaccSel, taskType.startSetup, outData);
TabDServ.addTask4Machine(IdxMaccSel, taskType.setArt, setArtVal);
TabDServ.addTask4Machine(IdxMaccSel, taskType.setComm, setCommVal);
TabDServ.addTask4Machine(IdxMaccSel, taskType.setPzComm, setPzCommVal);
TabDServ.addTask4Machine(IdxMaccSel, taskType.forceResetPzCount, "0");
TabDServ.MachineParamUpdate(IdxMaccSel, "setArt", setArtVal);
TabDServ.MachineParamUpdate(IdxMaccSel, "setComm", setCommVal);
TabDServ.MachineParamUpdate(IdxMaccSel, "setPzComm", setPzCommVal);
TabDServ.MachineParamUpdate(IdxMaccSel, "forceResetPzCount", "0");
TabDServ.addTask4Machine(IdxMaccSel, taskType.setParameter, "ForceUpdate");
//await advStep(currStep++);
// li aggiungo ANCHE sui PLC slave se ci sono...
if (isMaster)
{
// calcolo gli slave...
var slaveList = SMServ.ListM2S
.Where(x => x.IdxMacchina.Equals(IdxMaccSel, StringComparison.InvariantCultureIgnoreCase))
.ToList();
foreach (var machine in slaveList)
{
outData = $"TS:{ts}|MATR:{MatrOpr}|Master Machine:{IdxMaccSel}";
// invio chiusura attrezzaggio
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.startSetup, outData);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setArt, setArtVal);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setComm, setCommVal);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setPzComm, setPzCommVal);
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.forceResetPzCount, "0");
TabDServ.MachineParamUpdate(machine.IdxMacchinaSlave, "setArt", setArtVal);
TabDServ.MachineParamUpdate(machine.IdxMacchinaSlave, "setComm", setCommVal);
TabDServ.MachineParamUpdate(machine.IdxMacchinaSlave, "setPzComm", setPzCommVal);
TabDServ.MachineParamUpdate(machine.IdxMacchinaSlave, "forceResetPzCount", "0");
TabDServ.addTask4Machine(machine.IdxMacchinaSlave, taskType.setParameter, "ForceUpdate");
}
}
}
private void fixTcNotePzPallet(bool reloadFromOdl)
{
if (tcRichAttr == 0 || string.IsNullOrEmpty(noteAttr) || PzPallet == 0)
{
tcRichAttr = reloadFromOdl || IdxPOdlSel == 0 ? currOdl.TCRichAttr : currPodl.Tcassegnato;
noteAttr = reloadFromOdl || IdxPOdlSel == 0 ? currOdl.Note : currPodl.Note;
PzPallet = reloadFromOdl || IdxPOdlSel == 0 ? currOdl.PzPallet : currPodl.PzPallet;
}
}
/// <summary>
/// Flush cache relativa a MP-IO x dati ODL
/// </summary>
/// <returns></returns>
private async Task FlushMpIoOdlCache()
{
// svuoto dalla cache REDIS del server IO...
await TabDServ.ResetIoCache("CurrODL");
await TabDServ.ResetIoCache("CurrOdlRow");
await TabDServ.ResetIoCache("CurrStatoMacc");
await TabDServ.ResetIoCache("DtMac");
}
/// <summary>
/// processa evento richiesto
/// </summary>
/// <param name="idxMaccCurr"></param>
/// <param name="idxEvento"></param>
/// <param name="userMsg"></param>
/// <param name="idxODL"></param>
private async Task processaEvento(string idxMaccCurr, int idxEvento, string userMsg, int idxODL, DateTime adesso)
{
inputComandoMapo inCmd;
inputComandoMapo inCmd2;
var rigaStato = TabDServ.StatoMacchina(idxMaccCurr);
// processo evento...
EventListModel newRec = new EventListModel()
{
IdxMacchina = idxMaccCurr,
InizioStato = adesso,
IdxTipo = idxEvento,
CodArticolo = rigaStato.CodArticolo,
Value = "",
MatrOpr = MatrOpr,
pallet = rigaStato.pallet
};
// se realtime
inCmd = await TabDServ.EvListInsert(newRec, Enums.tipoInputEvento.barcode);
// se la macchina è MULTI (cod#tavola) e sonoa INIZIO/FINE attrezzaggio (idxEv <=2)
// oppure FINE PROD processo ANCHE per la macchina madre...
if (idxMaccCurr.IndexOf('#') > 0 && (idxEvento <= 2 || idxEvento == 7))
{
EventListModel newRecParent = new EventListModel()
{
IdxMacchina = IdxMaccParent,
InizioStato = adesso,
IdxTipo = idxEvento,
CodArticolo = rigaStato.CodArticolo,
Value = "",
MatrOpr = MatrOpr,
pallet = rigaStato.pallet
};
inCmd2 = await TabDServ.EvListInsert(newRecParent, Enums.tipoInputEvento.barcode);
}
// chiamo refresh MSE
await TabDServ.RicalcMse(idxMaccCurr, 0);
lblOut = userMsg;
// loggo USR MSG
Log.Info(userMsg);
}
private async Task ReloadData(bool forceReload)
{
isLoading = true;
Log.Trace("OdlMan.ReloadData 01");
if (forceReload)
{
isMaster = SMServ.ListM2S
.Where(x => x.IdxMacchina.Equals(RecMSE?.IdxMacchina, StringComparison.InvariantCultureIgnoreCase))
.ToList().Count > 0;
isSlave = SMServ.ListM2S
.Where(x => x.IdxMacchinaSlave.Equals(RecMSE?.IdxMacchina, StringComparison.InvariantCultureIgnoreCase))
.ToList().Count > 0;
}
if (!string.IsNullOrEmpty(IdxMaccSel))
{
// 2024.04.11 passo macchina selezionata SE multi... era "IdxMaccParent"
ListODLAll = await TabDServ.VSOdlGetUnused(IdxMaccSel, ShowAll, numDayOdl);
// ListODLAll = await TabDServ.VSOdlGetUnused(IdxMaccParent, ShowAll, numDayOdl);
if (string.IsNullOrEmpty(SearchPodl))
{
ListODL = ListODLAll;
}
else
{
ListODL = ListODLAll.Where(x => x.label.Contains(SearchPodl, StringComparison.InvariantCultureIgnoreCase) || x.value == 0).ToList();
}
Log.Trace($"OdlMan.ReloadData | found {ListODL.Count} rec");
if (forceReload)
{
if (!isMulti || (isMulti && IdxMaccSel.IndexOf("#") > 0))
{
var rawData = await TabDServ.PezziProdMacchina(IdxMaccSel);
datiProdAct = await TabDServ.StatoProdMacchinaAsync(IdxMaccSel, DateTime.Now);
await checkConfProd();
Log.Trace("OdlMan.ReloadData | check checkConfProd done");
}
}
await updateIdxOdl();
// aggiorno questi dati SOLO SE non sono in attrezzaggio
if (!inAttr && !showSplitOdlRiattr)
{
// imposto tcRichAttr in base allo stato...
if (odlOk)
{
// prendo TCRich da PODL...
if (IdxPOdlSel > 0)
{
tcRichAttr = currPodl.Tcassegnato;
noteAttr = currPodl.Note;
PzPallet = currPodl.PzPallet;
}
else if (IdxOdl > 0)
{
tcRichAttr = currOdl.TCRichAttr;
noteAttr = currOdl.Note;
PzPallet = currOdl.PzPallet;
}
}
}
}
isLoading = false;
Log.Trace("OdlMan.ReloadData | END");
}
private async Task ReloadPOdlDetailData()
{
if (IdxPOdlSel > 0)
{
await ReloadXDL(false);
// solo se NON sno in attrezzaggio controllo se sia cambiato PODL
if (IdxPOdlSel != lastIdxPOdl)
{
lastIdxPOdl = IdxPOdlSel;
if (!inAttr && !showSplitOdlRiattr)
{
tcRichAttr = currPodl.Tcassegnato;
noteAttr = currPodl.Note;
PzPallet = currPodl.PzPallet;
}
}
}
}
private async Task ReloadXDL(bool reloadFromOdl)
{
int currIdxPOdl = IdxPOdlSel;
if (RecMSE != null)
{
if (reloadFromOdl)
{
currIdxPOdl = RecMSE.IdxPOdl ?? 0;
}
// se ho PODL valido...
if (currIdxPOdl > 0)
{
currPodl = await TabDServ.PODLExp_getByKey(currIdxPOdl);
}
else
{
currPodl = new PODLExpModel()
{
IdxOdl = RecMSE.IdxOdl ?? 0,
KeyRichiesta = "-",
CodArticolo = RecMSE.CodArticolo,
DescArticolo = RecMSE.CodArticolo,
NumPezzi = RecMSE.NumPezzi,
Tcassegnato = RecMSE.TCAssegnato
};
}
}
// update a runtime dati ODL se assegnato
if (currPodl.IdxOdl > 0)
{
currOdl = await TabDServ.OdlByIdx(currPodl.IdxOdl, false);
}
await updateIdxOdl();
// sistemo TCiclo, note, pzPallet..
fixTcNotePzPallet(reloadFromOdl);
}
private async Task updateIdxOdl()
{
// sistemo idxOdl...
var tabOdl = await TabDServ.OdlCurrByMacc(IdxMaccSel, false);
IdxOdl = tabOdl.IdxOdl;
if (isMulti)
{
var tabOdlAltra = await TabDServ.OdlCurrByMacc(idxMaccAltraTav, false);
IdxOdlAltra = tabOdlAltra.IdxOdl;
}
}
#endregion Private Methods
}
}