Update gestione save e ricalcolo BOM x BEAM

This commit is contained in:
Samuele Locatelli
2025-11-06 17:26:48 +01:00
parent 9a4c96bcf8
commit a70ed095e9
12 changed files with 269 additions and 114 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>0.9.2511.0610</Version>
<Version>0.9.2511.0616</Version>
</PropertyGroup>
<ItemGroup>
+2 -1
View File
@@ -80,6 +80,7 @@
"ImageBaseUrl": "https://iis01.egalware.com/lux/srv/api/window/",
"ImageCalcTag": "svg-preview",
"ImageLiveTag": "svg",
"ImageFileTag": "svgfile"
"ImageFileTag": "svgfile",
"FileSharePath": "\\\\stor01\\TEAM DRIVES\\40_FileUpload\\LuxUploads"
}
}
+18 -1
View File
@@ -7,6 +7,10 @@
<td>Class</td>
<td>Descrizione</td>
@* <td>Cod</td> *@
@if (ShowVolume)
{
<td class="text-end">Vol</td>
}
<td class="text-end">Qty</td>
<td class="text-end">UnitPrice</td>
<td class="text-end">Importo</td>
@@ -31,6 +35,10 @@
<button class="btn btn-sm btn-success" title="Effettua Cambio" @onclick="() => DoSave()"><i class="fa-solid fa-check"></i></button>
</div>
</td>
@if (ShowVolume)
{
<td class="text-end">@($"{item.Value.Volume:N3}")</td>
}
<td class="text-end">@($"{item.Value.Qty:N3}")</td>
<td class="text-end">@($"{item.Value.PriceEff:C2}")</td>
<td class="text-end">@($"{item.Value.TotalCost:C2}")</td>
@@ -49,6 +57,10 @@
<td>@item.Value.ClassCode</td>
<td>@item.Value.ItemCode</td>
@* <td>@item.Value.DescriptionCode</td> *@
@if (ShowVolume)
{
<td class="text-end">@($"{item.Value.Volume:N3}")</td>
}
<td class="text-end">@($"{item.Value.Qty:N3}")</td>
<td class="text-end">@($"{item.Value.PriceEff:C2}")</td>
<td class="text-end">@($"{item.Value.TotalCost:C2}")</td>
@@ -58,7 +70,12 @@
</tbody>
<tfoot>
<tr class="table-primary">
<td colspan="5" class="text-end">@BomList.Count record</td>
<td colspan="4" class="text-start"><b>@BomList.Count</b> materiali</td>
@if (ShowVolume)
{
<td class="text-end">@($"{VolTotale:N3}")</td>
}
<td class="text-end">@($"{QtyTotale:N3}")</td>
<td class="text-end">tot:</td>
<td class="text-end fw-bold">@($"{ImportoTotale:C2}")</td>
</tr>
+35
View File
@@ -1,5 +1,6 @@
using EgwCoreLib.Lux.Core.RestPayload;
using EgwCoreLib.Lux.Data.DbModel.Items;
using EgwCoreLib.Lux.Data.DbModel.Sales;
using EgwCoreLib.Lux.Data.Services;
using EgwMultiEngineManager.Data;
using Microsoft.AspNetCore.Components;
@@ -14,6 +15,9 @@ namespace Lux.UI.Components.Compo
[Parameter]
public List<BomItemDTO> BomList { get; set; } = null!;
[Parameter]
public OfferRowModel CurrRowRec { get; set; } = null!;
[Parameter]
public EventCallback<List<BomItemDTO>> EC_Updated { get; set; }
@@ -37,9 +41,40 @@ namespace Lux.UI.Components.Compo
}
}
protected double QtyTotale
{
get
{
double valTot = 0;
if (bomDict != null)
{
valTot = bomDict.Sum(x => x.Value.Qty);
}
return valTot;
}
}
protected double VolTotale
{
get
{
double valTot = 0;
if (bomDict != null)
{
valTot = bomDict.Sum(x => x.Value.Volume);
}
return valTot;
}
}
#endregion Protected Properties
private bool ShowVolume
{
get => CurrRowRec.Envir == Constants.EXECENVIRONMENTS.BEAM || CurrRowRec.Envir == Constants.EXECENVIRONMENTS.WALL;
}
#region Protected Methods
protected void DoCancel()
@@ -20,7 +20,7 @@ namespace Lux.UI.Components.Compo.FileMan
public OfferRowModel CurrItem { get; set; }
[Parameter]
public EventCallback<Dictionary<string, string>> EC_DoUpdate { get; set; }
public EventCallback<Dictionary<string, string>> EC_ReqSave { get; set; }
[Parameter]
public EventCallback<bool> EC_OnClose { get; set; }
@@ -84,57 +84,68 @@ namespace Lux.UI.Components.Compo.FileMan
using var reader = new StreamReader(stream);
string rawContent = await reader.ReadToEndAsync();
// calcolo il nome del file trusted...
string trustedFileName = Path.GetRandomFileName();
CurrItem.FileResource = trustedFileName;
CurrItem.FileName = file.Name;
CurrItem.FileSize = rawContent.LongCount();
// aggiungo contenuto come SerStruct (in attesa di valutare FS save...)
CurrItem.SerStruct = rawContent;
// salvo sul DB i dati (nome, nome sicuro, size...)
await DLService.OffertRowUpdateFileData(CurrItem);
// parametri richiesta
fileArgs.Add("FileName", $"{file.Name}");
fileArgs.Add("SerializedData", rawContent);
fileArgs.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.PREVIEW}");
fileArgs.Add("SubMode", "2");
fileArgs.Add("Height", "1200");
fileArgs.Add("Width", "1800");
// invio!
CalcRequestDTO calcRequestDTO = new CalcRequestDTO()
// se ho contenuto nel file...
if (!string.IsNullOrEmpty(rawContent))
{
EnvType = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM,
DictExec = fileArgs
};
// richiesta PNG
await ICService.CallRestPost($"{ApiUrl}/{GenericBasePath}", $"{CalcTag}/{CurrItem.OfferRowUID}", calcRequestDTO);
// aggiungo info x BOM
bomArgs.Add("FileName", $"{file.Name}");
bomArgs.Add("SerializedData", rawContent);
bomArgs.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.BOM}");
// ...infine chiedo anche la BOM!
calcRequestDTO = new CalcRequestDTO()
{
EnvType = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM,
DictExec = bomArgs
};
// richiesta BOM
await ICService.CallRestPost($"{ApiUrl}/{GenericBasePath}", $"{CalcTag}/{CurrItem.OfferRowUID}", calcRequestDTO);
// elimino vecchio file... richiedendo save senza parametri
Dictionary<string, string> dictSave = new Dictionary<string, string>();
await EC_ReqSave.InvokeAsync(dictSave);
// calcolo il nome del file trusted...
string trustedFileName = Path.GetRandomFileName();
CurrItem.FileResource = trustedFileName;
CurrItem.FileName = file.Name;
CurrItem.FileSize = rawContent.LongCount();
#if false
// salvo in locale il file: SISTEMARE PERMESSI
saveFileContent(EditFileRecord.OfferRowUID, trustedFileName, rawContent);
// aggiungo contenuto come SerStruct (in attesa di valutare FS save...)
CurrItem.SerStruct = rawContent;
#endif
// salvo sul DB i dati (nome, nome sicuro, size...)
await DLService.OffertRowUpdateFileData(CurrItem);
// parametri richiesta
fileArgs.Add("FileName", $"{file.Name}");
fileArgs.Add("SerializedData", rawContent);
fileArgs.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.PREVIEW}");
fileArgs.Add("SubMode", "2");
fileArgs.Add("Height", "1200");
fileArgs.Add("Width", "1800");
// invio!
CalcRequestDTO calcRequestDTO = new CalcRequestDTO()
{
EnvType = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM,
DictExec = fileArgs
};
// richiesta PNG
await ICService.CallRestPost($"{ApiUrl}/{GenericBasePath}", $"{CalcTag}/{CurrItem.OfferRowUID}", calcRequestDTO);
// aggiungo info x BOM
bomArgs.Add("FileName", $"{file.Name}");
bomArgs.Add("SerializedData", rawContent);
bomArgs.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.BOM}");
// ...infine chiedo anche la BOM!
calcRequestDTO = new CalcRequestDTO()
{
EnvType = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM,
DictExec = bomArgs
};
// richiesta BOM
await ICService.CallRestPost($"{ApiUrl}/{GenericBasePath}", $"{CalcTag}/{CurrItem.OfferRowUID}", calcRequestDTO);
dictSave.Add("secureName", trustedFileName);
dictSave.Add("content", rawContent);
await EC_ReqSave.InvokeAsync(dictSave);
}
}
#endregion Private Methods
private void CloseEdit(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
{
_ = EC_OnClose.InvokeAsync(true);
// false --> NON salvo serializzato eprché ho già salvato l file x cui NON ricalcola la BOM
_ = EC_OnClose.InvokeAsync(false);
}
}
}
+2 -2
View File
@@ -15,7 +15,7 @@
CalcTag="@calcTag"
GenericBasePath="@genericBasePath"
ImgBasePath="@imgBasePath"
EC_DoUpdate="SaveFile"
EC_ReqSave="SaveFile"
EC_OnClose="CloseEdit">
</BtlPreview>
}
@@ -321,7 +321,7 @@ else
</div>
</div>
<div class="modal-body">
<EditBom BomList="@CurrBomList" EC_Updated="UpdateBom"></EditBom>
<EditBom CurrRowRec="@EditRecord" BomList="@CurrBomList" EC_Updated="UpdateBom"></EditBom>
</div>
</div>
</div>
+152 -62
View File
@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Components.Forms;
using Microsoft.IdentityModel.Tokens;
using Microsoft.JSInterop;
using Newtonsoft.Json;
using NLog;
using WebWindowComplex;
using WebWindowComplex.DTO;
using static EgwCoreLib.Lux.Core.Enums;
@@ -314,7 +315,6 @@ namespace Lux.UI.Components.Compo
CurrEditMode = EditMode.RecData;
}
/// <summary>
/// Edit del file:
/// - abilitazione fileUpload
@@ -330,7 +330,7 @@ namespace Lux.UI.Components.Compo
// preparazione dati da record corrente
PrepareWindowData(EditRecord.SerStruct);
// reset prev
prevJwd = "";
prevJwd = "";
#endif
}
@@ -589,6 +589,7 @@ namespace Lux.UI.Components.Compo
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private List<GenValueModel> AllColors = new();
private List<EnvirParamModel> AllConfEnvir = new();
@@ -615,6 +616,11 @@ namespace Lux.UI.Components.Compo
private List<string> AvailProfileList = new List<string>();
/// <summary>
/// Base path x network share files
/// </summary>
private string basePath = "unsafe_uploads";
private string calcTag = "calc";
private List<BomItemDTO>? CurrBomList = null;
@@ -630,10 +636,10 @@ namespace Lux.UI.Components.Compo
private int currPage = 1;
private string currPng = "";
private List<string> currProfList = new List<string>();
private string currSvg = "";
private string currPng = "";
/// <summary>
/// Record in Edit corrente
@@ -755,6 +761,7 @@ namespace Lux.UI.Components.Compo
private void ConfInit()
{
basePath = Config.GetValue<string>("ServerConf:FileSharePath") ?? "unsafe_uploads";
apiUrl = Config.GetValue<string>("ServerConf:Prog.ApiUrl") ?? "";
imgBasePath = Config.GetValue<string>("ServerConf:ImageBaseUrl") ?? "";
genericBasePath = Config.GetValue<string>("ServerConf:GenericBaseUrl") ?? "";
@@ -837,10 +844,10 @@ namespace Lux.UI.Components.Compo
if (currArgs.msgUid.Equals($"{pngChannel}:{EditRecord.OfferRowUID}"))
{
currPng = currArgs.newMessage;
// non devo passarlo al componente di gestione finestre...
// non devo passarlo al componente...
#if false
// salvo in live data...
CurrData.SvgPreview = currSvg;
CurrData.SvgPreview = currSvg;
#endif
}
await InvokeAsync(StateHasChanged);
@@ -1064,6 +1071,27 @@ namespace Lux.UI.Components.Compo
}
}
/// <summary>
/// Eliminazione file (old)
/// </summary>
/// <param name="secureName">Nome secure da impiegare</param>
/// <param name="content">Contenuto file</param>
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;
}
/// <summary>
/// Effettua vera richiesta della BOM
/// </summary>
@@ -1085,10 +1113,25 @@ namespace Lux.UI.Components.Compo
DictExec.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.BOM}");
// UID cablato x ora...
DictExec.Add("UID", currRec.OfferRowUID);
DictExec.Add(serKey, currRec.SerStruct);
// aggiungo comunque filename...
DictExec.Add("FileName", $"{currRec.FileName}");
// 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 = $"SO-{currRec.OfferID:X8}";
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()
{
@@ -1102,9 +1145,47 @@ namespace Lux.UI.Components.Compo
await CService.CallRestPost($"{apiUrl}/{genericBasePath}", $"{calcTag}/{currRec.OfferRowUID}", req);
}
/// <summary>
/// Salvataggio dei dati del file caricato
/// </summary>
/// <param name="fileDict">Dizionario info file</param>
private void SaveFile(Dictionary<string, string> fileDict)
{
// verifico di essere in edit...
if (EditRecord != null)
{
string folderPath = $"SO-{EditRecord.OfferID:X8}";
// 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);
}
}
}
/// <summary>
/// Esegue salvataggio del file ricevuto
/// </summary>
/// <param name="folderPath">Path relativo x file (tipicamente UID parent order)</param>
/// <param name="secureName">Nome secure da impiegare</param>
/// <param name="content">Contenuto file</param>
private bool saveFileContent(string folderPath, string secureName, string content)
@@ -1113,43 +1194,50 @@ namespace Lux.UI.Components.Compo
if (!string.IsNullOrEmpty(folderPath))
{
// calcolo path file...
string filePath = Path.Combine("unsafe_uploads", folderPath, secureName);
File.WriteAllText(filePath, content);
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;
}
/// <summary>
/// Salvataggio dei dati del file caricato
/// Restituisce il contenuto del file salvato
/// </summary>
/// <param name="fileDict">Dizionario info file</param>
private void SaveFile(Dictionary<string, string> fileDict)
/// <param name="folderPath"></param>
/// <param name="secureName"></param>
/// <returns></returns>
private string loadFileContent(string folderPath, string secureName)
{
// verifico di avere parametri...
if (fileDict != null && fileDict.Count > 0)
string answ = "";
if (!string.IsNullOrEmpty(folderPath))
{
string folderPath = "";
string secureName = "";
string content = "";
if (fileDict.ContainsKey("folderPath"))
try
{
folderPath = fileDict["folderPath"];
// calcolo path file...
string filePath = Path.Combine(basePath, folderPath, secureName);
if (File.Exists(filePath))
{
answ = File.ReadAllText(filePath);
}
}
if (fileDict.ContainsKey("secureName"))
catch (Exception exc)
{
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);
Log.Error($"Exception on loadFileContent{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
@@ -1200,6 +1288,37 @@ namespace Lux.UI.Components.Compo
}
}
/// <summary>
/// Verifia ammissibilità display btn ricalcolo BOM da item
/// </summary>
/// <param name="reqItem"></param>
/// <returns></returns>
private bool ShowBom(OfferRowModel reqItem)
{
bool answ = false;
if (DisplayMode == 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;
}
/// <summary>
/// Elenco SalesOfferRows calcolabili:
/// - contengono serializzazione come JWD
@@ -1239,35 +1358,6 @@ namespace Lux.UI.Components.Compo
}
}
/// <summary>
/// Verifia ammissibilità display btn ricalcolo BOM da item
/// </summary>
/// <param name="reqItem"></param>
/// <returns></returns>
private bool ShowBom(OfferRowModel reqItem)
{
bool answ = false;
if (DisplayMode == 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.SerStruct) && reqItem.SerStruct.Length > 2;
break;
case EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.NULL:
default:
break;
}
}
return answ;
}
/// <summary>
/// Filtro e paginazione
/// </summary>
+1 -1
View File
@@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50</UserSecretsId>
<Version>0.9.2511.0610</Version>
<Version>0.9.2511.0616</Version>
</PropertyGroup>
<ItemGroup>
+2 -1
View File
@@ -87,6 +87,7 @@
"ImageCalcTag": "live",
"ImageFileTag": "cache",
"ImageLiveTag": "svg",
"BaseUrl": "/lux/ui/"
"BaseUrl": "/lux/ui/",
"FileSharePath": "\\\\stor01\\TEAM DRIVES\\40_FileUpload\\LuxUploads"
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>LUX - Web Windows MES</i>
<h4>Versione: 0.9.2511.0610</h4>
<h4>Versione: 0.9.2511.0616</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
0.9.2511.0610
0.9.2511.0616
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>0.9.2511.0610</version>
<version>0.9.2511.0616</version>
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html</changelog>
<mandatory>false</mandatory>