using Egw.Window.Data; using EgwCoreLib.Lux.Core.Generic; using EgwCoreLib.Razor; using Newtonsoft.Json; using WebWindowComplex; using WebWindowComplex.DTO; using static EgwCoreLib.Lux.Core.Enums; namespace Lux.UI.Components.Compo.Order { public partial class OrderRowMan : IDisposable { #region Public Enums /// /// modalit� modifica riga offerta /// public enum EditMode { None = 0, /// /// Dati generici del record /// RecData, /// /// Struttura serializzata (es JWD) /// SerStruc, /// /// BOM editing /// BOM, /// /// File editing (es BTL) /// File, /// /// Editing ciclo di lavoro /// JobCycle, /// /// Dettaglio WorkLoad per TEMPI /// WorkLoadDetailTime, /// /// Dettaglio WorkLoad per Pezzi/Tags /// WorkLoadDetailTag } #endregion Public Enums #region Public Properties [Parameter] public OrderModel CurrRecord { get; set; } = null!; [Parameter] public DisplayMode DisplayMode { get; set; } = DisplayMode.Standard; [Parameter] public EventCallback EC_Action { get; set; } [Parameter] public EventCallback EC_Updated { get; set; } #endregion Public Properties #region Public Methods /// /// Dispose sottoscrizione canale /// public void Dispose() { DLService.PipeUpdate.EA_NewMessage -= PipeUpdate_EA_NewMessage; DLService.PipePng.EA_NewMessage -= PipePng_EA_NewMessage; DLService.PipeSvg.EA_NewMessage -= PipeSvg_EA_NewMessage; DLService.PipeHwOpt.EA_NewMessage -= PipeHwOpt_EA_NewMessage; DLService.PipeProfList.EA_NewMessage -= PipeProfList_EA_NewMessage; DLService.PipeShape.EA_NewMessage -= PipeShape_EA_NewMessage; } #endregion Public Methods #region Public Classes /// /// Oggetto merged tra riga d'ordine e carico di lavoro associato /// public class MergedOrderRow { #region Public Properties public OrderRowModel Original { get; set; } = null!; public WorkLoadDetailDTO? WorkLoad { get; set; } #endregion Public Properties } #endregion Public Classes #region Protected Methods /// /// Verifica after render x stato interattivo pagina /// /// protected override void OnAfterRender(bool firstRender) { if (firstRender) { // JS interop or data fetches go here isInteractive = true; } } /// /// init obj /// protected override async Task OnInitializedAsync() { ConfInit(); prevJwd = ""; await ReloadBaseList(); DLService.PipeUpdate.EA_NewMessage += PipeUpdate_EA_NewMessage; DLService.PipePng.EA_NewMessage += PipePng_EA_NewMessage; DLService.PipeSvg.EA_NewMessage += PipeSvg_EA_NewMessage; DLService.PipeHwOpt.EA_NewMessage += PipeHwOpt_EA_NewMessage; DLService.PipeProfList.EA_NewMessage += PipeProfList_EA_NewMessage; DLService.PipeShape.EA_NewMessage += PipeShape_EA_NewMessage; } protected override async Task OnParametersSetAsync() { await ReloadDataAsync(); UpdateTable(); } #endregion Protected Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private List AllColors = new(); private List AllConfEnvir = new(); private List AllConfGlass = new(); private List AllConfHardware = new(); private List AllConfWood = new(); private List AllProdPlant = new(); private List AllRecords = new List(); private string apiUrl = ""; private List AvailColorMaterialList = new List(); private List AvailFamilyHardwareList = new List(); private List AvailGlassList = new List(); private List AvailHardwareList = new(); private List AvailMaterialList = new List(); /// /// Lista profili da DB /// private List AvailProfileList = new(); /// /// Lista profili da Redis (old way) /// private List AvailProfileListOld = new List(); /// /// Base path x network share files /// private string basePath = "unsafe_uploads"; private string calcTag = "calc"; private EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS cEnvir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW; /// /// Channel update HwOptions /// private string chHwOpt = ""; /// /// Channel update PNG /// private string chPng = ""; /// /// Channel update Profile List /// private string chProfList = ""; /// /// Channel update Shape /// private string chShape = ""; /// /// Channel update SVG /// private string chSvg = ""; private List? CurrBomList = null; /// /// Predisposizione valori live SVG/JWD /// private LivePayload CurrData = new LivePayload(); /// /// Modalit� editint attiva /// private EditMode CurrEditMode = EditMode.None; private Dictionary currGroupShape = new Dictionary(); private Dictionary currHwOption = new Dictionary(); private int currPage = 1; private string currPng = ""; private string currSvg = ""; /// /// Record in Edit corrente x modifica file/serializzato /// private OrderRowModel? EditRecord = null; /// /// Abilita edit massivo record ITEM /// private bool enableMassEdit = false; private string genericBasePath = ""; private string imgBasePath = ""; /// /// Semaforo x definire se sia gi� in modalit� ionterattiva o di prerendering /// private bool isInteractive = false; private bool isLoading = false; private List? ListProdAssign = null; private List ListRecords = new List(); private int numRecord = 10; private string noteCss => EditRecord == null ? "btn-success" : "btn-primary bg-gradient"; /// /// Versione originale (pre edit) /// private string origJwd = ""; /// /// Versione precedente JWD x test e confronto /// private string prevJwd = ""; /// /// Dizionario richieste /// private Dictionary reqDict = new Dictionary(); private OrderRowModel? SelRecord = null; /// /// Configurazione elenchi anagrafiche /// private BaseListPayload SetupList = new BaseListPayload(); private int totalCount = 0; private WorkLoadDetailDTO? WorkLoadRecord = null; private BootstrapModal Modal = new(); private string mTitle = ""; private string mMessage = ""; private BootstrapModal.ModalMode mMode = BootstrapModal.ModalMode.ND; private Dictionary modalOpt = new Dictionary(); #endregion Private Fields #region Private Properties private Dictionary> AvailThreshold { get; set; } = new Dictionary>() { {"Profilo78", new List() { new Threshold(3, "Bottom")}}, {"ProfiloSaomad", new List(){ new Threshold(3, "Bottom")}} #if false {"Profilo78", new List() { new Threshold(3, "Bottom"), new Threshold(1, "Threshold")}}, {"ProfiloSaomad", new List(){ new Threshold(3, "Bottom"), new Threshold(2, "BottomWaterdrip"), new Threshold(1, "Threshold")}} #endif }; [Inject] private IConfigDataService CDService { get; set; } = null!; [Inject] private IConfGlassService CGService { get; set; } = null!; [Inject] private IConfiguration Config { get; set; } = null!; [Inject] private IConfProfileService CPService { get; set; } = null!; [Inject] private ICalcRuidService CRService { get; set; } = null!; [Inject] private ICalcRequestService CService { get; set; } = null!; [Inject] private IConfWoodService CWService { get; set; } = null!; [Inject] private IDataLayerServices DLService { get; set; } = null!; [Inject] private IMatReqService MRService { get; set; } = null!; [Inject] private IEnvirParamService EPService { get; set; } = null!; /// /// Costo totale calcolato x offerta /// private double GrandTotCost { get => AllRecords != null && AllRecords.Count > 0 ? AllRecords.Sum(x => x.TotalCost) : 0; } /// /// Margine medio calcolato x offerta /// private double GrandTotMargin { get { double answ = 0; if (AllRecords != null && AllRecords.Count > 0) { double totPrice = AllRecords.Sum(x => x.TotalPrice); double totCost = AllRecords.Sum(x => x.TotalCost); if (totPrice > 0) { answ = (totPrice - totCost) / totPrice; } } return answ; } } private decimal GrandTotMaxTime { get { decimal answ = 0; if (ListRecords != null && ListRecords.Count > 0) { answ = ListRecords.Sum(x => x.WorkLoad?.TotMaxTime ?? 0); } return answ; } } /// /// Importo totale calcolato x offerta /// private double GrandTotNumItems { get { double answ = 0; if (AllRecords != null && AllRecords.Count > 0) { answ = AllRecords.Sum(x => x.ProdItemQtyTot); } return answ; } } private int GrandTotNumKo { get { int answ = 0; if (ListRecords != null && ListRecords.Count > 0) { answ = ListRecords.Sum(x => x.WorkLoad?.NumKo ?? 0); } return answ; } } private int GrandTotNumOk { get { int answ = 0; if (ListRecords != null && ListRecords.Count > 0) { answ = ListRecords.Sum(x => x.WorkLoad?.NumOk ?? 0); } return answ; } } private int GrandTotNumOkVin { get { int answ = 0; if (ListRecords != null && ListRecords.Count > 0) { answ = ListRecords.Sum(x => x.WorkLoad?.NumOkVin ?? 0); } return answ; } } /// /// Importo totale calcolato x offerta /// private double GrandTotPrice { get => AllRecords != null && AllRecords.Count > 0 ? AllRecords.Sum(x => x.TotalPrice) : 0; } /// /// Num totale obj calcolato x offerta /// private double GrandTotQty { get => AllRecords != null && AllRecords.Count > 0 ? AllRecords.Sum(x => x.Qty) : 0; } [Inject] private IGenValService GVService { get; set; } = default!; [Inject] private IWebHostEnvironment HostEnv { get; set; } = null!; [Inject] private IImageCacheService ICService { get; set; } = null!; [Inject] private IItemService ItemService { get; set; } = null!; [Inject] private IJSRuntime JSRuntime { get; set; } = null!; /// /// ID Offerta corrente /// private int OrderID { get => CurrRecord.OrderID; } [Inject] private IOrderRowService OrdRService { get; set; } = null!; [Inject] private IOrderService OrdService { get; set; } = null!; [Inject] private IProductionGroupService PGService { get; set; } = null!; [Inject] private IProductionItemService PIService { get; set; } = null!; [Inject] private IProductionPlantService PPService { get; set; } = null!; [Inject] private IProdService PService { get; set; } = null!; #endregion Private Properties #region Private Methods /// /// Effettua vera richiesta della BOM /// /// private async Task callRefreshProfList() { Dictionary DictExec = new Dictionary(); var cMode = Egw.Window.Data.Enums.QuestionModes.CONFIG; var cSubMode = Egw.Window.Data.Enums.QuestionConfSubModes.PROFILELIST; // compongo righiesta string reqUid = "Default"; DictExec.Add("Mode", $"{(int)cMode}"); DictExec.Add("UID", reqUid); // creo registrazione richiesta... var ruid = await CRService.AddRequestAsync($"{cEnvir}", $"{cMode}-{cSubMode}", reqUid); // aggiungo RUID effettivo DictExec.Add("RUID", ruid); DictExec.Add("SubMode", $"{(int)cSubMode}"); CalcRequestDTO req = new CalcRequestDTO() { EnvType = cEnvir, DictExec = DictExec }; // chiamo la chiamata POST alla API, che manda la richiesta via REDIS await CService.CallRestPost($"{apiUrl}/{genericBasePath}", $"{calcTag}/{reqUid}", req); } /// /// Chiude edit andando eventualmente a salvare /// /// /// private async Task CloseEdit(bool doSave) { // Proseguo solo se sono in interattivo (NO prerender pagina) if (isInteractive) { // ...se ho editing if (EditRecord != null) { bool updateBom = false; // SE richiesto salvataggio... if (doSave) { // salvo su DB! await OrdRService.UpdateSerStructAsync(EditRecord.OrderRowID, prevJwd); // salvo nel record corrente! EditRecord.SerStruct = prevJwd; updateBom = true; } else // altrimenti ricalcolo valore salvato { prevJwd = EditRecord.SerStruct; CurrData.CurrJwd = EditRecord.SerStruct; } if (updateBom) { await reqBomUpdate(EditRecord); } // aggiorno nel dizionari if (reqDict.ContainsKey("SerializedData")) { reqDict["SerializedData"] = prevJwd; } if (reqDict != null && reqDict.Count > 0) { // chiamo richiesta update CalcRequestDTO calcRequestDTO = new CalcRequestDTO(); calcRequestDTO.EnvType = EditRecord.Envir; calcRequestDTO.DictExec = reqDict; // chiamo la chiamata POST alla API, che manda la richiesta via REDIS await ICService.CallRestPost($"{apiUrl}/{genericBasePath}", $"{calcTag}/{EditRecord.OrderRowUID}", calcRequestDTO); } EditRecord = null; CurrEditMode = EditMode.None; } } } /// /// Chiude edit con preprocess x caso JWD /// /// /// private Task CloseEditJwd(DataSave infoSave) { prevJwd = infoSave.currJwd; return CloseEdit(infoSave.ForceSave); } private void ClosePopup() { CurrEditMode = EditMode.None; EditRecord = null; } private void ConfInit() { basePath = Config.GetValue("ServerConf:FileSharePath") ?? "unsafe_uploads"; apiUrl = Config.GetValue("ServerConf:Prog.ApiUrl") ?? ""; imgBasePath = Config.GetValue("ServerConf:ImageBaseUrl") ?? ""; genericBasePath = Config.GetValue("ServerConf:GenericBaseUrl") ?? ""; calcTag = Config.GetValue("ServerConf:CalcTag") ?? "calc"; chHwOpt = Config.GetValue("ServerConf:ChannelHwOpt") ?? ""; chPng = Config.GetValue("ServerConf:ChannelPng") ?? ""; chProfList = Config.GetValue("ServerConf:ChannelProfList") ?? ""; chShape = Config.GetValue("ServerConf:ChannelShape") ?? ""; chSvg = Config.GetValue("ServerConf:ChannelSvg") ?? ""; } /// /// Esegue assegnazione diretta valori ricevuti /// /// /// private async Task DirectAssign(DirectAssignReqDto updInfo) { if (updInfo != null) { int numDone = await PIService.BulkAssignProdGroupAsync(updInfo.OrderRowID, updInfo.ProdAssignID, updInfo.DictPartAssign); await ForceOrderReload(updInfo.OrderRowID); } } /// /// Esecuzione azione richiesta /// /// Azione richiesta private void DoAction(LayoutConst.DataAction actReq) { switch (actReq) { case LayoutConst.DataAction.None: break; case LayoutConst.DataAction.ResetDictShape: CurrData.DictShape = new Dictionary(); break; case LayoutConst.DataAction.ResetHwOpt: CurrData.DictOptionsXml = new Dictionary(); break; default: break; } } /// /// Aggiunge una nuova riga vuota come nota sotto il record selezionato oppure in coda... /// /// private async Task DoAddNote() { #if false int numRow = AllRecords.Count + 1; if (EditRecord != null) { numRow = EditRecord.RowNum + 1; } OrderRowModel newNote = new OrderRowModel() { OrderID = CurrRecord.OrderID, Envir = CurrRecord.Envir, RowNum = numRow, OrderRowUID = "", Qty = 0, BomCost = 0, BomPrice = 0, StepCost = 0, StepPrice = 0 }; await DLService.OffertRowUpsert(newNote); #endif await ReloadDataAsync(); UpdateTable(); } /// /// Annullamento modifica /// /// /// private async Task DoCancel() { isLoading = true; CurrEditMode = EditMode.None; EditRecord = null; await Task.Delay(20); await OrdService.FlushCacheOrdersAsync(); await Task.Delay(20); await ReloadDataAsync(); UpdateTable(); isLoading = false; } /// /// Clona riga richiesta /// /// private async Task DoClone(OrderRowModel rec2clone) { mTitle = "Attenzione"; mMessage = "Confermi di voler duplicare la riga corrente?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; // calcolo indice riga... int numRow = totalCount + 1; OrderRowModel newRec = new OrderRowModel() { AwaitBom = true, AwaitPrice = true, Envir = rec2clone.Envir, FileName = rec2clone.FileName, FileResource = rec2clone.FileResource, FileSize = rec2clone.FileSize, Inserted = DateTime.Now, ItemBOM = rec2clone.ItemBOM, ItemSteps = rec2clone.ItemSteps, Modified = DateTime.Now, Note = rec2clone.Note, OrderID = OrderID, OrderRowUID = "", Qty = rec2clone.Qty, RowNum = numRow, SellingItemID = rec2clone.SellingItemID, SerStruct = rec2clone.SerStruct, StepCost = rec2clone.StepCost, StepPrice = rec2clone.StepPrice, }; // salvo sul DB await OrdRService.UpsertAsync(newRec); // chiamo update record che non hanno UID x questo ordine var list2fix = await OrdRService.FixUidAsync(OrderID); if (list2fix != null && list2fix.Count > 0) { // rileggo i miei record... await ReloadDataAsync(); var listCalc = SorListCalc(); foreach (var item in listCalc) { // se UID fosse tra quelli da ricalcolare... if (list2fix.Contains(item.OrderRowUID)) { // chiedo BOM e immagine await reqBomUpdate(item); } } } await ReloadDataAsync(); UpdateTable(); } /// /// Eliminazione riga Ordine /// /// /// private async Task DoDelete(OrderRowModel rec2del) { mTitle = "Attenzione"; mMessage = "Confermi di voler eliminare la riga corrente?\n" + $"Codice: {rec2del.OrderRowUID} | {rec2del.Note}\n" + $"Importo tot: {rec2del.TotalPrice}"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; await OrdRService.DeleteAsync(rec2del); // elimino cache img await ICService.DeleteSvgAsync(rec2del.OrderRowUID, rec2del.Envir); await ReloadDataAsync(); UpdateTable(); } /// /// Va in edit della riga richiesta /// /// private void DoEdit(OrderRowModel curRec) { // imposto edit record EditRecord = curRec; /// modalita edit: gestione valori campi record CurrEditMode = EditMode.RecData; isLoading = false; } private async Task DoGenFabbisogni(OrderRowModel curRec) { mTitle = "Attenzione"; mMessage = "Confermi di voler generare i fabbisogni per la riga d'ordine indicata?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; // chiamo procedura creazione fabbisogni... List listReq = new(); listReq.Add(curRec); await MRService.ReconcileOrderRowsAsync(listReq); await ReloadDataAsync(); UpdateTable(); } /// /// Edit del file: /// - abilitazione fileUpload /// - anteprima grande (live) /// /// private void DoEditFile(OrderRowModel curRec) { EditRecord = curRec; /// modalit�edit: gestione JWD CurrEditMode = EditMode.File; #if false // preparazione dati da record corrente PrepareWindowData(EditRecord.SerStruct); // reset prev prevJwd = ""; #endif } /// /// Apre editor finestre del record richiesto /// /// private void DoEditJwd(OrderRowModel curRec) { EditRecord = curRec; /// modalit�edit: gestione JWD CurrEditMode = EditMode.SerStruc; // preparazione dati da record corrente PrepareWindowData(EditRecord.SerStruct); // reset prev prevJwd = ""; } private async Task DoRecalcOrder(bool forceResetCalc) { isLoading = true; if (forceResetCalc) { await setAwaitPrice(true, false); UpdateTable(); await InvokeAsync(StateHasChanged); await Task.Delay(300); } await OrdService.UpdateCostAsync(OrderID); if (forceResetCalc) { await Task.Delay(300); await setAwaitPrice(false, true); } // rileggo dati await ReloadDataAsync(); UpdateTable(); isLoading = false; // da approfondire... await InvokeAsync(async () => { await EC_Updated.InvokeAsync(true); }); //await EC_Updated.InvokeAsync(true); } /// /// Salvataggio edit record + reload /// /// /// private async Task DoSave(OrderRowModel curRec) { isLoading = true; // salvo record modificato... await OrdRService.UpsertAsync(curRec); // reset CurrEditMode = EditMode.None; EditRecord = null; await OrdService.FlushCacheOrdersAsync(); await ReloadDataAsync(); UpdateTable(); isLoading = false; } /// /// Seleziono riga senza cambiare modalita editing /// /// private void DoSelect(OrderRowModel curRec) { // imposto edit record EditRecord = curRec; /// modalit�edit: gestione valori campi record CurrEditMode = EditMode.None; } /// /// Imposta modalita edit ciclo di lavoro /// /// private Task DoSwapJobCycle(OrderRowModel currRow) { CurrEditMode = EditMode.JobCycle; return selectBom(currRow); } /// /// Imposta modalita ad edit BOM /// /// private Task DoSwapMat(OrderRowModel currRow) { CurrEditMode = EditMode.BOM; return selectBom(currRow); } /// /// Salvataggio del JWD aggiornato nella mia riga di offerta /// /// private async Task ExecRequest(Dictionary CurrArgs) { // Proseguo solo se sono in interattivo (NO prerender pagina) if (isInteractive) { // ...se ho editing if (EditRecord != null) { // SE contiene il mio Jwd... if (CurrArgs.ContainsKey("SerializedData")) { string serStruct = CurrArgs["SerializedData"]; // controllo SE variato... if (!prevJwd.Equals(serStruct) || !EgwCoreLib.Utils.DictUtils.DictAreEqual(reqDict, CurrArgs)) { // aggiorno val prev reqDict = CurrArgs; prevJwd = serStruct; // aggiorno live data CurrData.CurrJwd = serStruct; // chiamo richiesta update CalcRequestDTO calcRequestDTO = new CalcRequestDTO(); calcRequestDTO.EnvType = EditRecord.Envir; calcRequestDTO.DictExec = reqDict; // chiamo la chiamata POST alla API, che manda la richiesta via REDIS await ICService.CallRestPost($"{apiUrl}/{genericBasePath}", $"{calcTag}/{EditRecord.OrderRowUID}", calcRequestDTO); #if false // salvo su DB! await DLService.OffertRowUpdateSerStruct(EditRecord.OrderRowID, serStruct); #endif } } } } } /// /// Path da parent record /// /// /// private string FolderPath(int objID) { return $"SO-{objID:X8}"; } private async Task ForceOrderReload(int OrderRowID) { // chiudo modale... ClosePopup(); // rileggo i dati! await ReloadDataAsync(); // recupero il record con orderId indicato var item = ListRecords.FirstOrDefault(x => x.Original.OrderRowID == OrderRowID); if (item != null) { // seleziono nuovamente i dati... await ShowWLD(item, EditMode.WorkLoadDetailTime); } } /// /// Svuota cache corrente + rilegge dati /// private async Task ForceReloadData() { isLoading = true; CurrEditMode = EditMode.None; EditRecord = null; await Task.Delay(20); await OrdService.FlushCacheOrdersAsync(); await Task.Delay(20); await ReloadDataAsync(); UpdateTable(); isLoading = false; } /// /// Formattazione durata /// /// /// private string FormatDatetime(decimal durationSec) { TimeSpan tsWorkTime = TimeSpan.FromSeconds((double)durationSec); return DateTimeUtils.FormatDateTime(tsWorkTime); } /// /// Display fileSize scalato /// /// /// private string fSize(long size) { return EgwCoreLib.Utils.FileHelpers.SizeSuffix(size, 1); } /// /// Formattazione testo come html x display /// private MarkupString HtmlConv(string rawData) { return (MarkupString)rawData.Replace(Environment.NewLine, "
").Replace("\n", "
");//.Replace(" ", " "); } /// /// Calcola src immagine direttamente da modello dati + base path /// /// /// private string imgSrc(string imgUrl) { return $"{apiUrl}/{imgBasePath}/{imgUrl}"; } /// /// Restituisce il contenuto del file salvato /// /// /// /// private string LoadFileContent(string folderPath, string secureName) { string answ = ""; if (!string.IsNullOrEmpty(folderPath)) { try { // calcolo path file... string filePath = Path.Combine(basePath, folderPath, secureName); if (File.Exists(filePath)) { answ = File.ReadAllText(filePath); } } catch (Exception exc) { Log.Error($"Exception on LoadFileContent{Environment.NewLine}{exc}"); } } return answ; } /// /// Conversione record originali/merged /// /// /// private List MergeRecord(List origList) { var mergedList = AllRecords .Select(item => new MergedOrderRow { Original = item, WorkLoad = !string.IsNullOrEmpty(item.ProdEstimate) ? WorkLoadDetail(item.OrderRowUID, item.ProdEstimate) : null }) .ToList(); return mergedList; } /// /// Forza parametri generali selezionati nell'offerta /// /// private async Task OrderForceParameters() { mTitle = "Attenzione"; mMessage = "Confermi di voler impostare i parametri selezionati per l'Ordine?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; // recupero obj dizionario x i parametri compresi... ParamDict CurrSel = new ParamDict(CurrRecord.DictPresel); // metto a waiting tutte le righe con bom... var listCalc = SorListCalc(); foreach (var item in listCalc) { await OrdRService.UpdateAwaitStateAsync(item.OrderRowID, true, true); // poich� non � gestito evento ritorno update window interno si "scassa" --> try catch/ if FALSE try { //string rColor = CurrSel.GetVal("Color"); //string rGlass = CurrSel.GetVal("Glass"); //string rProfile = CurrSel.GetVal("Profile"); //string rWood = CurrSel.GetVal("Wood"); //var newSerStruct = SerialMan.MassUpdate((string)item.SerStruct, null, null, rColor, rWood, rGlass, rProfile); //await OrdRService.UpdateSerStructAsync(item.OrderRowID, newSerStruct); } catch { } } await InvokeAsync(StateHasChanged); // verifica preliminare UID await OrdRService.FixUidAsync(OrderID); // ricalcolo di tutte le BOM e relativi prezzi... foreach (var item in listCalc) { // chiedo BOM e immagine await reqBomUpdate(item); } //await DoRecalcOrder(); } /// /// Aggiornamento costing completo: /// - verifica UID /// - ricalcolo BOM /// - update prezzi /// /// private async Task OrderUpdateAllCosting() { mTitle = "Attenzione"; mMessage = "Confermi di voler ricalcolare/validare in toto l'ordine?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; // metto a waiting tutte le righe con bom... var listCalc = SorListCalc(); foreach (var item in listCalc) { await OrdRService.UpdateAwaitStateAsync(item.OrderRowID, true, true); } await InvokeAsync(StateHasChanged); // verifica preliminare UID await OrdRService.FixUidAsync(OrderID); await OrdRService.FixImgTypeAsync(OrderID); // ricalcolo di tutte le BOM e relativi prezzi... foreach (var item in listCalc) { // chiedo BOM e immagine await reqBomUpdate(item); } } /// /// Verifica e ricalcolo dei prezzi degli items nell'Ordine /// /// private async Task OrderUpdatePrices() { mTitle = "Attenzione"; mMessage = "Confermi di voler ricalcolare Ordine a costi correnti?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; await DoRecalcOrder(true); } /// /// Ricevuto HwOpt, processo /// /// /// private async void PipeHwOpt_EA_NewMessage(object? sender, EventArgs e) { // vale SOLO SE sono in editing... if (EditRecord != null) { // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { if (currArgs.msgUid.Equals($"{chHwOpt}:{EditRecord.OrderRowUID}")) { var rawDict = JsonConvert.DeserializeObject>(currArgs.newMessage) ?? new Dictionary(); currHwOption = rawDict; // salvo in live data... CurrData.DictOptionsXml = currHwOption; } await InvokeAsync(StateHasChanged); } } } private async void PipePng_EA_NewMessage(object? sender, EventArgs e) { // vale SOLO SE sono in editing... if (EditRecord != null) { // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { if (currArgs.msgUid.Equals($"{chPng}:{EditRecord.OrderRowUID}")) { currPng = currArgs.newMessage; // non devo passarlo al componente... #if false // salvo in live data... CurrData.SvgPreview = currSvg; #endif } await InvokeAsync(StateHasChanged); } } } /// /// Ricevuta profile list, processo /// /// /// private async void PipeProfList_EA_NewMessage(object? sender, EventArgs e) { // vale SOLO SE sono in editing... if (EditRecord != null) { // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { if (currArgs.msgUid.Equals($"{chProfList}:{EditRecord.OrderRowUID}")) { try { // nuova gestione da DB: attendo 500ms che il DB sia aggiornato await Task.Delay(500); // rileggo DB x info profili AvailProfileList = await CPService.GetAllAsync(); // converto i profili nel nuovo formato x payload... var profList = AvailProfileList.Select(x => new ProfilePayload() { ProfileName = x.Code, ThresholdList = x.ThresholdList, ParameterDict = x.ProfileDataDict }).ToList(); SetupList.ProfileList = profList; } catch { } } await InvokeAsync(StateHasChanged); } } } /// /// Ricevuta shape, procersso /// /// /// private async void PipeShape_EA_NewMessage(object? sender, EventArgs e) { // vale SOLO SE sono in editing... if (EditRecord != null) { #if false // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { if (currArgs.msgUid.Equals($"{shapeChannel}:{EditRecord.OrderRowUID}")) { currGroupShape = currArgs.newMessage; // salvo in live data... CurrData.DictShape = currGroupShape; } await InvokeAsync(StateHasChanged); } #endif // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { if (currArgs.msgUid.StartsWith($"{chShape}:{EditRecord.OrderRowUID}")) { // deserializzo il dizionario delle risposte... var rawDict = JsonConvert.DeserializeObject>(currArgs.newMessage); #if false int groupId = 0; // verifica del groupID... int.TryParse(currArgs.msgUid.Replace($"{shapeChannel}:{windowUid}:", ""), out groupId); if (currGroupShape.ContainsKey(groupId)) { currGroupShape[groupId] = currArgs.newMessage; } else { currGroupShape.Add(groupId, currArgs.newMessage); } #endif currGroupShape = rawDict ?? new Dictionary(); CurrData.DictShape = currGroupShape; } await InvokeAsync(StateHasChanged); } } } /// /// Ricevuto SVG, se � il mio lo aggiorno... /// /// /// private async void PipeSvg_EA_NewMessage(object? sender, EventArgs e) { // vale SOLO SE sono in editing... if (EditRecord != null) { // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { if (currArgs.msgUid.Equals($"{chSvg}:{EditRecord.OrderRowUID}")) { currSvg = currArgs.newMessage; // salvo in live data... CurrData.SvgPreview = currSvg; } await InvokeAsync(StateHasChanged); } } } /// /// Task verifica update ricevuti /// /// /// private async void PipeUpdate_EA_NewMessage(object? sender, EventArgs e) { // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare if (!string.IsNullOrEmpty(currArgs.newMessage)) { // cerco se faccia parte dei record correnti... var recFound = AllRecords.Any(x => x.OrderRowUID == currArgs.newMessage); if (recFound) { isLoading = true; await Task.Delay(1); // se si tratta dell'UID corrente --> fa update await DoRecalcOrder(false); await InvokeAsync(StateHasChanged); } } await Task.Delay(1); } /// /// Preparazione dati x componente edit JWD /// /// private void PrepareWindowData(string currJwd) { // converto i profili nel nuovo formato x payload... var profList = AvailProfileList.Select(x => new ProfilePayload() { ProfileName = x.Code, ThresholdList = x.ThresholdList, ParameterDict = x.ProfileDataDict }).ToList(); // preparo conf oggetti x controllo SetupList = SetupList = new BaseListPayload() { ColorMaterial = AvailColorMaterialList, FamilyHardware = AvailFamilyHardwareList, Glass = AvailGlassList, Hardware = AvailHardwareList, Wood = AvailMaterialList, ProfileList = profList }; CurrData = new LivePayload() { CurrJwd = currJwd, SvgPreview = currSvg }; } /// /// init classi configurazione /// /// private async Task ReloadBaseList() { // lettura config setup varie da DB/Cache Redis AllConfEnvir = await EPService.GetAllAsync(); AllConfGlass = await CGService.GetAllAsync(); AvailProfileList = await CPService.GetAllAsync(); AllProdPlant = await PPService.GetAllAsync(); // FixMe ToDo rimuovere vers redis obsolete var rawProfiles = await CDService.ProfileListAsync(cEnvir, "Default"); // se fosse vuoto chiamo update... if (rawProfiles == null || rawProfiles.Count == 0) { await callRefreshProfList(); // aspetto 200ms... e richiedo! await Task.Delay(200); rawProfiles = await CDService.ProfileListAsync(cEnvir, "Default"); } AvailProfileListOld = rawProfiles; var rawHw = await CDService.HwModelListAsync(cEnvir, "HW.AGB"); // hw filtro solo validi... AllConfHardware = rawHw .Where(x => !x.FamilyName.Equals(x.Description, StringComparison.OrdinalIgnoreCase)) .ToList(); AllConfWood = await CWService.GetAllAsync(); AllColors = await GVService.GetFiltAsync("WoodCol"); // conversione tipi AvailGlassList = AllConfGlass .Select(x => x.Description) .ToList(); AvailFamilyHardwareList = AllConfHardware .DistinctBy(x => x.FamilyName) .OrderBy(x => x.FamilyName) .Select(x => x.FamilyName) .ToList(); AvailHardwareList = AllConfHardware .Select(x => new Egw.Window.Data.Hardware(x.Id, x.FamilyName, x.Description, x.OpeningType, x.Shape, x.SashQty, x.SashPosition)) .ToList(); AvailMaterialList = AllConfWood .Select(x => x.Description) .ToList(); // FixMe Todo: aggiunta profili (manca anche nel costruttore...) AvailColorMaterialList = AllColors .OrderBy(x => x.Index) .Select(x => x.ValString) .ToList(); } /// /// Legge i dati dei record completi /// private async Task ReloadDataAsync() { if (OrderID > 0) { AllRecords = await OrdRService.GetByParentAsync(OrderID); totalCount = AllRecords.Count(); // faccio un controllo/fix dei record int numFix = await OrdRService.ValidateAsync(AllRecords); } } /// /// Eliminazione file (old) /// /// Nome secure da impiegare /// Contenuto file private bool removeOldFile(string folderPath, string secureName) { bool answ = false; if (!string.IsNullOrEmpty(folderPath)) { // calcolo path file... string filePath = Path.Combine(basePath, folderPath, secureName); // se esiste... if (File.Exists(filePath)) { File.Delete(filePath); } } return answ; } /// /// Invio richiesta balance ordine /// /// /// private async Task ReqBalance(BalanceReqDto balData) { if (WorkLoadRecord != null && balData != null && balData.TagList.Count > 0) { mTitle = "Attenzione"; mMessage = $"Confermi richiesta bilanciamento carico per {balData.TagList.Count} articoli?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; // preparo oggetto richiesta // verifico parametri da conf envir... var envRec = AllConfEnvir.FirstOrDefault(x => x.EnvirID == CurrRecord.Envir); Egw.Window.Data.Enums.QuestionModes cMode = Egw.Window.Data.Enums.QuestionModes.ORDER; Egw.Window.Data.Enums.QuestionOrderSubModes cSubMode = Egw.Window.Data.Enums.QuestionOrderSubModes.BALANCE; string reqKey = ""; // preparo la richiesta di bilanciamento CalcRequestDTO calcReq = new CalcRequestDTO(); // elenco tags ricevuto... List TagList = balData.TagList; string serTagList = string.Join(",", TagList); // preparo richiesta serializzata e la accodo (viene inviata richiesta calcolo) Dictionary dictArgs = new Dictionary(); // creo registrazione richiesta... var ruid = await CRService.AddRequestAsync($"{CurrRecord.Envir}", $"{(int)cMode}-{(int)cSubMode}", WorkLoadRecord.UID); dictArgs.Add("UID", WorkLoadRecord.UID); dictArgs.Add("Group", $"99"); // aggiungo RUID effettivo dictArgs.Add("RUID", ruid); dictArgs.Add("OrderUID", CurrRecord.OrderCode); dictArgs.Add("Mode", $"{(int)cMode}"); dictArgs.Add("SubMode", $"{(int)cSubMode}"); dictArgs.Add("TagList", serTagList); // serializzo la richiesta di bilanciamento... string reqBalance = JsonConvert.SerializeObject(balData.MachineBalance); dictArgs.Add("ReqBalance", reqBalance); dictArgs.Add("BarLenght", $"{balData.BarLenght}"); calcReq = new CalcRequestDTO() { DictExec = dictArgs, EnvType = CurrRecord.Envir }; // chiave: composta da cMode, submode, UID riga... reqKey = $"{cMode}:{cSubMode}:{WorkLoadRecord.UID}"; // invio richiesta await PService.EnqueueRequestAsync("Balance", reqKey, calcReq); // parto dalla history attuale var currHist = CurrRecord.LogHistory; // aggiungo evento... currHist.Add(new TaskHistDTO() { DtEvent = DateTime.Now, UserName = "Default User", Message = $"{reqKey}", IconCss = "fa-solid fa-hourglass-start" }); CurrRecord.LogHistory = currHist; await OrdService.UpsertAsync(CurrRecord); } } /// /// Effettua vera richiesta della BOM /// /// /// private async Task reqBomUpdate(OrderRowModel currRec) { // salvo richiesta BOM su record currRec.AwaitBom = true; currRec.AwaitPrice = true; await OrdRService.UpdateAwaitStateAsync(currRec.OrderRowID, true, true); // preparo la domanda serializzata Dictionary DictExec = new Dictionary(); // verifico parametri da conf envir... var envRec = AllConfEnvir.FirstOrDefault(x => x.EnvirID == currRec.Envir); string serKey = envRec != null ? envRec.SerStrucKey : "SerializedData"; // cablata la BOM DictExec.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.BOM}"); // UID cablato x ora... DictExec.Add("UID", currRec.OrderRowUID); // aggiungo file secondo ambiente... switch (currRec.Envir) { case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW: DictExec.Add(serKey, currRec.SerStruct); break; case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM: case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL: case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET: // rileggo da file... string folderPath = FolderPath(currRec.OrderID); string rawData = LoadFileContent(folderPath, currRec.FileResource); DictExec.Add(serKey, rawData); DictExec.Add("FileName", currRec.FileName); break; case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.NULL: default: break; } CalcRequestDTO req = new CalcRequestDTO() { EnvType = currRec.Envir, DictExec = DictExec }; await InvokeAsync(StateHasChanged); // chiamo la chiamata POST alla API, che manda la richiesta via REDIS await CService.CallRestPost($"{apiUrl}/{genericBasePath}", $"{calcTag}/{currRec.OrderRowUID}", req); } /// /// Lancia la richiesta di ricaolo della BOM dal JWD (o equivalente) /// /// private async Task RequestBom(OrderRowModel currRec) { mTitle = "Attenzione"; mMessage = "Confermi di voler ricalcolare la BOM?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; await reqBomUpdate(currRec); } /// /// Rimette da coda running in waiting il Job del WLD corrente /// /// private async Task ReRunJob() { if (WorkLoadRecord != null && SelRecord != null) { mTitle = "Attenzione"; mMessage = "Sicuro di voler rimettere in coda il calcolo?"; mMode = BootstrapModal.ModalMode.Confirm; modalOpt = new(); modalOpt.Add(true, "Si"); modalOpt.Add(false, "No"); if (!await Modal!.ShowAsync()) return; string JobCode = $"ORDER:ESTIMATE:{WorkLoadRecord.UID}"; await PService.ReRunJobAsync(SelRecord.Envir, JobCode); } } /// /// Esegue reset assegnazioni /// /// /// private async Task ResetAssign(int OrderRowID) { await PIService.ResetAssignAsync(OrderRowID); await ForceOrderReload(OrderRowID); } /// /// Css di verifica riga selezionata /// /// /// private string RowClass(OrderRowModel selRow) { return EditRecord != null && EditRecord.OrderRowID == selRow.OrderRowID ? "table-info" : ""; } /// /// Salvataggio dei dati del file caricato /// /// Dizionario info file private void SaveFile(Dictionary fileDict) { // verifico di essere in edit... if (EditRecord != null) { string folderPath = FolderPath(EditRecord.OrderID); // verifico di avere parametri... if (fileDict != null && fileDict.Count > 0) { string secureName = ""; string content = ""; if (fileDict.ContainsKey("secureName")) { secureName = fileDict["secureName"]; } if (fileDict.ContainsKey("content")) { content = fileDict["content"]; } if (!string.IsNullOrEmpty(folderPath) && !string.IsNullOrEmpty(secureName) && !string.IsNullOrEmpty(content)) { // salvo! saveFileContent(folderPath, secureName, content); } } // altrimenti signifca cleanup eventuale vecchio file... else { removeOldFile(folderPath, EditRecord.FileResource); } } } /// /// Esegue salvataggio del file ricevuto /// /// Path relativo x file (tipicamente UID parent order) /// Nome secure da impiegare /// Contenuto file private bool saveFileContent(string folderPath, string secureName, string content) { bool answ = false; if (!string.IsNullOrEmpty(folderPath)) { // calcolo path file... string filePath = Path.Combine(basePath, folderPath, secureName); string? directoryPath = Path.GetDirectoryName(filePath); try { if (!string.IsNullOrEmpty(directoryPath)) { Directory.CreateDirectory(directoryPath); } File.WriteAllText(filePath, content); } catch (Exception exc) { Log.Error($"Exception on save{Environment.NewLine}{exc}"); } } return answ; } /// /// Selezione e fix dati BOM /// /// /// private async Task selectBom(OrderRowModel currRow) { EditRecord = currRow; CurrBomList = BomCalculator.GetBomList(EditRecord.ItemBOM); if (CurrBomList.Any(x => x.ItemID == 0)) { CurrBomList = await ItemService.GetBomFixItemIdAsync(CurrBomList); } } private async Task setAwaitPrice(bool awaitPrice, bool flushCache) { foreach (var item in AllRecords) { item.AwaitPrice = awaitPrice; await OrdRService.UpdateAwaitStateAsync(item.OrderRowID, null, awaitPrice, flushCache); } } /// /// Verifia ammissibilit� display btn ricalcolo BOM da item /// /// /// private bool ShowBom(OrderRowModel reqItem) { bool answ = false; if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit) { switch (reqItem.Envir) { case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW: answ = !string.IsNullOrEmpty(reqItem.SerStruct) && reqItem.SerStruct.Length > 2; break; case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM: case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL: case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET: // da cambiare con ricerca file su disco?!? answ = !string.IsNullOrEmpty(reqItem.FileResource) && !string.IsNullOrEmpty(reqItem.FileName); break; case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.NULL: default: break; } } return answ; } /// /// salva dettaglio workload x mostrare tipo pezzi richiesti /// /// private async Task ShowWLD(MergedOrderRow mergeRec, EditMode reqMode) { CurrEditMode = reqMode; EditRecord = null; SelRecord = mergeRec.Original; WorkLoadRecord = mergeRec.WorkLoad; // recupero i prodassign data... List? curList = await PGService.GetByOrderRowAsync(SelRecord.OrderRowID); #if false // se non avessi tutte le macchine configurate --> chiamo fix! if (curList == null || curList.Count == 0 || curList.Count < AllProdPlant.Count()) { //var currMachLilst = WorkLoadRecord?.ListMachines ?? AllProdPlant.Select(x => x.ProdPlantCod).ToList(); // metto tutte le macchine configurate, DA DISCUTERE... var currMachLilst = AllProdPlant.Select(x => x.ProdPlantCod).ToList(); curList = await DLService.ProdAssignCheckExist(SelRecord.OrderRowID, currMachLilst); } #endif ListProdAssign = curList; } /// /// Elenco SalesOfferRows calcolabili: /// - contengono serializzazione come JWD /// - contengono file come BTL /// private List SorListCalc() { var rawList = AllRecords .Where(x => (!string.IsNullOrEmpty(x.SerStruct) && x.SerStruct.Length > 2) || (!string.IsNullOrEmpty(x.FileName) && !string.IsNullOrEmpty(x.FileResource))) .ToList(); return rawList ?? new List(); } /// /// Toggle visibilit� modifica file indicando ID della OfferRow corrente (o zero se deselect) /// private void ToggleFileEdit(OrderRowModel? currRec) { CurrEditMode = currRec == null ? EditMode.None : EditMode.File; EditRecord = currRec; } /// /// Salva nel record corrente la BOM aggiornata e poi ricalcola importo... /// /// /// private async Task UpdateBom(List newBomList) { if (EditRecord != null) { // salvo BOM nel record corrente... bool fatto = await OrdRService.UpdateBomAsync(EditRecord.OrderRowID, newBomList); // ricalcolo offerta completa await ReloadDataAsync(); UpdateTable(); // rilegge il record da elenco appena rinfrescato... int OrderRowID = EditRecord.OrderRowID; var updRec = AllRecords.FirstOrDefault(x => x.OrderRowID == OrderRowID); if (updRec != null) { CurrBomList = new List(); // fa refresh dei dati della BOM visualizzata await selectBom(updRec); await InvokeAsync(StateHasChanged); } } } /// /// Filtro e paginazione /// private void UpdateTable() { // fix paginazione var filtRecords = AllRecords .OrderBy(x => x.RowNum) .Skip(numRecord * (currPage - 1)) .Take(numRecord) .ToList(); ListRecords = MergeRecord(filtRecords); isLoading = false; } private async Task UploadFile(InputFileChangeEventArgs e) { // Proseguo solo se sono in interattivo (NO prerender pagina) if (isInteractive) { if (EditRecord != null) { // init dizionari arg richiesta update Dictionary fileArgs = new Dictionary(); // leggo il contenuto del PRIMO (singolo) file IBrowserFile file = e.File; // limite file size (al momento 10 MB) var maxAllowedSize = 10 * 1024 * 1024; using var stream = file.OpenReadStream(maxAllowedSize); using var reader = new StreamReader(stream); string rawContent = await reader.ReadToEndAsync(); // calcolo il nome del file trusted... string trustedFileName = Path.GetRandomFileName(); EditRecord.FileResource = trustedFileName; EditRecord.FileName = file.Name; EditRecord.FileSize = rawContent.LongCount(); // salvo sul DB i dati (nome, nome sicuro, size...) await OrdRService.UpdateFileDataAsync(EditRecord); // parametri richiesta fileArgs.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.PREVIEW}"); fileArgs.Add("SubMode", "2"); fileArgs.Add("FileName", $"{file.Name}"); fileArgs.Add("Height", "1200"); fileArgs.Add("Width", "1800"); //fileArgs.Add("Btl", rawContent); fileArgs.Add("SerializedData", rawContent); // invio! CalcRequestDTO calcRequestDTO = new CalcRequestDTO(); calcRequestDTO.EnvType = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM; calcRequestDTO.DictExec = fileArgs; await ICService.CallRestPost($"{apiUrl}/{genericBasePath}", $"{calcTag}/{EditRecord.OrderRowUID}", calcRequestDTO); // ora chiedo anche la BOM! #if false // salvo in locale il file: SISTEMARE PERMESSI saveFileContent(EditFileRecord.OrderRowUID, trustedFileName, rawContent); #endif } } } /// /// Restituisce struttura dettaglio WorkLoad x item /// /// /// /// private WorkLoadDetailDTO WorkLoadDetail(string UID, string rawData) { var currWLD = new WorkLoadDetailDTO(UID, rawData); return currWLD; } private string cssReqPend(bool isDirty) { return isDirty ? "border border-warning rounded border-3" : ""; } private Task ReqEditRow() { return EC_Action.InvokeAsync("EditRow"); } #endregion Private Methods } }