Merge branch 'release/UpdateImgDisplay'
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EgwMultiEngineManager.Data" Version="2.7.8.5" />
|
||||
<PackageReference Include="Egw.Lux.WebWindowComplex" Version="2.7.10.1710" />
|
||||
<PackageReference Include="Egw.Window.Data" Version="2.7.10.1012" />
|
||||
<PackageReference Include="EgwMultiEngineManager.Data" Version="2.7.10.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EgwCoreLib.Lux.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Generico dizionario parametri con funzione ricerca valore (SE presente)
|
||||
/// </summary>
|
||||
public class ParamDict
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// init classe dal valore serializzato del dizionario
|
||||
/// </summary>
|
||||
/// <param name="rawVal"></param>
|
||||
public ParamDict(string rawVal)
|
||||
{
|
||||
DictVals = JsonConvert.DeserializeObject<Dictionary<string, string>>(rawVal) ?? new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// init classe da dizionario
|
||||
/// </summary>
|
||||
/// <param name="newDict"></param>
|
||||
public ParamDict(Dictionary<string, string> newDict)
|
||||
{
|
||||
DictVals = newDict;
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Versione serializzata del dizionario
|
||||
/// </summary>
|
||||
public string Serialized
|
||||
{
|
||||
get => JsonConvert.SerializeObject(DictVals);
|
||||
}
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Ricerca (se disponibile) il valore della chiave richiesta
|
||||
/// </summary>
|
||||
/// <param name="reqKey"></param>
|
||||
/// <returns></returns>
|
||||
public string GetVal(string reqKey)
|
||||
{
|
||||
string answ = "";
|
||||
if (DictVals.ContainsKey(reqKey))
|
||||
{
|
||||
answ = DictVals[reqKey];
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposta valore (aggiungendo se mancasse)
|
||||
/// </summary>
|
||||
/// <param name="Key"></param>
|
||||
/// <param name="Val"></param>
|
||||
public void SetVal(string Key, string Val)
|
||||
{
|
||||
if (DictVals.ContainsKey(Key))
|
||||
{
|
||||
DictVals[Key] = Val;
|
||||
}
|
||||
else
|
||||
{
|
||||
DictVals.Add(Key, Val);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Dizionario interno valori
|
||||
/// </summary>
|
||||
private Dictionary<string, string> DictVals { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.Data.DbModel.Admin;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,11 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Cost;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Production;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Stock;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Task;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using NLog;
|
||||
@@ -39,12 +46,16 @@ namespace EgwCoreLib.Lux.Data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual DbSet<CounterModel> DbSetCounters { get; set; }
|
||||
public virtual DbSet<GlassModel> DbSetConfGlass { get; set; }
|
||||
public virtual DbSet<ProfileModel> DbSetConfProfile { get; set; }
|
||||
public virtual DbSet<WoodModel> DbSetConfWood { get; set; }
|
||||
public virtual DbSet<EnvirParamModel> DbSetEnvirPar { get; set; }
|
||||
|
||||
public virtual DbSet<ItemGroupModel> DbSetItemGroup { get; set; }
|
||||
public virtual DbSet<ItemModel> DbSetItem { get; set; }
|
||||
public virtual DbSet<SellingItemModel> DbSetSellItem { get; set; }
|
||||
public virtual DbSet<TagsModel> DbSetRole { get; set; }
|
||||
public virtual DbSet<TagsModel> DbSetTags { get; set; }
|
||||
public virtual DbSet<CustomerModel> DbSetCustomer { get; set; }
|
||||
public virtual DbSet<DealerModel> DbSetDealer { get; set; }
|
||||
public virtual DbSet<SupplierModel> DbSetSupplier { get; set; }
|
||||
@@ -55,14 +66,18 @@ namespace EgwCoreLib.Lux.Data
|
||||
public virtual DbSet<ResourceModel> DbSetResource { get; set; }
|
||||
public virtual DbSet<PhaseModel> DbSetPhase { get; set; }
|
||||
public virtual DbSet<JobModel> DbSetJob { get; set; }
|
||||
public virtual DbSet<JobRowModel> DbSetJobRow { get; set; }
|
||||
public virtual DbSet<JobRowItemModel> DbSetJobRowItem { get; set; }
|
||||
public virtual DbSet<JobStepModel> DbSetJobRow { get; set; }
|
||||
public virtual DbSet<JobStepItemModel> DbSetJobRowItem { get; set; }
|
||||
public virtual DbSet<ProductionBatchModel> DbSetProdBatch { get; set; }
|
||||
public virtual DbSet<ProductionItemModel> DbSetProdItem { get; set; }
|
||||
public virtual DbSet<ProductionItemRowModel> DbSetProdItemRow { get; set; }
|
||||
public virtual DbSet<ProductionItemStepModel> DbSetProdItemRow { get; set; }
|
||||
public virtual DbSet<StockStatusModel> DbSetStockStatus { get; set; }
|
||||
public virtual DbSet<MovTypeModel> DbSetMovType { get; set; }
|
||||
public virtual DbSet<StockMovModel> DbSetStockMov { get; set; }
|
||||
public virtual DbSet<GenClassModel> DbSetGenClass { get; set; }
|
||||
public virtual DbSet<GenValueModel> DbSetGenVal { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
@@ -73,12 +88,23 @@ namespace EgwCoreLib.Lux.Data
|
||||
string connString = DbConfig.CONNECTION_STRING;
|
||||
if (string.IsNullOrEmpty(connString))
|
||||
{
|
||||
#if DEBUG
|
||||
connString = "Server=mdb.ufficio;port=3306;database=Lux_000;uid=lux_user;pwd=Egal_pwd!;sslmode=None;";
|
||||
//connString = "Server=mdb.ufficio;port=3306;database=Lux_000_dev;uid=lux_user;pwd=Egal_pwd!;sslmode=None;";
|
||||
#else
|
||||
connString = "Server=mdb.ufficio;port=3306;database=Lux_000;uid=lux_user;pwd=Egal_pwd!;sslmode=None;";
|
||||
#endif
|
||||
}
|
||||
if (!optionsBuilder.IsConfigured)
|
||||
{
|
||||
var serverVersion = ServerVersion.AutoDetect(connString);
|
||||
optionsBuilder.UseMySql(connString, serverVersion);
|
||||
// verificare setup componente
|
||||
#if false
|
||||
optionsBuilder
|
||||
.UseMySql(connString, serverVersion)
|
||||
.UseSnakeCaseNamingConvention(); // via EFCore.NamingConventions
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +119,13 @@ namespace EgwCoreLib.Lux.Data
|
||||
modelBuilder.Entity<CounterModel>()
|
||||
.HasKey(c => new { c.RefYear, c.CountName});
|
||||
|
||||
modelBuilder.Entity<GlassModel>()
|
||||
.HasKey(c => new { c.GlassID });
|
||||
modelBuilder.Entity<ProfileModel>()
|
||||
.HasKey(c => new { c.ProfileID });
|
||||
modelBuilder.Entity<WoodModel>()
|
||||
.HasKey(c => new { c.WoodID });
|
||||
|
||||
// fix valori timestamp
|
||||
modelBuilder.Entity<StockMovModel>(entity =>
|
||||
{
|
||||
|
||||
@@ -74,8 +74,12 @@ namespace EgwCoreLib.Lux.Data
|
||||
DATABASE_NAME = $"Lux_{nKey}";
|
||||
DATABASE_USER = $"user_{nKey}";
|
||||
DATABASE_PWD = $"pwd_{sKey}";
|
||||
CONNECTION_STRING = $"server={DATABASE_SERV};port=3306;database={DATABASE_NAME};uid={DATABASE_USER};pwd={DATABASE_PWD};sslmode=None";
|
||||
// stringa admin con utente root egalware...
|
||||
#if DEBUG
|
||||
CONNECTION_STRING = $"server={DATABASE_SERV};port=3306;database={DATABASE_NAME}_dev;uid={DATABASE_USER};pwd={DATABASE_PWD};sslmode=None";
|
||||
#else
|
||||
CONNECTION_STRING = $"server={DATABASE_SERV};port=3306;database={DATABASE_NAME};uid={DATABASE_USER};pwd={DATABASE_PWD};sslmode=None";
|
||||
#endif
|
||||
ADMIN_CONNECTION_STRING = $"server={DATABASE_SERV};port=3306;database=mysql;uid=root;pwd=Egalware_24068!;sslmode=None";
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.Data.DbModel.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Tabella dei USER di MySql
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Risorsa tipo di Glass x EF
|
||||
/// </summary>
|
||||
[Table("conf_envir")]
|
||||
public class EnvirParamModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID / Environment definito
|
||||
/// </summary>
|
||||
[Key]
|
||||
public EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS EnvirID { get; set; } = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW;
|
||||
|
||||
/// <summary>
|
||||
/// Chiave da impiegare nel dizionario x inviare la struttura serializzata da calcolare
|
||||
/// </summary>
|
||||
public string SerStrucKey { get; set; } = "SerStr";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Risorsa tipo di Glass x EF
|
||||
/// </summary>
|
||||
[Table("conf_glass")]
|
||||
public class GlassModel : Egw.Window.Data.Glass
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Risorsa tipo di Hardware x EF
|
||||
/// </summary>
|
||||
[Table("conf_Hardware")]
|
||||
public class HardwareModel : Egw.Window.Data.Hardware
|
||||
{
|
||||
public HardwareModel(string Id, string FamilyName, string Description, Egw.Window.Data.Enums.OpeningTypes OpeningType, string Shape, int SashQty, int SashPosition) : base(Id, FamilyName, Description, OpeningType, Shape, SashQty, SashPosition)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Risorsa tipo di Wood x EF
|
||||
/// </summary>
|
||||
[Table("conf_profile")]
|
||||
public class ProfileModel : Egw.Window.Data.Profile
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Risorsa tipo di Wood x EF
|
||||
/// </summary>
|
||||
[Table("conf_wood")]
|
||||
public class WoodModel : Egw.Window.Data.Wood
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Cost
|
||||
{
|
||||
/// <summary>
|
||||
/// Rappresenta la definizione di un Driver Risorsa da convertire in WorkOur (driver di ResourceModel)
|
||||
/// </summary>
|
||||
[Table("cost_driver")]
|
||||
public class CostDriverModel
|
||||
{
|
||||
[Key]
|
||||
public int CostDriverID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Nome driver
|
||||
/// e.g. "WorkHour"
|
||||
/// </summary>
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Nome dell'UM
|
||||
/// e.g. "hour", "meter"
|
||||
/// </summary>
|
||||
public string Unit { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione driver
|
||||
/// e.g. "WorkHour"
|
||||
/// </summary>
|
||||
public string Descript { get; set; } = "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Cost
|
||||
{
|
||||
/// <summary>
|
||||
/// Risorsa / Centro di Costo, con costi / Hourly
|
||||
/// </summary>
|
||||
[Table("cost_resource")]
|
||||
public class ResourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int ResourceID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Nome/Descrizione
|
||||
/// </summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// ID del driver di costo impiegato, tipicamente 1 = WorkHour
|
||||
/// </summary>
|
||||
public int CostDriverID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valore di riferimento del CostDriver per il calcolo dell'importo unitario della risorsa
|
||||
/// Se è basato su WorkHour diventa il budget annuale della risorsa disponibile
|
||||
/// Tipicamente le Ore di impiego a buget risorsa, es 220gg x 8h
|
||||
/// </summary>
|
||||
public decimal CostDriverBudget { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Costo totale (rif al CostDriverBudget) componente FIXED (macchinari) della risorsa (ove applicabile), comprendendo
|
||||
/// - ammortamenti
|
||||
/// - costi di manutenzione ordinaria
|
||||
/// - costi di manutenzione straordinaria (se stimabili, in periodo post ammortamento)
|
||||
/// </summary>
|
||||
public decimal FixedCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Costo totale (rif al CostDriverBudget) componente variabile (tipicamente Energia)
|
||||
/// nb: stima basata sul (costo medio energia aziendale) * consumo effettivo (se disponibile), altrimenti (stima potenza media impiegata) * (ore di impiego stimate)
|
||||
/// </summary>
|
||||
public decimal VariableCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Costo della componente HR sulla gestione impianto (rif al CostDriverBudget)
|
||||
/// </summary>
|
||||
public decimal LaborCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Costi di OverHead (rif al CostDriverBudget) da ribaltare su risorsa (tipicamente struttura)
|
||||
/// </summary>
|
||||
public decimal OverHeadCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Costo di overhead (come % on top del resto)
|
||||
/// </summary>
|
||||
public decimal OverHeadPerc { get; set; } = 0.15M;
|
||||
|
||||
/// <summary>
|
||||
/// EBT ovvero marginalità minima garantita on top del resto dei costi e OH
|
||||
/// </summary>
|
||||
public decimal EBTPerc { get; set; } = 0.1M;
|
||||
|
||||
/// <summary>
|
||||
/// Margine sul prezzo ovvero valore da potersi eventualmente scontare
|
||||
/// </summary>
|
||||
public decimal PriceMargin { get; set; } = 0.2M;
|
||||
|
||||
/// <summary>
|
||||
/// Costo Netto la risorsa su base CostDriver
|
||||
/// </summary>
|
||||
|
||||
[NotMapped]
|
||||
private decimal BaseNetCost
|
||||
{
|
||||
get => CostDriverBudget == 0 ? 0 : (FixedCost + VariableCost + OverHeadCost) / CostDriverBudget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo RockBottom Risorsa su base CostDriver
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public decimal BaseRockBottomCost
|
||||
{
|
||||
get => BaseNetCost * (1 + OverHeadPerc) * (1 + EBTPerc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo comprensivo di margine di ricarico massimo scontabile (sul RockBottom)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public decimal BasePrice
|
||||
{
|
||||
get => BaseRockBottomCost * (1 + PriceMargin);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Driver costo
|
||||
/// </summary>
|
||||
[ForeignKey("CostDriverID")]
|
||||
public virtual CostDriverModel DriverNav { get; set; } = null!;
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Indica gli asset/cespiti
|
||||
/// </summary>
|
||||
public bool IsAsset { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indica che è un operatore umano
|
||||
/// </summary>
|
||||
public bool IsHuman { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Costo fisso risorsa per UM tipo ammortamento
|
||||
/// </summary>
|
||||
public double UnitCostFix { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Unità di misura della risorsa tipo fisso/ammortamento
|
||||
/// </summary>
|
||||
public string UmFix { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Costo unitario risorsa per UM tipo consumabili
|
||||
/// </summary>
|
||||
public double UnitCostProp { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Unità di misura della risorsa
|
||||
/// </summary>
|
||||
public string UmProp { get; set; } = string.Empty;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -6,12 +6,12 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Items
|
||||
{ // <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegItemGroup")]
|
||||
[Table("item_group")]
|
||||
public class ItemGroupModel
|
||||
{
|
||||
|
||||
+4
-4
@@ -2,13 +2,13 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using static EgwCoreLib.Lux.Core.Enums;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Items
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegItem")]
|
||||
[Table("item_item")]
|
||||
public class ItemModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -85,7 +85,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
[NotMapped]
|
||||
public bool IsOkQty
|
||||
{
|
||||
get => QtyMax > 0 && (QtyMax - QtyMin) > 0;
|
||||
get => QtyMax > 0 && QtyMax - QtyMin > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -117,7 +117,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
[NotMapped]
|
||||
public bool IsProtected
|
||||
{
|
||||
get => this.ItemType == EgwCoreLib.Lux.Core.Enums.ItemClassType.Bom;
|
||||
get => ItemType == ItemClassType.Bom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
+12
-5
@@ -1,13 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Task;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Items
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("SellingItem")]
|
||||
[Table("item_selling_item")]
|
||||
public class SellingItemModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -16,6 +17,11 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
[Key]
|
||||
public int SellingItemID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Environment del selling item
|
||||
/// </summary>
|
||||
public EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS Envir { get; set; } = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW;
|
||||
|
||||
/// <summary>
|
||||
/// Definisce l'articolo come servizio vs concreto=materiale
|
||||
/// </summary>
|
||||
@@ -67,9 +73,10 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
public string SerStruct { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Json contenente la serializzazione delle fasi previste per la stima dei tempi e costi in formato SerializedPhasePreview; potrebbe contenere anche altre info accessorie x definire dati logistico/gestionali
|
||||
/// Elenco StepDTO (Fasi) per la stima tempi / costi
|
||||
/// potrebbe contenere anche altre info accessorie x definire dati logistico/gestionali
|
||||
/// </summary>
|
||||
public string ItemSPP { get; set; } = "";
|
||||
public string ItemSteps { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Job/Cicli
|
||||
+2
-2
@@ -6,13 +6,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Items
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegSupplier")]
|
||||
[Table("item_supplier")]
|
||||
public class SupplierModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
{
|
||||
|
||||
[Table("JobList")]
|
||||
public class JobModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int JobID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione del ciclo
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
{
|
||||
[Table("JobRowList")]
|
||||
public class JobRowModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int JobRowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ciclo di appartenenza
|
||||
/// </summary>
|
||||
public int JobID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indice della fase all'interno del Job
|
||||
/// </summary>
|
||||
public int Index { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// ID della fase realizzata
|
||||
/// </summary>
|
||||
public int PhaseID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID dellaa risorsa impiegata
|
||||
/// </summary>
|
||||
public int ResourceID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione della fase del Job
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Margine percentuale standard
|
||||
/// </summary>
|
||||
public double Qty { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Job/Cicli
|
||||
/// </summary>
|
||||
[ForeignKey("JobID")]
|
||||
public virtual JobModel JobNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Job/Cicli
|
||||
/// </summary>
|
||||
[ForeignKey("PhaseID")]
|
||||
public virtual PhaseModel PhaseNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Job/Cicli
|
||||
/// </summary>
|
||||
[ForeignKey("ResourceID")]
|
||||
public virtual ResourceModel ResourceNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("OfferRowList")]
|
||||
public class OfferRowModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int OfferRowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Riferimento offerta
|
||||
/// </summary>
|
||||
public int OfferID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Riga Offerta (per ordinamento)
|
||||
/// </summary>
|
||||
public int RowNum { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Campo salvato dell'Environment
|
||||
/// </summary>
|
||||
public string Environment { get; set; } = "WINDOW";
|
||||
|
||||
/// <summary>
|
||||
/// Campo salvato dell'UID da codice DataMatrix calcolato
|
||||
/// </summary>
|
||||
public string OfferRowUID { get; set; } = "OFF00001230AZ";
|
||||
|
||||
/// <summary>
|
||||
/// Codice calcolato offerta ANNO.ID_RIGA_OFFERTA (0...Z come Dtx)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string OfferRowDtx
|
||||
{
|
||||
get => $"OFF{Inserted.Year:yy}{OfferRowID:000000000}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ID dell'articolo di vendita offerto
|
||||
/// </summary>
|
||||
public int SellingItemID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Costo (standard / senza listini)
|
||||
/// </summary>
|
||||
public double Cost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Margine percentuale standard
|
||||
/// </summary>
|
||||
public double Qty { get; set; } = 1;
|
||||
|
||||
[NotMapped]
|
||||
public double TotalCost
|
||||
{
|
||||
get => Qty * Cost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Valore serializzato della composizione articolo (in formato JWD x finestra)
|
||||
/// </summary>
|
||||
public string SerStruct { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Json contenente la serializzazione delle fasi previste per la stima dei tempi e costi in formato SerializedPhasePreview; potrebbe contenere anche altre info accessorie x definire dati logistico/gestionali
|
||||
/// </summary>
|
||||
public string ItemSPP { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// BOM serializzata per la produzione dell'item
|
||||
/// </summary>
|
||||
public string ItemBOM { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Validazione dati BOM (Inteso come gruppi tutti trovati/esistenti)
|
||||
/// </summary>
|
||||
public bool BomOk { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Validazione livello item per Costo e range dimensione
|
||||
/// </summary>
|
||||
public bool ItemOk { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Note libere
|
||||
/// </summary>
|
||||
public string Note { get; set; } = "";
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Stack degli ultimi item serializzati per Uno/Redo actions
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public List<string> UndoRedoSerStruct { get; set; } = new List<string>();
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DataOra inserimento
|
||||
/// </summary>
|
||||
public DateTime Inserted { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// DataOra ultima modifica
|
||||
/// </summary>
|
||||
public DateTime Modified { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Offer
|
||||
/// </summary>
|
||||
[ForeignKey("OfferID")]
|
||||
public virtual OfferModel OfferNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Item
|
||||
/// </summary>
|
||||
[ForeignKey("SellingItemID")]
|
||||
public virtual SellingItemModel SellingItemNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Production
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("ProductionBatch")]
|
||||
[Table("production_batch")]
|
||||
public class ProductionBatchModel
|
||||
{
|
||||
/// <summary>
|
||||
+4
-3
@@ -1,13 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Production
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("ProductionItem")]
|
||||
[Table("production_item")]
|
||||
public class ProductionItemModel
|
||||
{
|
||||
/// <summary>
|
||||
+8
-6
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Cost;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Task;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
@@ -9,19 +11,19 @@ using System.Threading.Tasks;
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Production
|
||||
{
|
||||
/// <summary>
|
||||
/// Tabella delel effettiva righe della fgasi di lavorazione x ogni item da produrre
|
||||
/// Tabella delle fasi di lavorazione x ogni item da produrre
|
||||
/// </summary>
|
||||
[Table("ProductionItemRowList")]
|
||||
public class ProductionItemRowModel
|
||||
[Table("production_item_step")]
|
||||
public class ProductionItemStepModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int ProdItemRowID { get; set; }
|
||||
public int ProdItemStepID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Item di appartenenza
|
||||
@@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
{
|
||||
[Table("RegResource")]
|
||||
public class ResourceModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int ResourceID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Indica gli assec/cespiti
|
||||
/// </summary>
|
||||
public bool IsAsset { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indica che è un operatore umano
|
||||
/// </summary>
|
||||
public bool IsHuman { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Costo fisso risorsa per UM tipo ammortamento
|
||||
/// </summary>
|
||||
public double UnitCostFix { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Unità di misura della risorsa tipo fisso/ammortamento
|
||||
/// </summary>
|
||||
public string UmFix { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Costo unitario risorsa per UM tipo consumabili
|
||||
/// </summary>
|
||||
public double UnitCostProp { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Unità di misura della risorsa
|
||||
/// </summary>
|
||||
public string UmProp { get; set; } = "";
|
||||
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -6,13 +6,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegCustomer")]
|
||||
[Table("sales_customer")]
|
||||
public class CustomerModel
|
||||
{
|
||||
/// <summary>
|
||||
+2
-2
@@ -6,13 +6,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegDealer")]
|
||||
[Table("sales_dealer")]
|
||||
public class DealerModel
|
||||
{
|
||||
/// <summary>
|
||||
+56
-14
@@ -1,20 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static EgwCoreLib.Lux.Core.Enums;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("Offer")]
|
||||
[Table("sales_offer")]
|
||||
public class OfferModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -23,6 +17,11 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
[Key]
|
||||
public int OfferID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Environment della richiesta
|
||||
/// </summary>
|
||||
public EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS Envir { get; set; } = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW;
|
||||
|
||||
/// <summary>
|
||||
/// Anno rif offerta
|
||||
/// </summary>
|
||||
@@ -40,11 +39,12 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
|
||||
/// <summary>
|
||||
/// Codice calcolato offerta ANNO.NUMERO.REV
|
||||
/// inizia per SO = SalesOffer
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string OfferCode
|
||||
{
|
||||
get => $"{RefYear:00}.{RefNum:00000}.{RefRev:00}";
|
||||
get => $"SO.{RefYear:00}.{RefNum:000000}.{RefRev:000}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -62,6 +62,16 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// </summary>
|
||||
public int DealerID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dizionario serializzato delle preselezioni (opzionale)
|
||||
/// </summary>
|
||||
public string DictPresel { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// note di consegna (opzionali)
|
||||
/// </summary>
|
||||
public string ConsNote { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Validità offerta
|
||||
/// </summary>
|
||||
@@ -77,30 +87,61 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// </summary>
|
||||
public DateTime Modified { get; set; } = DateTime.Now;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enum stato offerta
|
||||
/// </summary>
|
||||
public OfferStates OffertState { get; set; } = OfferStates.Open;
|
||||
|
||||
/// <summary>
|
||||
/// Sconto applicato (deve essere < del MAX)
|
||||
/// </summary>
|
||||
public double Discount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Numero Item compresi
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public int NumItems
|
||||
public double NumItems
|
||||
{
|
||||
get => OfferRowNav?.Sum(x => x.Qty) ?? 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Numero Item compresi
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public int NumRows
|
||||
{
|
||||
get => OfferRowNav?.Count ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposto totale offerta
|
||||
/// Costo totale offerta (rock bottom)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double TotalCost
|
||||
{
|
||||
get => OfferRowNav?.Sum(x => x.Cost) ?? 0;
|
||||
get => OfferRowNav?.Sum(x => x.TotalCost) ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo totale offerta (compreso di amrginalità)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double TotalPrice
|
||||
{
|
||||
get => OfferRowNav?.Sum(x => x.TotalPrice) ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sconto massimo applicabile
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double MaxDiscount
|
||||
{
|
||||
get => (TotalCost > 0 && TotalPrice > TotalCost) ? (TotalPrice - TotalCost) / TotalPrice : 0;
|
||||
}
|
||||
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// ID Ordine (nullo se non c'è ordine)
|
||||
@@ -126,6 +167,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
[ForeignKey("DealerID")]
|
||||
public virtual DealerModel DealerNav { get; set; } = null!;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione alle righe offerta
|
||||
/// </summary>
|
||||
@@ -0,0 +1,214 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
{
|
||||
|
||||
[Table("sales_offer_row")]
|
||||
public class OfferRowModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int OfferRowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Riferimento offerta
|
||||
/// </summary>
|
||||
public int OfferID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Riga Offerta (per ordinamento)
|
||||
/// </summary>
|
||||
public int RowNum { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Environment della richiesta
|
||||
/// </summary>
|
||||
public EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS Envir { get; set; } = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW;
|
||||
|
||||
/// <summary>
|
||||
/// Campo salvato dell'UID da codice DataMatrix calcolato
|
||||
/// inizia per SOR = SalesOfferRow
|
||||
/// </summary>
|
||||
public string OfferRowUID { get; set; } = "SOR.25.0123ABCD";
|
||||
|
||||
/// <summary>
|
||||
/// Codice calcolato offerta ANNO.ID_RIGA_OFFERTA in HEX (0xFFFFFFFF)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string OfferRowDtx
|
||||
{
|
||||
get => $"SOR.{Inserted:yy}.{OfferRowID:X8}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ID dell'articolo di vendita offerto
|
||||
/// </summary>
|
||||
public int SellingItemID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Quantità della risorsa
|
||||
/// </summary>
|
||||
public double Qty { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Costo dei componeti BOM (RockBottom)
|
||||
/// </summary>
|
||||
public double BomCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo dei componeti BOM (scontabile)
|
||||
/// </summary>
|
||||
public double BomPrice { get; set; } = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Costo produzione Fase/Step (RockBottom)
|
||||
/// </summary>
|
||||
public double StepCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo produzione Fase/Step (scontabile)
|
||||
/// </summary>
|
||||
public double StepPrice { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale Risorsa (BOM + Fase)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double UnitCost
|
||||
{
|
||||
get => BomCost + StepCost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale Risorsa (BOM + Fase)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double UnitPrice
|
||||
{
|
||||
get => BomPrice + StepPrice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sconto massimo applicabile
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double MaxDiscount
|
||||
{
|
||||
get => (UnitCost > 0 && UnitPrice > UnitCost) ? (UnitPrice - UnitCost) / UnitPrice : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale risorsa
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double TotalCost
|
||||
{
|
||||
get => UnitCost * Qty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale risorsa
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double TotalPrice
|
||||
{
|
||||
get => UnitPrice * Qty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Valore serializzato della composizione articolo (in formato JWD x finestra)
|
||||
/// </summary>
|
||||
public string SerStruct { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Nomi risorsa file associato alla riga offerta (es per BTL)
|
||||
/// URI come risorsa dentro folder offerta/riga-offerta/guid
|
||||
/// </summary>
|
||||
public string FileResource { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Nomi file originale associato alla riga offerta (es per BTL)
|
||||
/// </summary>
|
||||
public string FileName { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Dimensione del file (per visualizzazione rapida)
|
||||
/// </summary>
|
||||
public long FileSize { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Elenco StepDTO (Fasi) per la stima tempi / costi
|
||||
/// potrebbe contenere anche altre info accessorie x definire dati logistico/gestionali
|
||||
/// </summary>
|
||||
public string ItemSteps { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// BOM serializzata per la produzione dell'item
|
||||
/// </summary>
|
||||
public string ItemBOM { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Validazione dati BOM (Inteso come gruppi tutti trovati/esistenti)
|
||||
/// </summary>
|
||||
public bool BomOk { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Validazione livello item per Costo e range dimensione
|
||||
/// </summary>
|
||||
public bool ItemOk { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Note libere
|
||||
/// </summary>
|
||||
public string Note { get; set; } = "";
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Stack degli ultimi item serializzati per Uno/Redo actions
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public List<string> UndoRedoSerStruct { get; set; } = new List<string>();
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DataOra inserimento
|
||||
/// </summary>
|
||||
public DateTime Inserted { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// DataOra ultima modifica
|
||||
/// </summary>
|
||||
public DateTime Modified { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Indica che è in attesa aggiornamento BOM
|
||||
/// </summary>
|
||||
public bool AwaitBom { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indica che è in attesa aggiornamento Price
|
||||
/// </summary>
|
||||
public bool AwaitPrice { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Offer
|
||||
/// </summary>
|
||||
[ForeignKey("OfferID")]
|
||||
public virtual OfferModel OfferNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Item
|
||||
/// </summary>
|
||||
[ForeignKey("SellingItemID")]
|
||||
public virtual SellingItemModel SellingItemNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -8,7 +8,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static EgwCoreLib.Lux.Core.Enums;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
@@ -17,7 +17,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// <summary>
|
||||
/// Classe degli ordini commerciali
|
||||
/// </summary>
|
||||
[Table("Order")]
|
||||
[Table("sales_order")]
|
||||
public class OrderModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -70,6 +70,16 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// </summary>
|
||||
public int DealerID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// note di consegna (opzionali)
|
||||
/// </summary>
|
||||
public string ConsNote { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Dizionario serializzato delle preselezioni (opzionale)
|
||||
/// </summary>
|
||||
public string DictPresel { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Validità Ordine
|
||||
/// </summary>
|
||||
+68
-10
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
@@ -7,13 +8,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("OrderRowList")]
|
||||
[Table("sales_order_row")]
|
||||
public class OrderRowModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -33,12 +34,13 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
public int RowNum { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Codice calcolato Ordine ANNO.NUMERO.REV
|
||||
/// Codice calcolato Ordine ANNO.NUMERO
|
||||
/// inizia per PO = PurchaseOrder
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string OrderRowCode
|
||||
{
|
||||
get => $"{OrderRowID:0000}.{RowNum:000}";
|
||||
get => $"PO{OrderRowID:000000}.{RowNum:000}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,19 +49,74 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
public int SellingItemID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Costo (standard / senza listini)
|
||||
/// Costo dei componeti BOM (RockBottom)
|
||||
/// </summary>
|
||||
public double Cost { get; set; } = 0;
|
||||
public double BomCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Margine percentuale standard
|
||||
/// </summary>
|
||||
public double Qty { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo dei componeti BOM (scontabile)
|
||||
/// </summary>
|
||||
public double BomPrice { get; set; } = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Costo produzione Fase/Step (RockBottom)
|
||||
/// </summary>
|
||||
public double StepCost { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo produzione Fase/Step (scontabile)
|
||||
/// </summary>
|
||||
public double StepPrice { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale Risorsa (BOM + Fase)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double UnitCost
|
||||
{
|
||||
get => BomCost + StepCost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale Risorsa (BOM + Fase)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double UnitPrice
|
||||
{
|
||||
get => BomPrice + StepPrice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sconto massimo applicabile
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double MaxDiscount
|
||||
{
|
||||
get => (UnitCost > 0 && UnitPrice > UnitCost) ? (UnitPrice - UnitCost) / UnitPrice : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale risorsa
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double TotalCost
|
||||
{
|
||||
get => Qty * Cost;
|
||||
get => UnitCost * Qty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costo Totale risorsa
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public double TotalPrice
|
||||
{
|
||||
get => UnitPrice * Qty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,9 +125,10 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
public string SerStruct { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Json contenente la serializzazione delle fasi previste per la stima dei tempi e costi in formato SerializedPhasePreview; potrebbe contenere anche altre info accessorie x definire dati logistico/gestionali
|
||||
/// Elenco StepDTO (Fasi) per la stima tempi / costi
|
||||
/// potrebbe contenere anche altre info accessorie x definire dati logistico/gestionali
|
||||
/// </summary>
|
||||
public string ItemSPP { get; set; } = "";
|
||||
public string ItemSteps { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Note libere
|
||||
+5
-4
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
@@ -6,7 +7,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Stock
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
@@ -14,7 +15,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// <summary>
|
||||
/// Tabella dei movimenti degli item in giacenza
|
||||
/// </summary>
|
||||
[Table("StockMov")]
|
||||
[Table("stock_mov")]
|
||||
public class StockMovModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -39,7 +40,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
public DateTime DtMod { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Qty movimento registrato (delta +/-)
|
||||
/// ProductivityRate movimento registrato (delta +/-)
|
||||
/// </summary>
|
||||
public double QtyRec { get; set; } = 0;
|
||||
|
||||
+5
-4
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
@@ -6,7 +7,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Stock
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
@@ -15,7 +16,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// Tabelal delle giacenze di magazzino
|
||||
/// </summary>
|
||||
|
||||
[Table("StockStatus")]
|
||||
[Table("stock_status")]
|
||||
public class StockStatusModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -30,7 +31,7 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
public int ItemID { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Qty in giacenza
|
||||
/// ProductivityRate in giacenza
|
||||
/// </summary>
|
||||
public double QtyAvail { get; set; } = 0;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Definizione macro dei Cicli di Lavoro / Job
|
||||
/// </summary>
|
||||
[Table("task_job")]
|
||||
public class JobModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int JobID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione del ciclo di lavoro
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Navigation verso JobStep
|
||||
/// </summary>
|
||||
public virtual ICollection<JobStepModel> JobStepNav { get; set; } = new List<JobStepModel>();
|
||||
}
|
||||
}
|
||||
+8
-12
@@ -1,29 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Task
|
||||
{
|
||||
[Table("JobRowItemList")]
|
||||
public class JobRowItemModel
|
||||
[Table("task_job_step_item")]
|
||||
public class JobStepItemModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int JobRowItemID { get; set; }
|
||||
public int JobStepItemID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fase del Ciclo di appartenenza
|
||||
/// </summary>
|
||||
public int JobRowID { get; set; }
|
||||
public int JobStepID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indice della fase all'interno del Job
|
||||
@@ -48,8 +44,8 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// <summary>
|
||||
/// Navigazione su fasi ciclo
|
||||
/// </summary>
|
||||
[ForeignKey("JobRowID")]
|
||||
public virtual JobRowModel JobRowNav { get; set; } = null!;
|
||||
[ForeignKey("JobStepID")]
|
||||
public virtual JobStepModel JobStepNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione su Items
|
||||
@@ -0,0 +1,116 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Cost;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Task;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Task
|
||||
{
|
||||
/// <summary>
|
||||
/// Routing dei cicli di lavoro, con riferimento a risorse e fasi
|
||||
/// </summary>
|
||||
[Table("task_job_step")]
|
||||
public class JobStepModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int JobStepID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ciclo di appartenenza
|
||||
/// </summary>
|
||||
public int JobID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indice della fase all'interno del Job
|
||||
/// </summary>
|
||||
public int Index { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// ID del driver di costo impiegato
|
||||
/// </summary>
|
||||
public int CostDriverID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID della fase realizzata
|
||||
/// </summary>
|
||||
public int PhaseID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID della risorsa impiegata
|
||||
/// </summary>
|
||||
public int ResourceID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione della fase del Job
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Rapporto produttività tra CostDriver Step e CostDriver Risorsa (es: m/h)
|
||||
/// </summary>
|
||||
public decimal ProductivityRate { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Costo RockBottom Fase (step) di produzione
|
||||
/// sulla base del costo della risorsa, della produttività e della quantità impiegata
|
||||
/// </summary>
|
||||
/// <param name="quantity">Quantità risorsa impiegata</param>
|
||||
/// <returns></returns>
|
||||
public decimal RockBottomCost(decimal quantity)
|
||||
{
|
||||
decimal stepCost = 0;
|
||||
var unitRequired = quantity / ProductivityRate;
|
||||
if (ResourceNav != null)
|
||||
{
|
||||
stepCost = ResourceNav.BaseRockBottomCost * quantity;
|
||||
}
|
||||
return stepCost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prezzo calcolato per Fase (step) di produzione
|
||||
/// sulla base del costo RockBottom + marginalità standard
|
||||
/// </summary>
|
||||
/// <param name="quantity">Quantità risorsa impiegata</param>
|
||||
/// <returns></returns>
|
||||
public decimal RockBottomPrice(decimal quantity)
|
||||
{
|
||||
decimal stepCost = 0;
|
||||
var unitRequired = quantity / ProductivityRate;
|
||||
if (ResourceNav != null)
|
||||
{
|
||||
stepCost = ResourceNav.BasePrice * quantity;
|
||||
}
|
||||
return stepCost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Job/Cicli
|
||||
/// </summary>
|
||||
[ForeignKey("JobID")]
|
||||
public virtual JobModel JobNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Driver costo
|
||||
/// </summary>
|
||||
[ForeignKey("CostDriverID")]
|
||||
public virtual CostDriverModel DriverNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Fasi
|
||||
/// </summary>
|
||||
[ForeignKey("PhaseID")]
|
||||
public virtual PhaseModel PhaseNav { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione Risorse
|
||||
/// </summary>
|
||||
[ForeignKey("ResourceID")]
|
||||
public virtual ResourceModel ResourceNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -9,10 +9,12 @@ using System.Threading.Tasks;
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Task
|
||||
{
|
||||
|
||||
[Table("RegPhase")]
|
||||
/// <summary>
|
||||
/// Fase di lavorazione / ProductionStage
|
||||
/// </summary>
|
||||
[Table("task_phase")]
|
||||
public class PhaseModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -25,7 +27,5 @@ namespace EgwCoreLib.Lux.Data.DbModel
|
||||
/// Descrizione
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -6,13 +6,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Utils
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("Counter")]
|
||||
[Table("utils_counter")]
|
||||
public class CounterModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Utils
|
||||
{
|
||||
|
||||
[Table("utils_gen_class")]
|
||||
public class GenClassModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Cod della classe
|
||||
/// </summary>
|
||||
[Key]
|
||||
public string ClassCod { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Descrizione
|
||||
/// </summary>
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Numero Item compresi
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public int NumChild
|
||||
{
|
||||
get => GenValNav?.Count ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione alle righe dei valori associati
|
||||
/// </summary>
|
||||
public virtual ICollection<GenValueModel> GenValNav { get; set; } = new List<GenValueModel>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Utils
|
||||
{
|
||||
|
||||
[Table("utils_gen_value")]
|
||||
public class GenValueModel
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del record
|
||||
/// </summary>
|
||||
[Key]
|
||||
public int GenValID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Riferimento Classe di appartenenza
|
||||
/// </summary>
|
||||
public string ClassCod { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Valore ordinale (entro classe)
|
||||
/// </summary>
|
||||
public int Ordinal { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Valore String
|
||||
/// </summary>
|
||||
public string ValString { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Navigazione GenClass
|
||||
/// </summary>
|
||||
[ForeignKey("ClassCod")]
|
||||
public virtual GenClassModel GenClassNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -6,12 +6,12 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Utils
|
||||
{ // <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegMovType")]
|
||||
[Table("utils_mov_type")]
|
||||
public class MovTypeModel
|
||||
{
|
||||
|
||||
+2
-2
@@ -6,13 +6,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.DbModel
|
||||
namespace EgwCoreLib.Lux.Data.DbModel.Utils
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
|
||||
[Table("RegTags")]
|
||||
[Table("utils_tags")]
|
||||
public class TagsModel
|
||||
{
|
||||
/// <summary>
|
||||
@@ -17,6 +17,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="DbModel\Cost\Enums.cs" />
|
||||
<Compile Remove="Services\ExternalMessageProcessor.cs" />
|
||||
<Compile Remove="Services\RedisSubscriberServiceOld.cs" />
|
||||
</ItemGroup>
|
||||
@@ -26,6 +27,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Egw.Lux.WebWindow.Base" Version="2.7.10.1710" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.17" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.17" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="8.0.17" />
|
||||
@@ -40,7 +42,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="NLog" Version="6.0.1" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
|
||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||
@@ -48,6 +50,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DbModel\Engine\" />
|
||||
<Folder Include="Migrations\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,310 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddItemParentRel : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ItemIDParent",
|
||||
table: "RegItem",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Offer",
|
||||
keyColumn: "OfferID",
|
||||
keyValue: 1,
|
||||
columns: new[] { "Inserted", "Modified", "ValidUntil" },
|
||||
values: new object[] { new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9069), new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9071), new DateTime(2025, 10, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9064) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "OfferRowList",
|
||||
keyColumn: "OfferRowID",
|
||||
keyValue: 1,
|
||||
columns: new[] { "Inserted", "Modified" },
|
||||
values: new object[] { new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9104), new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9106) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "OfferRowList",
|
||||
keyColumn: "OfferRowID",
|
||||
keyValue: 2,
|
||||
columns: new[] { "Inserted", "Modified" },
|
||||
values: new object[] { new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9114), new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9116) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "OfferRowList",
|
||||
keyColumn: "OfferRowID",
|
||||
keyValue: 3,
|
||||
columns: new[] { "Inserted", "Modified" },
|
||||
values: new object[] { new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9123), new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(9125) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 1,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 2,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 3,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 4,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 5,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 6,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 7,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 8,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 9,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 10,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 11,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "RegItem",
|
||||
keyColumn: "ItemID",
|
||||
keyValue: 12,
|
||||
column: "ItemIDParent",
|
||||
value: 0);
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 1,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8693));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 2,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8785));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 3,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8790));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 4,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8794));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 5,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8799));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 6,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8803));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 7,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8808));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 8,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8812));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 9,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8817));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 10,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 9, 16, 17, 23, 0, 861, DateTimeKind.Local).AddTicks(8821));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ItemIDParent",
|
||||
table: "RegItem");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Offer",
|
||||
keyColumn: "OfferID",
|
||||
keyValue: 1,
|
||||
columns: new[] { "Inserted", "Modified", "ValidUntil" },
|
||||
values: new object[] { new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4215), new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4216), new DateTime(2025, 9, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4212) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "OfferRowList",
|
||||
keyColumn: "OfferRowID",
|
||||
keyValue: 1,
|
||||
columns: new[] { "Inserted", "Modified" },
|
||||
values: new object[] { new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4243), new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4245) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "OfferRowList",
|
||||
keyColumn: "OfferRowID",
|
||||
keyValue: 2,
|
||||
columns: new[] { "Inserted", "Modified" },
|
||||
values: new object[] { new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4252), new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4253) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "OfferRowList",
|
||||
keyColumn: "OfferRowID",
|
||||
keyValue: 3,
|
||||
columns: new[] { "Inserted", "Modified" },
|
||||
values: new object[] { new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4259), new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4261) });
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 1,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(3939));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 2,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(3989));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 3,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(3993));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 4,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(3997));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 5,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4000));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 6,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4004));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 7,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4008));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 8,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4011));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 9,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4015));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StockMov",
|
||||
keyColumn: "StockMovID",
|
||||
keyValue: 10,
|
||||
column: "DtCreate",
|
||||
value: new DateTime(2025, 8, 8, 16, 36, 28, 420, DateTimeKind.Local).AddTicks(4019));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1745
-854
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,11 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Cost;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Stock;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Task;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data
|
||||
{
|
||||
@@ -18,7 +19,8 @@ namespace EgwCoreLib.Lux.Data
|
||||
/// <param name="modelBuilder"></param>
|
||||
public static void Seed(this ModelBuilder modelBuilder)
|
||||
{
|
||||
// inizializzazione dei valori di default x Ruoli
|
||||
|
||||
// inizializzazione dei valori di default x Ruoli/Tags
|
||||
modelBuilder.Entity<TagsModel>().HasData(
|
||||
new TagsModel { TagID = 1, Description = "Tag 01" },
|
||||
new TagsModel { TagID = 2, Description = "Tag 02" },
|
||||
@@ -27,6 +29,60 @@ namespace EgwCoreLib.Lux.Data
|
||||
new TagsModel { TagID = 5, Description = "Tag 05" }
|
||||
);
|
||||
|
||||
// init classi generiche x gestione liste
|
||||
modelBuilder.Entity<GenClassModel>().HasData(
|
||||
new GenClassModel { ClassCod = "ShapeList", Description = "Elenco Shape Gestite" },
|
||||
new GenClassModel { ClassCod = "WoodCol", Description = "Elenco Colori Legno" }
|
||||
);
|
||||
|
||||
// init dati x invio serializzazioni da environment
|
||||
modelBuilder.Entity<EnvirParamModel>().HasData(
|
||||
new EnvirParamModel { EnvirID = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, SerStrucKey = "Jwd" },
|
||||
new EnvirParamModel { EnvirID = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM, SerStrucKey = "Btl" },
|
||||
new EnvirParamModel { EnvirID = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET, SerStrucKey = "Btl" },
|
||||
new EnvirParamModel { EnvirID = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL, SerStrucKey = "Btl" }
|
||||
);
|
||||
|
||||
modelBuilder.Entity<GenValueModel>().HasData(
|
||||
new GenValueModel { GenValID = 1, Ordinal = 1, ClassCod = "WoodCol", ValString = "Blue" },
|
||||
new GenValueModel { GenValID = 2, Ordinal = 2, ClassCod = "WoodCol", ValString = "White" },
|
||||
new GenValueModel { GenValID = 3, Ordinal = 3, ClassCod = "WoodCol", ValString = "Red" },
|
||||
new GenValueModel { GenValID = 4, Ordinal = 4, ClassCod = "WoodCol", ValString = "Black" },
|
||||
new GenValueModel { GenValID = 5, Ordinal = 1, ClassCod = "ShapeList", ValString = "Rectangular" },
|
||||
new GenValueModel { GenValID = 6, Ordinal = 2, ClassCod = "ShapeList", ValString = "Trapezoidal" },
|
||||
new GenValueModel { GenValID = 7, Ordinal = 3, ClassCod = "ShapeList", ValString = "Triangular" },
|
||||
new GenValueModel { GenValID = 8, Ordinal = 4, ClassCod = "ShapeList", ValString = "Arc" },
|
||||
new GenValueModel { GenValID = 9, Ordinal = 5, ClassCod = "ShapeList", ValString = "FullArc" },
|
||||
new GenValueModel { GenValID = 10, Ordinal = 6, ClassCod = "ShapeList", ValString = "SemiFullArc" },
|
||||
new GenValueModel { GenValID = 11, Ordinal = 7, ClassCod = "ShapeList", ValString = "SemiArc" },
|
||||
new GenValueModel { GenValID = 12, Ordinal = 8, ClassCod = "ShapeList", ValString = "Circular" }
|
||||
);
|
||||
|
||||
modelBuilder.Entity<GlassModel>().HasData(
|
||||
new GlassModel { GlassID = 1, Code = "0001", Description = "Vetro BE 2S 4/12/4", Thickness = 20 },
|
||||
new GlassModel { GlassID = 2, Code = "0002", Description = "Vetro BE 2S 4/16/4", Thickness = 24 },
|
||||
new GlassModel { GlassID = 3, Code = "0003", Description = "Vetro BE 3S 4/12/4/12/4", Thickness = 36 },
|
||||
new GlassModel { GlassID = 4, Code = "0004", Description = "Vetro BE 3S 4/16/4/16/4", Thickness = 44 },
|
||||
new GlassModel { GlassID = 5, Code = "0005", Description = "Vetro BE 2S 4T/12/4T", Thickness = 20 },
|
||||
new GlassModel { GlassID = 6, Code = "0006", Description = "Vetro BE 2S 4T/16/4T", Thickness = 24 },
|
||||
new GlassModel { GlassID = 7, Code = "0007", Description = "Vetro BE 3S 4T/12/4T/12/4T", Thickness = 36 },
|
||||
new GlassModel { GlassID = 8, Code = "0008", Description = "Vetro BE 3S 4T/16/4T/16/4T", Thickness = 44 }
|
||||
);
|
||||
modelBuilder.Entity<ProfileModel>().HasData(
|
||||
new ProfileModel { ProfileID = 1, Code = "0001", Description = "Profilo60", Thickness = 60 },
|
||||
new ProfileModel { ProfileID = 2, Code = "0002", Description = "Profilo78", Thickness = 78 },
|
||||
new ProfileModel { ProfileID = 3, Code = "0003", Description = "Profilo90", Thickness = 90 }
|
||||
);
|
||||
modelBuilder.Entity<WoodModel>().HasData(
|
||||
new WoodModel { WoodID = 1, Code = "0001", Description = "Abete", Type = 1 },
|
||||
new WoodModel { WoodID = 2, Code = "0002", Description = "Acero", Type = 1 },
|
||||
new WoodModel { WoodID = 3, Code = "0003", Description = "Pino", Type = 2 },
|
||||
new WoodModel { WoodID = 4, Code = "0004", Description = "Tek", Type = 3 }
|
||||
);
|
||||
|
||||
|
||||
// valori base classi generiche
|
||||
|
||||
// inizializzazione dei valori di default x Customer
|
||||
modelBuilder.Entity<CustomerModel>().HasData(
|
||||
new CustomerModel { CustomerID = 1, FirstName = "Customer A", LastName = "Egalware", VAT = "1234567890123456" },
|
||||
@@ -131,15 +187,23 @@ namespace EgwCoreLib.Lux.Data
|
||||
new StockMovModel { StockMovID = 10, StockStatusId = 10, QtyRec = 1, MovCod = "CAR", UserId = "samuele.locatelli@egalware.com", Note = "DEMO" }
|
||||
);
|
||||
|
||||
// init cost drivers
|
||||
modelBuilder.Entity<CostDriverModel>().HasData(
|
||||
// Risorsa principale di calcolo produttività/costi
|
||||
new CostDriverModel() { CostDriverID = 1, Name = "WorkHour", Unit = "h", Descript = "Ore lavorate per step/fase" },
|
||||
new CostDriverModel() { CostDriverID = 2, Name = "Meter", Unit = "m", Descript = "Metri prodotti per step/fase" },
|
||||
new CostDriverModel() { CostDriverID = 3, Name = "Unit", Unit = "#", Descript = "Numero unità prodotte (lavorate) per step/fase" }
|
||||
);
|
||||
|
||||
// inizializzazione risorse
|
||||
modelBuilder.Entity<ResourceModel>().HasData(
|
||||
new ResourceModel { ResourceID = 1, Description = "Sezionatrice", IsAsset = true, IsHuman = false, UnitCostFix = 15, UmFix = "€/h" },
|
||||
new ResourceModel { ResourceID = 2, Description = "Linea SAOMAD WoodPecker Just 3500", IsAsset = true, IsHuman = false, UnitCostFix = 240, UmFix = "€/h", UnitCostProp = 1.9, UmProp = "€/m" },
|
||||
new ResourceModel { ResourceID = 3, Description = "Linea Pantografo", IsAsset = true, IsHuman = false, UnitCostFix = 90, UmFix = "€/h", UnitCostProp = 5.9, UmProp = "€/m" },
|
||||
new ResourceModel { ResourceID = 4, Description = "Stazione Verniciatura", IsAsset = true, IsHuman = false, UnitCostFix = 40, UmFix = "€/h", UnitCostProp = 1.9, UmProp = "€/m" },
|
||||
new ResourceModel { ResourceID = 5, Description = "Verniciatura Manuale", IsAsset = false, IsHuman = true, UnitCostFix = 10, UmFix = "€/h", UnitCostProp = 1.9, UmProp = "€/m" },
|
||||
new ResourceModel { ResourceID = 6, Description = "Montaggio Manuale", IsAsset = false, IsHuman = true, UnitCostProp = 40, UmProp = "€/h" },
|
||||
new ResourceModel { ResourceID = 7, Description = "Installatore", IsAsset = false, IsHuman = true, UnitCostProp = 40, UmProp = "€/h" }
|
||||
new ResourceModel { ResourceID = 1, Name = "Sezionatrice", FixedCost = 12000, VariableCost = 6000, OverHeadCost = 5000, CostDriverID = 1, CostDriverBudget = 220 * 4, LaborCost = 30, OverHeadPerc = 0.15M, EBTPerc = 0.15M },
|
||||
new ResourceModel { ResourceID = 2, Name = "Linea SAOMAD WoodPecker Just 3500", FixedCost = 100000, VariableCost = 30000, OverHeadCost = 15000, CostDriverID = 1, CostDriverBudget = 220 * 8, LaborCost = 40, OverHeadPerc = 0.15M, EBTPerc = 0.15M },
|
||||
new ResourceModel { ResourceID = 3, Name = "Linea Pantografo", FixedCost = 24000, VariableCost = 6000, OverHeadCost = 5000, CostDriverID = 1, CostDriverBudget = 220 * 8, LaborCost = 35, OverHeadPerc = 0.15M, EBTPerc = 0.15M },
|
||||
new ResourceModel { ResourceID = 4, Name = "Stazione Verniciatura", FixedCost = 24000, VariableCost = 6000, OverHeadCost = 3000, CostDriverID = 1, CostDriverBudget = 220 * 4, LaborCost = 30, OverHeadPerc = 0.15M, EBTPerc = 0.15M },
|
||||
new ResourceModel { ResourceID = 5, Name = "Verniciatura Manuale", FixedCost = 6000, VariableCost = 2000, OverHeadCost = 3000, CostDriverID = 1, CostDriverBudget = 220 * 1, LaborCost = 30, OverHeadPerc = 0.15M, EBTPerc = 0.15M },
|
||||
new ResourceModel { ResourceID = 6, Name = "Montaggio Manuale", FixedCost = 500, VariableCost = 500, OverHeadCost = 500, CostDriverID = 1, CostDriverBudget = 220 * 8 * 2, LaborCost = 30, OverHeadPerc = 0.15M, EBTPerc = 0.15M },
|
||||
new ResourceModel { ResourceID = 7, Name = "Installatore", FixedCost = 0, VariableCost = 3000, OverHeadCost = 0, CostDriverID = 1, CostDriverBudget = 220 * 8 * 2, LaborCost = 40, OverHeadPerc = 0.15M, EBTPerc = 0.15M }
|
||||
);
|
||||
|
||||
// inizializzazione fasi
|
||||
@@ -156,57 +220,92 @@ namespace EgwCoreLib.Lux.Data
|
||||
// inizializzazione cicli di lavoro
|
||||
modelBuilder.Entity<JobModel>().HasData(
|
||||
new JobModel { JobID = 1, Description = "Rivendita / servizi" },
|
||||
new JobModel { JobID = 2, Description = "Serramento Completo Legno su linea Saomad e installatore interno" }//,
|
||||
//new JobModel { JobID = 2, Description = "Serramento Completo Legno/Alluminio" },
|
||||
//new JobModel { JobID = 3, Description = "Persiana Legno" },
|
||||
//new JobModel { JobID = 4, Description = "restauro Persiana Esistente" }
|
||||
new JobModel { JobID = 2, Description = "Serramento Completo Legno su linea Saomad e installatore interno" },
|
||||
new JobModel { JobID = 3, Description = "Realizzazione Trave" },
|
||||
new JobModel { JobID = 4, Description = "Realizzazione Cabinet" },
|
||||
new JobModel { JobID = 5, Description = "Realizzazione Parete" }
|
||||
);
|
||||
|
||||
// init righe ciclo (fasi di ciclo)
|
||||
modelBuilder.Entity<JobRowModel>().HasData(
|
||||
modelBuilder.Entity<JobStepModel>().HasData(
|
||||
// per fare 1 finestra singola/semplice taglio 4 tronchetti telaio + 4 tronchetti finestra, considero 1 perché mi arriva dal sistema preventivo/motore
|
||||
new JobRowModel { JobRowID = 1, JobID = 2, Index = 1, PhaseID = 1, Qty = 1, ResourceID = 1 },
|
||||
new JobStepModel { JobStepID = 1, JobID = 2, Index = 1, CostDriverID = 3, PhaseID = 1, ProductivityRate = 1, ResourceID = 1 },
|
||||
// taglio profilo su linea saomad, considero 1 perché mi arriva dal sistema preventivo/motore
|
||||
new JobRowModel { JobRowID = 2, JobID = 2, Index = 2, PhaseID = 2, Qty = 1, ResourceID = 2 },
|
||||
new JobStepModel { JobStepID = 2, JobID = 2, Index = 2, CostDriverID = 2, PhaseID = 2, ProductivityRate = 1, ResourceID = 2 },
|
||||
// verniciatura automatica, considero 1 perché mi arriva dal sistema preventivo/motore
|
||||
new JobRowModel { JobRowID = 3, JobID = 2, Index = 3, PhaseID = 3, Qty = 1, ResourceID = 4 },
|
||||
new JobStepModel { JobStepID = 3, JobID = 2, Index = 3, CostDriverID = 3, PhaseID = 3, ProductivityRate = 1, ResourceID = 4 },
|
||||
// assemblaggio
|
||||
new JobRowModel { JobRowID = 4, JobID = 2, Index = 4, PhaseID = 4, Qty = 1, ResourceID = 6 },
|
||||
new JobStepModel { JobStepID = 4, JobID = 2, Index = 4, CostDriverID = 3, PhaseID = 4, ProductivityRate = 1, ResourceID = 6 },
|
||||
// installazione
|
||||
new JobRowModel { JobRowID = 5, JobID = 2, Index = 5, PhaseID = 6, Qty = 1, ResourceID = 7 }
|
||||
new JobStepModel { JobStepID = 5, JobID = 2, Index = 5, CostDriverID = 3, PhaseID = 6, ProductivityRate = 1, ResourceID = 7 }
|
||||
);
|
||||
|
||||
// init item righe ciclo (articoli + prodotti delle fasi del ciclo)
|
||||
modelBuilder.Entity<JobRowItemModel>().HasData(
|
||||
modelBuilder.Entity<JobStepItemModel>().HasData(
|
||||
// eventuale scarto del materiale tra grezzo e finito--> porta ad un numero >1 (QUI NON USATO, ho il valore calcolato dal motore)
|
||||
new JobRowItemModel { JobRowItemID = 1, JobRowID = 1, Index = 1, ItemID = 1, Qty = 1, Description = "Grezzo legno abete" },
|
||||
new JobStepItemModel { JobStepItemID = 1, JobStepID = 1, Index = 1, ItemID = 1, Qty = 1, Description = "Grezzo legno abete" },
|
||||
// 1/10 litro di vernice per metro lineare prodotto
|
||||
new JobRowItemModel { JobRowItemID = 2, JobRowID = 3, Index = 2, ItemID = 8, Qty = 0.1, Description = "Vernice trasparente standard 1L" },
|
||||
new JobStepItemModel { JobStepItemID = 2, JobStepID = 3, Index = 2, ItemID = 8, Qty = 0.1, Description = "Vernice trasparente standard 1L" },
|
||||
// uso un KIT intero (vs specifico n prodotti singoli) x questo modello; se dal preventivo arrivano n pezzi spcifici, qui li esplodiamo
|
||||
new JobRowItemModel { JobRowItemID = 3, JobRowID = 4, Index = 3, ItemID = 9, Qty = 1, Description = "Ferramenta AGB - rif. AGFD.00000.00000" }
|
||||
new JobStepItemModel { JobStepItemID = 3, JobStepID = 4, Index = 3, ItemID = 9, Qty = 1, Description = "Ferramenta AGB - rif. AGFD.00000.00000" }
|
||||
);
|
||||
|
||||
|
||||
// JWD finestra cVetro Fisso / Cieca
|
||||
string jwdVetroFisso = "{\"ProfilePath\":\"Profilo78\",\"Material\":\"Abete\",\"ColorMaterial\":\"White\",\"Glass\":\"Vetro BE 2S 4/12/4\",\"AreaList\":[{\"Shape\":\"RECTANGLE\",\"DimensionList\":[{\"nIndex\":1,\"sName\":\"Width\",\"dValue\":800.0},{\"nIndex\":2,\"sName\":\"Height\",\"dValue\":1200.0}],\"JointList\":[{\"nIndex\":1,\"JointType\":\"FULL_H\"},{\"nIndex\":2,\"JointType\":\"FULL_H\"},{\"nIndex\":3,\"JointType\":\"FULL_H\"},{\"nIndex\":4,\"JointType\":\"FULL_H\"}],\"BottomRail\":false,\"BottomRailQty\":0,\"IdGroup\":1,\"AreaList\":[{\"FillType\":\"GLASS\",\"IdGroup\":4,\"AreaList\":[],\"AreaType\":\"FILL\"}],\"AreaType\":\"FRAME\"}]}";
|
||||
|
||||
// JWD finestra 1 Anta 800x1200
|
||||
string jwdAntaSingola = "{\"ProfilePath\":\"Profilo78\",\"Material\":\"Abete\",\"ColorMaterial\":\"White\",\"Glass\":\"Vetro BE 2S 4/12/4\",\"AreaList\":[{\"Shape\":\"RECTANGLE\",\"DimensionList\":[{\"nIndex\":1,\"sName\":\"Width\",\"dValue\":800.0},{\"nIndex\":2,\"sName\":\"Height\",\"dValue\":1200.0}],\"JointList\":[{\"nIndex\":1,\"JointType\":\"FULL_H\"},{\"nIndex\":2,\"JointType\":\"FULL_H\"},{\"nIndex\":3,\"JointType\":\"FULL_H\"},{\"nIndex\":4,\"JointType\":\"FULL_H\"}],\"BottomRail\":false,\"BottomRailQty\":0,\"IdGroup\":1,\"AreaList\":[{\"bIsSashVertical\":true,\"SashList\":[{\"nSashId\":1,\"OpeningType\":\"TILTTURN_LEFT\",\"bHasHandle\":true,\"dDimension\":100.0}],\"SashType\":\"NULL\",\"JointList\":[{\"nIndex\":1,\"JointType\":\"FULL_H\"},{\"nIndex\":2,\"JointType\":\"FULL_H\"},{\"nIndex\":3,\"JointType\":\"FULL_H\"},{\"nIndex\":4,\"JointType\":\"FULL_H\"}],\"BottomRail\":false,\"BottomRailQty\":0,\"Hardware\":\"000558\",\"IdGroup\":2,\"AreaList\":[{\"FillType\":\"GLASS\",\"IdGroup\":3,\"AreaList\":[],\"AreaType\":\"FILL\"}],\"AreaType\":\"SASH\"}],\"AreaType\":\"FRAME\"}]}";
|
||||
|
||||
// inizializzazione dei valori di default x SellingItem
|
||||
modelBuilder.Entity<SellingItemModel>().HasData(
|
||||
new SellingItemModel { SellingItemID = 1, IsService = false, Description = "Finestra anta Singola", Cost = 820, Margin = 0.2, JobID = 2 },
|
||||
new SellingItemModel { SellingItemID = 2, IsService = false, Description = "Persiana anta singola", Cost = 150, Margin = 0.1, JobID = 1 },
|
||||
new SellingItemModel { SellingItemID = 3, IsService = true, Description = "Installazione", Cost = 200, Margin = 0.3, JobID = 1 }
|
||||
new SellingItemModel { SellingItemID = 1, IsService = false, Description = "Finestra Anta Singola", Cost = 500, Margin = 0.2, JobID = 2, SerStruct = jwdAntaSingola, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW },
|
||||
new SellingItemModel { SellingItemID = 2, IsService = false, Description = "Finestra Vetro Fisso ", Cost = 300, Margin = 0.2, JobID = 2, SerStruct = jwdVetroFisso, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW },
|
||||
new SellingItemModel { SellingItemID = 3, IsService = false, Description = "Persiana anta singola", Cost = 150, Margin = 0.1, JobID = 1, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW },
|
||||
new SellingItemModel { SellingItemID = 4, IsService = true, Description = "Installazione", Cost = 200, Margin = 0.3, JobID = 1, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW },
|
||||
new SellingItemModel { SellingItemID = 5, IsService = false, Description = "Trave lamellare", Cost = 1000, Margin = 0.3, JobID = 3, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM },
|
||||
new SellingItemModel { SellingItemID = 6, IsService = false, Description = "Cabinet", Cost = 500, Margin = 0.3, JobID = 4, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET },
|
||||
new SellingItemModel { SellingItemID = 7, IsService = false, Description = "Parete", Cost = 2000, Margin = 0.3, JobID = 5, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL }
|
||||
);
|
||||
|
||||
// inizializzazione dei valori di default x Offer
|
||||
modelBuilder.Entity<OfferModel>().HasData(
|
||||
new OfferModel { OfferID = 1, RefYear = 2024, RefNum = 1, RefRev = 1, Description = "Offerta per tre serramenti", CustomerID = 2, DealerID = 2 }
|
||||
//new OfferModel { OfferID = 2, RefYear = 2025, RefNum = 2, RefRev = 1, Description = "Offerta per un serramento + installazione", CustomerID = 1, DealerID = 1 },
|
||||
//new OfferModel { OfferID = 3, RefYear = 2025, RefNum = 3, RefRev = 1, Description = "Offerta per tre serramenti", CustomerID = 2, DealerID = 1 },
|
||||
//new OfferModel { OfferID = 5, RefYear = 2025, RefNum = 4, RefRev = 2, Description = "Offerta per cinque serramenti + installazione", CustomerID = 3, DealerID = 2 }
|
||||
new OfferModel { OfferID = 1, RefYear = 2024, RefNum = 1, RefRev = 1, Description = "Offerta per tre serramenti", CustomerID = 2, DealerID = 2, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW },
|
||||
new OfferModel { OfferID = 2, RefYear = 2024, RefNum = 2, RefRev = 1, Description = "Offerta BEAM", CustomerID = 2, DealerID = 2, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM },
|
||||
new OfferModel { OfferID = 3, RefYear = 2024, RefNum = 3, RefRev = 1, Description = "Offerta Cabinet", CustomerID = 2, DealerID = 2, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET },
|
||||
new OfferModel { OfferID = 4, RefYear = 2024, RefNum = 4, RefRev = 1, Description = "Offerta Wall", CustomerID = 2, DealerID = 2, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL }
|
||||
//new OfferModel { OfferID = 2, RefYear = 2025, RefNum = 2, RefRev = 1, Name = "Offerta per un serramento + installazione", CustomerID = 1, DealerID = 1 },
|
||||
//new OfferModel { OfferID = 3, RefYear = 2025, RefNum = 3, RefRev = 1, Name = "Offerta per tre serramenti", CustomerID = 2, DealerID = 1 },
|
||||
//new OfferModel { OfferID = 5, RefYear = 2025, RefNum = 4, RefRev = 2, Name = "Offerta per cinque serramenti + installazione", CustomerID = 3, DealerID = 2 }
|
||||
);
|
||||
|
||||
// inizializzazione dei valori di default x OfferRow
|
||||
|
||||
// inizializzazione dei valori di default x Offerta 1 = WINDOW
|
||||
modelBuilder.Entity<OfferRowModel>().HasData(
|
||||
new OfferRowModel { OfferRowID = 1, OfferID = 1, OfferRowUID = "OFF0000000001", Inserted = DateTime.Now, Modified = DateTime.Now, Cost = 950, SellingItemID = 1, Qty = 3, RowNum = 1, SerStruct = "{}", Note = "Finestra anta singola 2025", ItemSPP = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 2, OfferID = 1, OfferRowUID = "OFF0000000002", Inserted = DateTime.Now, Modified = DateTime.Now, Cost = 160, SellingItemID = 2, Qty = 3, RowNum = 2, SerStruct = "{}", Note = "Persiana per Finestra anta singola 2025", ItemSPP = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 3, OfferID = 1, OfferRowUID = "OFF0000000003", Inserted = DateTime.Now, Modified = DateTime.Now, Cost = 200, SellingItemID = 3, Qty = 3, RowNum = 3, SerStruct = "{}", Note = "Installazione serramento", ItemSPP = "{}", BomOk = true, ItemOk = true }
|
||||
new OfferRowModel { OfferRowID = 1, OfferID = 1, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, OfferRowUID = $"SOR.{DateTime.Today:yy}.{1:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 900, BomPrice = 950, SellingItemID = 2, Qty = 3, RowNum = 1, SerStruct = jwdVetroFisso, Note = "Finestra Vetro Fisso 2025", ItemSteps = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 2, OfferID = 1, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, OfferRowUID = $"SOR.{DateTime.Today:yy}.{2:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 900, BomPrice = 950, SellingItemID = 1, Qty = 3, RowNum = 1, SerStruct = jwdAntaSingola, Note = "Finestra Anta Singola 2025", ItemSteps = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 3, OfferID = 1, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, OfferRowUID = $"SOR.{DateTime.Today:yy}.{3:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 160, BomPrice = 200, SellingItemID = 2, Qty = 3, RowNum = 2, SerStruct = "{}", Note = "Persiana per Finestra anta singola 2025", ItemSteps = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 4, OfferID = 1, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, OfferRowUID = $"SOR.{DateTime.Today:yy}.{4:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 200, BomPrice = 250, SellingItemID = 3, Qty = 3, RowNum = 3, SerStruct = "{}", Note = "Installazione serramento", ItemSteps = "{}", BomOk = true, ItemOk = true }
|
||||
);
|
||||
|
||||
// inizializzazione dei valori di default x Offerta 2 = BEAM
|
||||
modelBuilder.Entity<OfferRowModel>().HasData(
|
||||
new OfferRowModel { OfferRowID = 5, OfferID = 2, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM, OfferRowUID = $"SOR.{DateTime.Today:yy}.{5:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 800, BomPrice = 1150, SellingItemID = 4, Qty = 10, RowNum = 1, SerStruct = "", Note = "Demo file 01", ItemSteps = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 6, OfferID = 2, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM, OfferRowUID = $"SOR.{DateTime.Today:yy}.{6:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 600, BomPrice = 950, SellingItemID = 4, Qty = 4, RowNum = 1, SerStruct = "", Note = "Demo file 02", ItemSteps = "{}", BomOk = true, ItemOk = true }
|
||||
);
|
||||
|
||||
// inizializzazione dei valori di default x Offerta 3 = CABINET
|
||||
modelBuilder.Entity<OfferRowModel>().HasData(
|
||||
new OfferRowModel { OfferRowID = 7, OfferID = 3, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL, OfferRowUID = $"SOR.{DateTime.Today:yy}.{7:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 200, BomPrice = 250, SellingItemID = 5, Qty = 4, RowNum = 1, SerStruct = "", Note = "Demo file 01", ItemSteps = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 8, OfferID = 3, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WALL, OfferRowUID = $"SOR.{DateTime.Today:yy}.{8:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 50, BomPrice = 80, SellingItemID = 5, Qty = 12, RowNum = 1, SerStruct = "", Note = "Demo file 02", ItemSteps = "{}", BomOk = true, ItemOk = true }
|
||||
);
|
||||
|
||||
// inizializzazione dei valori di default x Offerta 4 = WALL
|
||||
modelBuilder.Entity<OfferRowModel>().HasData(
|
||||
new OfferRowModel { OfferRowID = 9, OfferID = 4, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET, OfferRowUID = $"SOR.{DateTime.Today:yy}.{9:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 800, BomPrice = 1150, SellingItemID = 6, Qty = 6, RowNum = 1, SerStruct = "", Note = "Demo file 01", ItemSteps = "{}", BomOk = true, ItemOk = true },
|
||||
new OfferRowModel { OfferRowID = 10, OfferID = 4, Envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.CABINET, OfferRowUID = $"SOR.{DateTime.Today:yy}.{10:X8}", Inserted = DateTime.Now, Modified = DateTime.Now, BomCost = 600, BomPrice = 950, SellingItemID = 6, Qty = 4, RowNum = 1, SerStruct = "", Note = "Demo file 02", ItemSteps = "{}", BomOk = true, ItemOk = true }
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
@@ -13,58 +13,105 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Classe base per i servizi che fornisce funzionalità comuni come
|
||||
/// - connessione a Redis
|
||||
/// - configurazione
|
||||
/// - gestione dei messaggi
|
||||
/// - strategie di caching.
|
||||
///
|
||||
/// Questa classe agisce come modello per altri servizi derivati.
|
||||
/// </summary>
|
||||
public class BaseServ
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Inizializza una nuova istanza della classe BaseServ.
|
||||
/// Configura la connessione Redis, carica le impostazioni di configurazione e inizializza il serializzatore JSON.
|
||||
/// </summary>
|
||||
/// <param name="Configuration">Oggetto di configurazione per recuperare le impostazioni dell'applicazione.</param>
|
||||
/// <param name="RedisConn">Multiplexer di connessione Redis per operazioni sul database.</param>
|
||||
public BaseServ(IConfiguration Configuration, IConnectionMultiplexer RedisConn)
|
||||
{
|
||||
configuration = Configuration;
|
||||
|
||||
// setup componenti REDIS
|
||||
#if false
|
||||
redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis") ?? "localhost");
|
||||
#endif
|
||||
_config = Configuration;
|
||||
redisConn = RedisConn;
|
||||
redisDb = redisConn.GetDatabase();
|
||||
|
||||
svgChannel = configuration.GetValue<string>("ServerConf:SvgChannel") ?? "svg:img";
|
||||
// aggiungo ricerca generica ":*" al channel...
|
||||
// channel name setup
|
||||
svgChannel = _config.GetValue<string>("ServerConf:SvgChannel") ?? "Egw-svg:img";
|
||||
bomChannel = _config.GetValue<string>("ServerConf:BomChannel") ?? "Egw-bom";
|
||||
updateChannel = _config.GetValue<string>("ServerConf:UpdateChannel") ?? "Egw-update";
|
||||
// Appends ":*" to the channels to enable wildcard subscription for dynamic events
|
||||
if (!svgChannel.EndsWith(":*"))
|
||||
{
|
||||
svgChannel += ":*";
|
||||
}
|
||||
}
|
||||
if (!bomChannel.EndsWith(":*"))
|
||||
{
|
||||
bomChannel += ":*";
|
||||
}
|
||||
if (!updateChannel.EndsWith(":*"))
|
||||
{
|
||||
updateChannel += ":*";
|
||||
}
|
||||
|
||||
// json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/
|
||||
// Configurazione serializzatore JSON per risolvere errore di loop circolare
|
||||
JSSettings = new JsonSerializerSettings()
|
||||
{
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
||||
};
|
||||
// conf message pipe
|
||||
|
||||
// Configurazione pipe dei messaggi
|
||||
CalcDonePipe = new MessagePipe(redisConn, svgChannel);
|
||||
BomPipe = new MessagePipe(RedisConn, bomChannel);
|
||||
UpdatePipe = new MessagePipe(RedisConn, updateChannel);
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
private string svgChannel = "";
|
||||
protected static IConfiguration configuration = null!;
|
||||
protected JsonSerializerSettings? JSSettings;
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Message pipe esecuzione elaborazione EgwCalc >> UI
|
||||
/// Pipe dei messaggi per la comunicazione riguardo update calcolo BOM
|
||||
/// </summary>
|
||||
public MessagePipe BomPipe { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Pipe dei messaggi per la comunicazione tra servizi di calcolo e interfaccia utente.
|
||||
/// I messaggi vengono inviati sul canale Redis definito da svgChannel.
|
||||
/// </summary>
|
||||
public MessagePipe CalcDonePipe { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto per connessione a REDIS
|
||||
/// Pipe dei messaggi per la comunicazione riguardo update generico UI
|
||||
/// </summary>
|
||||
public MessagePipe UpdatePipe { get; set; } = null!;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto di configurazione statico per accedere alle impostazioni dell'applicazione (es. stringhe di connessione).
|
||||
/// Condiviso tra tutte le istanze di BaseServ.
|
||||
/// </summary>
|
||||
protected static IConfiguration _config = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Impostazioni del serializzatore JSON utilizzato per gestire oggetti con riferimenti circolari
|
||||
/// (es. oggetti che si fanno riferimento reciprocamente).
|
||||
/// </summary>
|
||||
protected JsonSerializerSettings? JSSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto per la connessione a Redis utilizzato per operazioni di lettura/scrittura.
|
||||
/// </summary>
|
||||
protected IConnectionMultiplexer redisConn = null!;
|
||||
|
||||
//ISubscriber sub = redis.GetSubscriber();
|
||||
/// <summary>
|
||||
/// Oggetto DB redis da impiegare x chiamate R/W
|
||||
/// Database Redis utilizzato per le operazioni di lettura/scrittura
|
||||
/// nb: ottenuto tramite redisConn.GetDatabase()
|
||||
/// </summary>
|
||||
protected IDatabase redisDb = null!;
|
||||
|
||||
@@ -73,7 +120,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
#region Protected Properties
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache breve (1 min circa + perturbazione percentuale +/-10%)
|
||||
/// Durata della cache breve (circa 1 minuto + variazione del +/-10%)
|
||||
/// </summary>
|
||||
protected TimeSpan FastCache
|
||||
{
|
||||
@@ -81,7 +128,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
|
||||
/// Durata della cache lunga (+ variazione del +/-10%)
|
||||
/// </summary>
|
||||
protected TimeSpan LongCache
|
||||
{
|
||||
@@ -89,7 +136,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache MOLTO breve (10 sec circa + perturbazione percentuale +/-10%)
|
||||
/// Durata della cache molto breve (circa 10 secondi + variazione del +/-10%)
|
||||
/// </summary>
|
||||
protected TimeSpan UltraFastCache
|
||||
{
|
||||
@@ -97,7 +144,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache MOLTO lunga (+ perturbazione percentuale +/-10%)
|
||||
/// Durata della cache molto lunga (+ variazione del +/-10%)
|
||||
/// </summary>
|
||||
protected TimeSpan UltraLongCache
|
||||
{
|
||||
@@ -108,20 +155,46 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
|
||||
#region Private Fields
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto logger utilizzato per registrare eventi e errori a livello di classe.
|
||||
/// Utile per il monitoraggio del comportamento dell'applicazione e la risoluzione di problemi.
|
||||
/// </summary>
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache lunga IN SECONDI
|
||||
/// Redis channel for BOM related info
|
||||
/// </summary>
|
||||
private string bomChannel = "";
|
||||
|
||||
/// <summary>
|
||||
/// Durata della cache lunga in secondi (predefinito: 5 minuti)
|
||||
/// Utilizzato nella proprietà LongCache per definire quanto a lungo i dati devono essere memorizzati in cache.
|
||||
/// </summary>
|
||||
private int cacheTtlLong = 60 * 5;
|
||||
|
||||
/// <summary>
|
||||
/// Durata cache breve IN SECONDI
|
||||
/// Durata della cache breve in secondi (predefinito: 1 minuto)
|
||||
/// Utilizzato nelle proprietà FastCache e UltraFastCache per definire la durata della cache breve.
|
||||
/// </summary>
|
||||
private int cacheTtlShort = 60 * 1;
|
||||
|
||||
/// <summary>
|
||||
/// Generatore di numeri casuali utilizzato per introdurre variabilità dinamica nelle durate della cache
|
||||
/// (simula variazioni reali nella freschezza dei dati e nei tempi di scadenza).
|
||||
/// </summary>
|
||||
private Random rnd = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Nome del canale Redis utilizzato per l'invio/ricezione di messaggi relativi a img svg.
|
||||
/// Predefinito a "svg:img" con suffisso ":*".
|
||||
/// </summary>
|
||||
private string svgChannel = "";
|
||||
|
||||
/// <summary>
|
||||
/// Nome del canale Redis utilizzato per l'invio/ricezione di messaggi di update
|
||||
/// </summary>
|
||||
private string updateChannel = "";
|
||||
|
||||
#endregion Private Fields
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Services
|
||||
{
|
||||
public class CalcRequestService
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public CalcRequestService(IConfiguration config, IRedisService redisService)
|
||||
{
|
||||
_config = config;
|
||||
_redisService = redisService;
|
||||
bomChannel = _config.GetValue<string>("ServerConf:BomChannel") ?? "bom";
|
||||
// verifico la url base
|
||||
apiUrl = _config.GetValue<string>("ServerConf:Prog.ApiUrl") ?? "https://iis01.egalware.com/lux/srv/api";
|
||||
routeBasePath = _config.GetValue<string>("ServerConf:RouteBaseUrl") ?? "window";
|
||||
// fix opzioni base del RestClient
|
||||
restOptStd = new RestClientOptions
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(60),
|
||||
BaseUrl = new Uri($"{apiUrl}/{routeBasePath}")
|
||||
};
|
||||
Log.Info("ImageCache Service Started");
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Effettua una generica chiamata ApiRest
|
||||
/// </summary>
|
||||
/// <param name="ApiUrl">URL Api di base</param>
|
||||
/// <param name="ApiRequest">Richiesta completa</param>
|
||||
/// <param name="rawBody">Corpo Json trasmesso con richiesta</param>
|
||||
/// <returns></returns>
|
||||
public async Task<RestResponse> CallRestPost(string ApiUrl, string ApiRequest, object rawBody)
|
||||
{
|
||||
RestResponse response;
|
||||
// cerco online
|
||||
using (RestClient client = new RestClient(ApiUrl))
|
||||
{
|
||||
var request = new RestRequest(ApiRequest, Method.Post);
|
||||
string rawData = JsonConvert.SerializeObject(rawBody);
|
||||
request.AddJsonBody(rawData);
|
||||
response = await client.ExecutePostAsync(request);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private readonly IRedisService _redisService;
|
||||
private readonly string apiUrl = "";
|
||||
private readonly string bomChannel = "bomdev";
|
||||
private readonly string routeBasePath = "";
|
||||
private IConfiguration _config;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Conf client RestSharp standard:
|
||||
/// - base URI al sito
|
||||
/// - timeout 1 min
|
||||
/// </summary>
|
||||
private RestClientOptions restOptStd { get; set; } = new RestClientOptions();
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using EgwCoreLib.Lux.Core.RestPayload;
|
||||
using EgwCoreLib.Lux.Data.Controllers;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwMultiEngineManager.Data;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Services
|
||||
{
|
||||
public class ConfigDataService : BaseServ
|
||||
{
|
||||
|
||||
public ConfigDataService(IConfiguration configuration, IConnectionMultiplexer RedisConn) : base(configuration, RedisConn)
|
||||
{
|
||||
// init implicito
|
||||
Log.Info($"ConfigDataService | Init OK");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// restituisce l'elenco dell'HW valido in memoria
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<HardwareModel> ElencoHw(Constants.EXECENVIRONMENTS execEnvironment, string HwReq = "HW.AGB")
|
||||
{
|
||||
List<HardwareModel> result = new List<HardwareModel>();
|
||||
// leggo obj da redis cache
|
||||
var currKey = $"{redisBaseKey}:{execEnvironment}:HML:{HwReq}";
|
||||
RedisValue rawData = redisDb.StringGet(currKey);
|
||||
// prendo solo i valori validi (Description <> FamilyName)
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
var currList = JsonConvert.DeserializeObject<List<HardwareModel>>($"{rawData}");
|
||||
result = currList ?? new List<HardwareModel>();
|
||||
//var currList = JsonConvert.DeserializeObject<HwListDTO>($"{rawData}");
|
||||
//if (currList != null && currList.ListItem != null)
|
||||
//{
|
||||
// result = currList.ListItem;
|
||||
//}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private string redisBaseKey = "Lux";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using EgwCoreLib.Lux.Core.RestPayload;
|
||||
using EgwCoreLib.Lux.Data.Controllers;
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwMultiEngineManager.Data;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
@@ -15,6 +16,8 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static EgwCoreLib.Lux.Core.Enums;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Services
|
||||
{
|
||||
@@ -25,15 +28,15 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
public DataLayerServices(IConfiguration configuration, IConnectionMultiplexer RedisConn) : base(configuration, RedisConn)
|
||||
{
|
||||
// conf DB
|
||||
string connStr = BaseServ.configuration.GetConnectionString("Lux.All") ?? "";
|
||||
string connStr = BaseServ._config.GetConnectionString("Lux.All") ?? "";
|
||||
if (string.IsNullOrEmpty(connStr))
|
||||
{
|
||||
Log.Error("ConnString empty!");
|
||||
}
|
||||
else
|
||||
{
|
||||
//dbController = new Controllers.LuxController(_config);
|
||||
dbController = new LuxController();
|
||||
//dbController = new Controllers.LuxController(configuration);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine($"DataLayerServices | LuxController OK");
|
||||
Log.Info(sb.ToString());
|
||||
@@ -42,14 +45,216 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public static LuxController dbController { get; set; } = null!;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Config Envir
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<EnvirParamModel>> ConfEnvirParamGetAllAsync()
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<EnvirParamModel>? result = new List<EnvirParamModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:ConfEnvir";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<EnvirParamModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.ConfEnvirParamGetAllAsync();
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<EnvirParamModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"ConfEnvirParamGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue eliminazione + refresh cache
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ConfGlassDeleteAsync(GlassModel selRec)
|
||||
{
|
||||
bool result = await dbController.ConfGlassDeleteAsync(selRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ConfGlass");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Config Glass
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<GlassModel>> ConfGlassGetAllAsync()
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<GlassModel>? result = new List<GlassModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:ConfGlass";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<GlassModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.ConfGlassGetAllAsync();
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<GlassModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"ConfGlassGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue Upsert del record ricevuto
|
||||
/// </summary>
|
||||
/// <param name="upsRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ConfGlassUpsertAsync(GlassModel upsRec)
|
||||
{
|
||||
bool result = await dbController.ConfGlassUpsertAsync(upsRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ConfGlass");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue eliminazione + refresh cache
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ConfProfileDeleteAsync(ProfileModel selRec)
|
||||
{
|
||||
bool result = await dbController.ConfProfileDeleteAsync(selRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ConfProfile");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Config Profile
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<ProfileModel>> ConfProfileGetAllAsync()
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<ProfileModel>? result = new List<ProfileModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:ConfProfile";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<ProfileModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.ConfProfileGetAllAsync();
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<ProfileModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"ConfProfileGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue Upsert del record ricevuto
|
||||
/// </summary>
|
||||
/// <param name="upsRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ConfProfileUpsertAsync(ProfileModel upsRec)
|
||||
{
|
||||
bool result = await dbController.ConfProfileUpsertAsync(upsRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ConfProfile");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue eliminazione + refresh cache
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ConfWoodDeleteAsync(WoodModel selRec)
|
||||
{
|
||||
bool result = await dbController.ConfWoodDeleteAsync(selRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ConfWood");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Config Wood
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<WoodModel>> ConfWoodGetAllAsync()
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<WoodModel>? result = new List<WoodModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:ConfWood";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<WoodModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.ConfWoodGetAllAsync();
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<WoodModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"ConfWoodGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue Upsert del record ricevuto
|
||||
/// </summary>
|
||||
/// <param name="upsRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ConfWoodUpsertAsync(WoodModel upsRec)
|
||||
{
|
||||
bool result = await dbController.ConfWoodUpsertAsync(upsRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ConfWood");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Customers
|
||||
/// </summary>
|
||||
@@ -73,7 +278,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
result = dbController.CustomersGetAll();
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(result);
|
||||
redisDb.StringSet(currKey, rawData, LongCache);
|
||||
redisDb.StringSet(currKey, rawData, UltraLongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
@@ -148,6 +353,171 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset cache sistema x Offerte modalità async
|
||||
/// </summary>
|
||||
public async Task<bool> FlushCacheOffersAsync()
|
||||
{
|
||||
bool answ = false;
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"FlushCacheOffersAsync in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset cache sistema x Ordini modalità async
|
||||
/// </summary>
|
||||
public async Task<bool> FlushCacheOrdersAsync()
|
||||
{
|
||||
bool answ = false;
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Orders:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"FlushCacheOrdersAsync in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue eliminazione + refresh cache
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> GenClassDeleteAsync(GenClassModel selRec)
|
||||
{
|
||||
bool result = await dbController.GenClassDeleteAsync(selRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenClass");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenVal:*");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo GenClass
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<GenClassModel>> GenClassGetAllAsync()
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<GenClassModel>? result = new List<GenClassModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:GenClass";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<GenClassModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.GenClassGetAllAsync();
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, LongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<GenClassModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"GenClassGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue Upsert del record ricevuto
|
||||
/// </summary>
|
||||
/// <param name="upsRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> GenClassUpsertAsync(GenClassModel upsRec)
|
||||
{
|
||||
bool result = await dbController.GenClassUpsertAsync(upsRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenClass");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenVal:*");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue eliminazione + refresh cache
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> GenValDeleteAsync(GenValueModel selRec)
|
||||
{
|
||||
bool result = await dbController.GenValDeleteAsync(selRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenClass");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenVal:*");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco valori x classe richiesta
|
||||
/// </summary>
|
||||
/// <param name="codClass"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<GenValueModel>> GenValGetFiltAsync(string codClass)
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<GenValueModel>? result = new List<GenValueModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:GenVal:{codClass}";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<GenValueModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.GenValGetFiltAsync(codClass);
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, LongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<GenValueModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"GenValGetFiltAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue spostamento nell'ordinamento relativo alla classe + refresh cache
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
/// <param name="moveUp"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> GenValMoveAsync(GenValueModel selRec, bool moveUp)
|
||||
{
|
||||
bool result = await dbController.GenValMoveAsync(selRec, moveUp);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenClass");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenVal:*");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue Upsert del record ricevuto
|
||||
/// </summary>
|
||||
/// <param name="upsRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> GenValUpsertAsync(GenValueModel upsRec)
|
||||
{
|
||||
bool result = await dbController.GenValUpsertAsync(upsRec);
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenClass");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:GenVal:*");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eliminazione record item
|
||||
/// </summary>
|
||||
@@ -197,43 +567,6 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return result;
|
||||
}
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Elenco item Child da ParentId (per sostituzione) async
|
||||
/// </summary>
|
||||
/// <param name="ItemId">ID corrente di cui cercare parent + fratelli</param>
|
||||
/// <returns></returns>
|
||||
public List<ItemModel> ItemGetChild(int ItemId)
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<ItemModel>? result = new List<ItemModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:Item:ListChild:{ItemId}";
|
||||
RedisValue rawData = redisDb.StringGet(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<ItemModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = dbController.ItemGetChild(ItemId);
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
redisDb.StringSet(currKey, rawData, FastCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<ItemModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"ItemGetChild | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Elenco item da ricerca completa Async
|
||||
/// </summary>
|
||||
@@ -442,7 +775,27 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe dell'offerta indicata
|
||||
/// Effettua fix UID righe child dell'offerta indicata e restituisce elenco UID da chiamare x refresh
|
||||
/// </summary>
|
||||
/// <param name="updRec">Key</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<string>> OffertRowFixUid(int OffertID)
|
||||
{
|
||||
List<string> answ = new List<string>();
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// calcolo
|
||||
answ = dbController.OffertRowFixUid(OffertID);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertRowFixUid in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update della BOM (e dei costi) di tutte le righe dell'offerta indicata
|
||||
/// </summary>
|
||||
/// <param name="OfferRowID">ID riga offerta da aggiornare</param>
|
||||
/// <param name="newBomList">Bom aggiornata da salvare</param>
|
||||
@@ -461,6 +814,111 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update delle info legate al file per la riga offerta
|
||||
/// </summary>
|
||||
/// <param name="updRec">IRiga offerta coin dati FILE da aggiornare</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertRowUpdateFileData(OfferRowModel updRec)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertRowUpdateFileData(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertRowUpdateFileData in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update del valore serializzato della riga offerta
|
||||
/// </summary>
|
||||
/// <param name="OfferRowID">ID riga offerta da aggiornare</param>
|
||||
/// <param name="serStruct">Serializzazione oggetto (es JWD)</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertRowUpdateSerStruct(int OfferRowID, string serStruct)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertRowUpdateSerStruct(OfferRowID, serStruct);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertRowUpdateSerStruct in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Effettua eliminazione della riga offerta
|
||||
/// </summary>
|
||||
/// <param name="updRec">IRiga offerta coin dati FILE da aggiornare</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertRowDelete(OfferRowModel updRec)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertRowDelete(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertRowDelete in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua Upsert della riga offerta
|
||||
/// </summary>
|
||||
/// <param name="updRec">IRiga offerta coin dati FILE da aggiornare</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertRowUpsert(OfferRowModel updRec)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertRowUpsert(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertRowUpsert in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update stato await BOM/PRICE per l'offerta indicata
|
||||
/// </summary>
|
||||
/// <param name="offerRowID">ID singola riga offerta</param>
|
||||
/// <param name="awaitBom">Se non nullo è il nuovo stato await BOM</param>
|
||||
/// <param name="awaitPrice">Se non nullo è stato await Price</param>
|
||||
/// <param name="flushCache">Indica se svuotare la cache</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertUpdateAwaitState(int offerRowID, bool? awaitBom, bool? awaitPrice, bool flushCache = false)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// aggiorno
|
||||
bool fatto = await dbController.OffertUpdateAwaitState(offerRowID, awaitBom, awaitPrice);
|
||||
if (flushCache)
|
||||
{
|
||||
// svuoto cache...
|
||||
#if false
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
#endif
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertUpdateAwaitState in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe dell'offerta indicata
|
||||
/// </summary>
|
||||
@@ -480,6 +938,25 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua Upsert complessivo record offerta
|
||||
/// </summary>
|
||||
/// <param name="updRec">Key</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertUpsert(OfferModel updRec)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertUpsert(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
sw.Stop();
|
||||
Log.Debug($"OffertUpsert in {sw.Elapsed.TotalMilliseconds} ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue salvataggio BOM sul DB
|
||||
/// </summary>
|
||||
@@ -498,7 +975,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(bomContent);
|
||||
if (bomList != null)
|
||||
{
|
||||
// verifico 1:1 gli item ricevuti dalla BOM sul DB con eventuale insert in anagrafica
|
||||
// verifico 1:1 gli item ricevuti dalla BOM sul DB con eventuale insert in anagrafica dei nuovi
|
||||
dbController.ItemUpsertFromBom(bomList);
|
||||
// salvo la BOM nel record del DB relativo all'oggetto richiesto
|
||||
dbController.OfferUpsertFromBom(uID, bomList);
|
||||
@@ -732,5 +1209,48 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
private string redisBaseKey = "Lux:Cache";
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private static LuxController dbController { get; set; } = null!;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Elenco item Child da ParentId (per sostituzione) async
|
||||
/// </summary>
|
||||
/// <param name="ItemId">ID corrente di cui cercare parent + fratelli</param>
|
||||
/// <returns></returns>
|
||||
public List<ItemModel> ItemGetChild(int ItemId)
|
||||
{
|
||||
string source = "DB";
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
List<ItemModel>? result = new List<ItemModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:Item:ListChild:{ItemId}";
|
||||
RedisValue rawData = redisDb.StringGet(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<ItemModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = dbController.ItemGetChild(ItemId);
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
redisDb.StringSet(currKey, rawData, FastCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<ItemModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"ItemGetChild | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,6 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
/// </summary>
|
||||
public interface IRedisService
|
||||
{
|
||||
#if false
|
||||
IDatabase GetDatabase();
|
||||
void Publish(string channel, string message);
|
||||
#endif
|
||||
|
||||
long Publish(string channel, string message);
|
||||
Task<long> PublishAsync(string channel, string message);
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
liveTag = _config.GetValue<string>("ServerConf:ImageLiveTag") ?? "svg";
|
||||
cacheTag = _config.GetValue<string>("ServerConf:ImageFileTag") ?? "svgfile";
|
||||
calcTag = _config.GetValue<string>("ServerConf:ImageCalcTag") ?? "svg-preview";
|
||||
bomChannel = _config.GetValue<string>("ServerConf:BomChannel") ?? "Egw-bom";
|
||||
updateChannel = _config.GetValue<string>("ServerConf:UpdateChannel") ?? "Egw-update";
|
||||
// verifico la url base
|
||||
apiUrl = _config.GetValue<string>("ServerConf:Prog.ApiUrl") ?? "https://iis01.egalware.com/lux/srv/api";
|
||||
imgBasePath = _config.GetValue<string>("ServerConf:ImageBaseUrl") ?? "window";
|
||||
@@ -114,11 +116,12 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
public string ImageUrl(string baseUrl, bool isLive, string imgUID, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW)
|
||||
{
|
||||
string tag = isLive ? liveTag : cacheTag;
|
||||
if (!imgUID.EndsWith(".svg"))
|
||||
if (imgUID.EndsWith(".svg"))
|
||||
{
|
||||
imgUID += ".svg";
|
||||
imgUID.Replace(".svg","");
|
||||
}
|
||||
string fullUrl = $"{baseUrl}/{tag}/{imgUID}?envir={envir}".Replace("////", "//");
|
||||
string rndImg = $"{DateTime.Now:HHmmssfff}";
|
||||
string fullUrl = $"{baseUrl}/{tag}/{imgUID}-{rndImg}.svg?envir={envir}".Replace("////", "//");
|
||||
return fullUrl;
|
||||
}
|
||||
|
||||
@@ -168,13 +171,14 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salva e invia su channel img redis SVG per il doc richiesto
|
||||
/// Salva e invia su channel BOM redis il doc richiesto
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="env"></param>
|
||||
/// <param name="bomContent"></param>
|
||||
public async Task<bool> SaveBomAsync(string uid, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS env, string bomContent)
|
||||
public async Task<bool> SaveBomAsync(string uid, Constants.EXECENVIRONMENTS env, string bomContent)
|
||||
{
|
||||
// salvo img in cache
|
||||
// salvo in cache
|
||||
string currKey = $"{redisBaseKey}:{env}:BOM:{uid.Replace("/", ":")}";
|
||||
var done = await _redisService.SetAsync(currKey, bomContent);
|
||||
// invio notifica nuova svg generata sul canale... viene inviato solo svg con ID nel canale
|
||||
@@ -183,12 +187,29 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return done;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salva e invia su channel richiesto un update x UID
|
||||
/// è attesao un refresh per chi sottoscrive il canale
|
||||
/// </summary>
|
||||
/// <param name="env"></param>
|
||||
/// <param name="uid"></param>
|
||||
public async Task<bool> PublishUpdateAsync(string uid, Constants.EXECENVIRONMENTS env)
|
||||
{
|
||||
bool done = false;
|
||||
// invio notifica sul canale di update generale...
|
||||
string notifyChannel = $"{updateChannel}:{env}";
|
||||
// contenuto è UID
|
||||
long numSent = await _redisService.PublishAsync(notifyChannel, $"{uid}");
|
||||
done = numSent > 0;
|
||||
return done;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salva e invia su channel img redis SVG per il doc richiesto
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="rawData"></param>
|
||||
public async Task<bool> SaveHmlAsync(string uid, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS env, string rawData)
|
||||
public async Task<bool> SaveHmlAsync(string uid, Constants.EXECENVIRONMENTS env, string rawData)
|
||||
{
|
||||
// salvo img in cache
|
||||
string currKey = $"{redisBaseKey}:{env}:HML:{uid.Replace("/", ":")}";
|
||||
@@ -244,6 +265,7 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
private readonly string apiUrl = "";
|
||||
|
||||
private readonly string bomChannel = "bom:item";
|
||||
private readonly string updateChannel = "ui:update";
|
||||
private readonly string cacheTag = "svgfile";
|
||||
private readonly string calcTag = "svgpreview";
|
||||
private readonly string hmlChannel = "hml:item";
|
||||
|
||||
@@ -7,6 +7,13 @@ Lbreria salvata come nuget SDK per accesso dati per EgalWare's LUX
|
||||
Necessaria rpesenza configurazione DB/Redis in appsettings.json:
|
||||
|
||||
esempio dev ufficio:
|
||||
```json
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=mdb.ufficio;port=3306;database=Lux_000_dev_;uid=db_user;pwd=secure_password;sslmode=None;",
|
||||
"Redis": "redis.ufficio:26379, serviceName=devel, DefaultDatabase=6, keepAlive=180, connectTimeout=15000, syncTimeout=15000, asyncTimeout=15000, abortConnect=false, ssl=false, allowAdmin=true"
|
||||
},
|
||||
```
|
||||
esempio prod ufficio:
|
||||
```json
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=mdb.ufficio;port=3306;database=Lux_000;uid=db_user;pwd=secure_password;sslmode=None;",
|
||||
|
||||
@@ -36,13 +36,7 @@ namespace Lux.API.Controllers
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
string svgContent = "";
|
||||
|
||||
// se contiene ".svg" lo levo...
|
||||
if (id.EndsWith(".svg"))
|
||||
{
|
||||
id = id.Replace(".svg", "");
|
||||
}
|
||||
string retVal = "";
|
||||
|
||||
// ...se ricevo percorso --> leggo jwd/svg cablato
|
||||
if (currReq != null)
|
||||
@@ -62,11 +56,48 @@ namespace Lux.API.Controllers
|
||||
QuestionDTO currArgs = new QuestionDTO(nId, currReq.EnvType, DictExec);
|
||||
|
||||
await _redisService.PublishAsync(pubChannel, currArgs.sProcessArgs);
|
||||
svgContent = "DONE";
|
||||
retVal = "DONE";
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Info($"calcSvg | {sw.Elapsed.TotalMilliseconds:N3} ms");
|
||||
return Ok(svgContent);
|
||||
return Ok(retVal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chiamata POST: riceve Json in formato JWD serializzato, invia richiesta calcolo modo 2 (BOM)
|
||||
/// PUT: api/window/bom/00000000-0000-0000-0000-000000000000
|
||||
/// </summary>
|
||||
/// <param name="id">id oggetto</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("bom/{id}")]
|
||||
public async Task<ActionResult<string>> getBom(string id, [FromBody] string currSer)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
string retVal = "";
|
||||
|
||||
// se messaggio vuoto --> uso default!
|
||||
currSer = string.IsNullOrEmpty(currSer) ? "" : currSer;
|
||||
|
||||
// ...se ricevo percorso --> leggo jwd/svg cablato
|
||||
if (!string.IsNullOrEmpty(currSer))
|
||||
{
|
||||
Dictionary<string, string> DictExec = new Dictionary<string, string>();
|
||||
// cablata la BOM
|
||||
DictExec.Add("Mode", "2");
|
||||
// UID cablato x ora...
|
||||
DictExec.Add("UID", id);
|
||||
DictExec.Add("Jwd", currSer);
|
||||
int nId = 1;
|
||||
// da modificare con tipo richiesta...
|
||||
QuestionDTO currArgs = new QuestionDTO(nId, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, DictExec);
|
||||
|
||||
await _redisService.PublishAsync(pubChannel, currArgs.sProcessArgs);
|
||||
retVal = "DONE";
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Info($"getBom | {sw.Elapsed.TotalMilliseconds:N3} ms");
|
||||
return Ok(retVal);
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EgwCoreLib.Lux.Core;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using EgwMultiEngineManager.Data;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -13,11 +14,12 @@ namespace Lux.API.Controllers
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public WindowController(IConfiguration config, IRedisService redisService, ImageCacheService imgServ)
|
||||
public WindowController(IConfiguration config, IRedisService redisService, ImageCacheService imgServ, ConfigDataService confServ)
|
||||
{
|
||||
_config = config;
|
||||
_redisService = redisService;
|
||||
_imgService = imgServ;
|
||||
_confService = confServ;
|
||||
pubChannel = _config.GetValue<string>("ServerConf:PubChannel") ?? "";
|
||||
}
|
||||
|
||||
@@ -75,7 +77,7 @@ namespace Lux.API.Controllers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chiamata GET: riceve Json in formato serializzato, invia richiesta modo 3 (HardwareModelList)
|
||||
/// Chiamata GET: invia richiesta modo 3 (HardwareModelList) che sarà poi salvata
|
||||
/// GET: api/window/hwlist
|
||||
/// </summary>
|
||||
/// <param name="id">id oggetto</param>
|
||||
@@ -86,6 +88,19 @@ namespace Lux.API.Controllers
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
string hwContent = "";
|
||||
await sendHwReq();
|
||||
hwContent = "DONE";
|
||||
sw.Stop();
|
||||
Log.Info($"getHardwareList | {sw.Elapsed.TotalMilliseconds:N3} ms");
|
||||
return Ok(hwContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue invio effettivo richiesta elenco HW list
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task sendHwReq()
|
||||
{
|
||||
Dictionary<string, string> DictExec = new Dictionary<string, string>();
|
||||
DictExec.Add("Mode", $"{(int)Enums.EngineQueryType.HardwareModelList}");
|
||||
// da rivedere?
|
||||
@@ -96,10 +111,38 @@ namespace Lux.API.Controllers
|
||||
// da modificare con tipo richiesta...
|
||||
QuestionDTO currArgs = new QuestionDTO(nId, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, DictExec);
|
||||
await _redisService.PublishAsync(pubChannel, currArgs.sProcessArgs);
|
||||
hwContent = "DONE";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chiamata GET:
|
||||
/// - se trova in cache risponde con elenco hw già ricevuto
|
||||
/// - se non trova invia richiesta modo 3 (HardwareModelList) che sarà poi salvata
|
||||
/// GET: api/window/hwlist/nome_produttore
|
||||
/// </summary>
|
||||
/// <param name="id">nome del produttore, es HW.AGB (default)</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("hwlist/{id}")]
|
||||
public async Task<ActionResult<List<HardwareModel>>> getHardwareList(string id)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
string hwReq = id ?? "HW.AGB";
|
||||
var answ = _confService.ElencoHw(EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, hwReq);
|
||||
if (answ == null || answ.Count == 0)
|
||||
{
|
||||
await sendHwReq();
|
||||
answ = new List<HardwareModel>();
|
||||
}
|
||||
// filtro quelli default/non significativi (famili=descript)
|
||||
else
|
||||
{
|
||||
answ = answ
|
||||
.Where(x => !x.FamilyName.Equals(x.Description, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Info($"getHardwareList | {sw.Elapsed.TotalMilliseconds:N3} ms");
|
||||
return Ok(hwContent);
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -224,6 +267,7 @@ namespace Lux.API.Controllers
|
||||
#region Private Properties
|
||||
|
||||
private ImageCacheService _imgService { get; set; }
|
||||
private ConfigDataService _confService { get; set; }
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>0.9.2509.1807</Version>
|
||||
<Version>0.9.2510.2012</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -65,8 +65,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Egw.Lux.WebWindow.Base" Version="2.7.9-beta.1313" />
|
||||
<PackageReference Include="EgwMultiEngineManager.Data" Version="2.7.9-beta.1" />
|
||||
<PackageReference Include="NLog" Version="6.0.1" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="6.0.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
|
||||
@@ -48,6 +48,7 @@ builder.Services.AddSingleton<ImageCacheService>();
|
||||
builder.Services.AddSingleton<DataLayerServices>();
|
||||
builder.Services.AddSingleton<ExternalMessageProcessor>();
|
||||
builder.Services.AddHostedService<RedisSubscriberService>();
|
||||
builder.Services.AddSingleton<ConfigDataService>();
|
||||
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -59,6 +59,9 @@ namespace Lux.API.Services
|
||||
await cacheService.SaveBomAsync(UID, retData.ExecEnvironment, newBom);
|
||||
// salvo la BOM completa con i dati recuperati dal DB
|
||||
await dbService.SaveBomAsync(UID, retData.ExecEnvironment, newBom);
|
||||
|
||||
// pubblico refresh info così da segnalare richeista di update conseguente
|
||||
await cacheService.PublishUpdateAsync(UID, retData.ExecEnvironment);
|
||||
}
|
||||
if (retData.Args.ContainsKey("HardwareModelList"))
|
||||
{
|
||||
@@ -90,9 +93,9 @@ namespace Lux.API.Services
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private readonly ImageCacheService cacheService;
|
||||
private readonly DataLayerServices dbService;
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
},
|
||||
"ServerConf": {
|
||||
"BaseUrl": "/lux/srv/",
|
||||
"PubChannel": "EgwEngineInput",
|
||||
"SubChannel": "EgwEngineOutput"
|
||||
"PubChannel": "EgwDevEngineInput",
|
||||
"SubChannel": "EgwDevEngineOutput",
|
||||
"ImageBaseUrl": "https://iis01.egalware.com/lux/srv/api/window/"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"ServerConf": {
|
||||
"BaseUrl": "/lux/srv/",
|
||||
"PubChannel": "EgwEngineInput",
|
||||
"SubChannel": "EgwEngineOutput"
|
||||
"SubChannel": "EgwEngineOutput",
|
||||
"ImageBaseUrl": "https://office.egalware.com/lux/srv/api/window/"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
},
|
||||
"ServerConf": {
|
||||
"BaseUrl": "/lux/srv/",
|
||||
//"PubChannel": "EgwEngineInput",
|
||||
//"SubChannel": "EgwEngineOutput",
|
||||
"PubChannel": "EgwDevEngineInput",
|
||||
"SubChannel": "EgwDevEngineOutput"
|
||||
"PubChannel": "EgwEngineInput",
|
||||
"SubChannel": "EgwEngineOutput"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,15 +50,17 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
//"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50;Trusted_Connection=True;MultipleActiveResultSets=true",
|
||||
"DefaultConnection": "Server=mdb.ufficio;port=3306;database=Lux_000;uid=lux_user;pwd=Egal_pwd!;sslmode=None;",
|
||||
"Lux.All": "Server=SQL2016DEV;Database=MoonPro_STATS; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.Land;",
|
||||
"Redis": "redis.ufficio:26379, serviceName=devel, DefaultDatabase=6, keepAlive=180, connectTimeout=15000, syncTimeout=15000, asyncTimeout=15000, abortConnect=false, ssl=false, allowAdmin=true"
|
||||
},
|
||||
"ServerConf": {
|
||||
"CalcTag": "calc",
|
||||
"PubChannel": "EgwEngineInput",
|
||||
"SubChannel": "EgwEngineOutput",
|
||||
"SvgChannel": "svg:img",
|
||||
"SvgChannel": "Egw:svg:img",
|
||||
"BomChannel": "Egw:bom",
|
||||
"UpdateChannel": "Egw:update",
|
||||
"BaseUrl": "/lux/srv/",
|
||||
"ImageBaseUrl": "https://iis01.egalware.com/lux/srv/api/window/",
|
||||
"ImageLiveTag": "svg",
|
||||
|
||||
@@ -7,8 +7,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EgwCoreLib.Lux.Core", "EgwC
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EgwCoreLib.Lux.Data", "EgwCoreLib.Lux.Data\EgwCoreLib.Lux.Data.csproj", "{9BA9FBAC-0D76-41CA-9970-A8DB982CC5F0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{E94496AD-22BB-4443-9A81-11D19AFBE0A3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lux.UI", "Lux.UI\Lux.UI.csproj", "{A3B8FAE0-3BAD-4402-B4D9-26DD9CB777E5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lux.UI.Client", "Lux.UI.Client\Lux.UI.Client.csproj", "{ECA4B6A4-692B-41EB-8238-C33C5FB71942}"
|
||||
@@ -29,10 +27,6 @@ Global
|
||||
{9BA9FBAC-0D76-41CA-9970-A8DB982CC5F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9BA9FBAC-0D76-41CA-9970-A8DB982CC5F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9BA9FBAC-0D76-41CA-9970-A8DB982CC5F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E94496AD-22BB-4443-9A81-11D19AFBE0A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E94496AD-22BB-4443-9A81-11D19AFBE0A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E94496AD-22BB-4443-9A81-11D19AFBE0A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E94496AD-22BB-4443-9A81-11D19AFBE0A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A3B8FAE0-3BAD-4402-B4D9-26DD9CB777E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A3B8FAE0-3BAD-4402-B4D9-26DD9CB777E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A3B8FAE0-3BAD-4402-B4D9-26DD9CB777E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Egw.Lux.WebWindow.Base" Version="2.7.9-beta.1313" />
|
||||
<PackageReference Include="Egw.Lux.WebWindowComplex" Version="2.7.10.1710" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.17" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.17" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<h5>Conf. Vetro</h5>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<div class="px-0 d-flex justify-content-between">
|
||||
<div class="px-1">
|
||||
<div class="input-group input-group-sm" title="ricerca">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" @bind="@SearchVal">
|
||||
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-1">
|
||||
@if (isLoading || ListRecords == null)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else if (totalCount == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center display-6">Nessun record trovato</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-nowrap text-center">
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoReset"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
</th>
|
||||
@* <th>ID</th> *@
|
||||
<th class="text-nowrap">Cod.</th>
|
||||
<th class="w-100">Descrizione</th>
|
||||
<th class="text-nowrap text-end">Size mm</th>
|
||||
<th class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-success" @onclick="DoAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
<tr>
|
||||
<td class="text-center">@item.GlassID</td>
|
||||
<td class="">@item.Code</td>
|
||||
<td class="w-100">@item.Description</td>
|
||||
<td class="text-end">@($"{item.Thickness:N2}")</td>
|
||||
<td class="text-nowrap text-end">
|
||||
@if (false)
|
||||
{
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-sm btn-secondary" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@if (totalCount >= numRecord)
|
||||
{
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="15">
|
||||
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,199 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
|
||||
namespace Lux.UI.Components.Compo.Config
|
||||
{
|
||||
public partial class GlassMan
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
if (searchVal != value)
|
||||
{
|
||||
searchVal = value;
|
||||
_ = FullUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// impossta record x eliminazione
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
protected async Task DoDelete(GlassModel selRec)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.GlassID} | {selRec.Description} | {selRec.Thickness}"))
|
||||
return;
|
||||
|
||||
// esegue eliminazione del record...
|
||||
await DLService.ConfGlassDeleteAsync(selRec);
|
||||
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edit articolo selezionato
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEdit(GlassModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset selezione
|
||||
/// </summary>
|
||||
protected void DoReset()
|
||||
{
|
||||
EditRecord = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selezione articolo x display info
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoSelect(GlassModel curRec)
|
||||
{
|
||||
SelRecord = curRec;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void ResetSearch()
|
||||
{
|
||||
SearchVal = "";
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
numRecord = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
currPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private List<GlassModel> AllRecords = new();
|
||||
private int currPage = 1;
|
||||
private GlassModel? EditRecord = null;
|
||||
private bool isLoading = false;
|
||||
private List<GlassModel> ListRecords = new();
|
||||
private int numRecord = 5;
|
||||
private GlassModel? SelRecord = null;
|
||||
private int totalCount = 0;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string searchVal { get; set; } = string.Empty;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task DoAdd()
|
||||
{
|
||||
// aggiungo un nuovo record in coda...
|
||||
EditRecord = new GlassModel()
|
||||
{
|
||||
Description = "New Glass",
|
||||
Code = "",
|
||||
Thickness = 30
|
||||
};
|
||||
await DoSave(EditRecord);
|
||||
}
|
||||
|
||||
private async Task DoSave(GlassModel currRec)
|
||||
{
|
||||
// salvo
|
||||
await DLService.ConfGlassUpsertAsync(currRec);
|
||||
await ResetEdit();
|
||||
UpdateTable();
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
}
|
||||
|
||||
private async Task FullUpdate()
|
||||
{
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
AllRecords = await DLService.ConfGlassGetAllAsync();
|
||||
// se ho ricerca testuale faccio filtro ulteriore...
|
||||
if (string.IsNullOrEmpty(SearchVal))
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.Where(x =>
|
||||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
x.Code.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
totalCount = AllRecords.Count;
|
||||
}
|
||||
|
||||
private async Task ResetEdit()
|
||||
{
|
||||
// reset edit
|
||||
EditRecord = null;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
private void UpdateTable()
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<h5>Conf. Hardware</h5>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<div class="px-0 d-flex justify-content-between">
|
||||
<div class="px-1">
|
||||
<div class="input-group input-group-sm" title="ricerca">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" @bind="@SearchVal">
|
||||
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-1">
|
||||
@if (isLoading || ListRecords == null)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else if (totalCount == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center display-6">Nessun record trovato</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-nowrap text-center">
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoReset"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
</th>
|
||||
@* <th>ID</th> *@
|
||||
<th class="text-nowrap">Fam.</th>
|
||||
<th class="w-100">Descrizione</th>
|
||||
<th class="text-end">Shape</th>
|
||||
@* <th class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-success" @onclick="DoAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</th> *@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
<tr>
|
||||
<td class="text-center">@item.Id</td>
|
||||
<td class="text-nowrap">@item.FamilyName</td>
|
||||
<td class="w-100">@item.Description</td>
|
||||
<td class="text-end">@item.Shape</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@if (totalCount >= numRecord)
|
||||
{
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="15">
|
||||
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Lux.UI.Components.Compo.Config
|
||||
{
|
||||
public partial class HardwareMan
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected ConfigDataService CDService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
if (searchVal != value)
|
||||
{
|
||||
searchVal = value;
|
||||
ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Reset selezione
|
||||
/// </summary>
|
||||
protected void DoReset()
|
||||
{
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selezione articolo x display info
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoSelect(HardwareModel curRec)
|
||||
{
|
||||
SelRecord = curRec;
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void ResetSearch()
|
||||
{
|
||||
SearchVal = "";
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
numRecord = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
currPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private List<HardwareModel> AllRecords = new();
|
||||
private int currPage = 1;
|
||||
private HardwareModel? EditRecord = null;
|
||||
private bool isLoading = false;
|
||||
private List<HardwareModel> ListRecords = new();
|
||||
private int numRecord = 5;
|
||||
private HardwareModel? SelRecord = null;
|
||||
private int totalCount = 0;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string searchVal { get; set; } = string.Empty;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// impossta record x eliminazione
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
protected async Task DoDelete(HardwareModel selRec)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.HardwareID} | {selRec.Description} | {selRec.Thickness}"))
|
||||
return;
|
||||
|
||||
// esegue eliminazione del record...
|
||||
await CDService.ConfHardwareDeleteAsync(selRec);
|
||||
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edit articolo selezionato
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEdit(HardwareModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
}
|
||||
#endif
|
||||
#if false
|
||||
private async Task DoAdd()
|
||||
{
|
||||
// aggiungo un nuovo record in coda...
|
||||
EditRecord = new HardwareModel()
|
||||
{
|
||||
Description = "New Glass",
|
||||
Code = "",
|
||||
Thickness = 30
|
||||
};
|
||||
await DoSave(EditRecord);
|
||||
}
|
||||
|
||||
private async Task DoSave(HardwareModel currRec)
|
||||
{
|
||||
// salvo
|
||||
await CDService.ConfHardwareUpsertAsync(currRec);
|
||||
await ResetEdit();
|
||||
UpdateTable();
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
AllRecords = CDService.ElencoHw(EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, "HW.AGB");
|
||||
// se ho ricerca testuale faccio filtro ulteriore...
|
||||
if (string.IsNullOrEmpty(SearchVal))
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.Where(x =>
|
||||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
x.FamilyName.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
totalCount = AllRecords.Count;
|
||||
}
|
||||
|
||||
#if false
|
||||
private void ResetEdit()
|
||||
{
|
||||
// reset edit
|
||||
EditRecord = null;
|
||||
ReloadData();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
private void UpdateTable()
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<h5>Conf. Profilo</h5>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<div class="px-0 d-flex justify-content-between">
|
||||
<div class="px-1">
|
||||
<div class="input-group input-group-sm" title="ricerca">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" @bind="@SearchVal">
|
||||
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-1">
|
||||
@if (isLoading || ListRecords == null)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else if (totalCount == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center display-6">Nessun record trovato</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-nowrap text-center">
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoReset"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
</th>
|
||||
@* <th>ID</th> *@
|
||||
<th class="text-nowrap">Cod.</th>
|
||||
<th class="w-100">Descrizione</th>
|
||||
<th class="text-nowrap text-end">Size mm</th>
|
||||
<th class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-success" @onclick="DoAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
<tr>
|
||||
<td class="text-center">@item.ProfileID</td>
|
||||
<td class="">@item.Code</td>
|
||||
<td class="w-100">@item.Description</td>
|
||||
<td class="text-end">@($"{item.Thickness:N2}")</td>
|
||||
<td class="text-nowrap text-end">
|
||||
@if (false)
|
||||
{
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-sm btn-secondary" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@if (totalCount >= numRecord)
|
||||
{
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="15">
|
||||
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,199 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Lux.UI.Components.Compo.Config
|
||||
{
|
||||
public partial class ProfileMan
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
if (searchVal != value)
|
||||
{
|
||||
searchVal = value;
|
||||
_ = FullUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// impossta record x eliminazione
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
protected async Task DoDelete(ProfileModel selRec)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.ProfileID} | {selRec.Description} | {selRec.Thickness}"))
|
||||
return;
|
||||
|
||||
// esegue eliminazione del record...
|
||||
await DLService.ConfProfileDeleteAsync(selRec);
|
||||
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edit articolo selezionato
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEdit(ProfileModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset selezione
|
||||
/// </summary>
|
||||
protected void DoReset()
|
||||
{
|
||||
EditRecord = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selezione articolo x display info
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoSelect(ProfileModel curRec)
|
||||
{
|
||||
SelRecord = curRec;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void ResetSearch()
|
||||
{
|
||||
SearchVal = "";
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
numRecord = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
currPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private List<ProfileModel> AllRecords = new();
|
||||
private int currPage = 1;
|
||||
private ProfileModel? EditRecord = null;
|
||||
private bool isLoading = false;
|
||||
private List<ProfileModel> ListRecords = new();
|
||||
private int numRecord = 5;
|
||||
private ProfileModel? SelRecord = null;
|
||||
private int totalCount = 0;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string searchVal { get; set; } = string.Empty;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task DoAdd()
|
||||
{
|
||||
// aggiungo un nuovo record in coda...
|
||||
EditRecord = new ProfileModel()
|
||||
{
|
||||
Description = "New Glass",
|
||||
Code = "",
|
||||
Thickness = 30
|
||||
};
|
||||
await DoSave(EditRecord);
|
||||
}
|
||||
|
||||
private async Task DoSave(ProfileModel currRec)
|
||||
{
|
||||
// salvo
|
||||
await DLService.ConfProfileUpsertAsync(currRec);
|
||||
await ResetEdit();
|
||||
UpdateTable();
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
}
|
||||
|
||||
private async Task FullUpdate()
|
||||
{
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
AllRecords = await DLService.ConfProfileGetAllAsync();
|
||||
// se ho ricerca testuale faccio filtro ulteriore...
|
||||
if (string.IsNullOrEmpty(SearchVal))
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.Where(x =>
|
||||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
x.Code.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
totalCount = AllRecords.Count;
|
||||
}
|
||||
|
||||
private async Task ResetEdit()
|
||||
{
|
||||
// reset edit
|
||||
EditRecord = null;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
private void UpdateTable()
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<h5>Conf. Legno</h5>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<div class="px-0 d-flex justify-content-between">
|
||||
<div class="px-1">
|
||||
<div class="input-group input-group-sm" title="ricerca">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" @bind="@SearchVal">
|
||||
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-1">
|
||||
@if (isLoading || ListRecords == null)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else if (totalCount == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center display-6">Nessun record trovato</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-nowrap text-center">
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoReset"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
</th>
|
||||
@* <th>ID</th> *@
|
||||
<th class="text-nowrap">Cod.</th>
|
||||
<th class="w-100">Descrizione</th>
|
||||
<th class="text-nowrap text-end">Tipo</th>
|
||||
<th class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-success" @onclick="DoAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
<tr>
|
||||
<td class="text-center">@item.WoodID</td>
|
||||
<td class="">@item.Code</td>
|
||||
<td class="w-100">@item.Description</td>
|
||||
<td class="text-end">@item.Type</td>
|
||||
<td class="text-nowrap text-end">
|
||||
@if (false)
|
||||
{
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-sm btn-secondary" disabled><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@if (totalCount >= numRecord)
|
||||
{
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="15">
|
||||
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,199 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Lux.UI.Components.Compo.Config
|
||||
{
|
||||
public partial class WoodMan
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
if (searchVal != value)
|
||||
{
|
||||
searchVal = value;
|
||||
_ = FullUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// impossta record x eliminazione
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
protected async Task DoDelete(WoodModel selRec)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.WoodID} | {selRec.Description} | Tipo: {selRec.Type}"))
|
||||
return;
|
||||
|
||||
// esegue eliminazione del record...
|
||||
await DLService.ConfWoodDeleteAsync(selRec);
|
||||
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edit articolo selezionato
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEdit(WoodModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset selezione
|
||||
/// </summary>
|
||||
protected void DoReset()
|
||||
{
|
||||
EditRecord = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selezione articolo x display info
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoSelect(WoodModel curRec)
|
||||
{
|
||||
SelRecord = curRec;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void ResetSearch()
|
||||
{
|
||||
SearchVal = "";
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
numRecord = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
currPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private List<WoodModel> AllRecords = new();
|
||||
private int currPage = 1;
|
||||
private WoodModel? EditRecord = null;
|
||||
private bool isLoading = false;
|
||||
private List<WoodModel> ListRecords = new();
|
||||
private int numRecord = 5;
|
||||
private WoodModel? SelRecord = null;
|
||||
private int totalCount = 0;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string searchVal { get; set; } = string.Empty;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task DoAdd()
|
||||
{
|
||||
// aggiungo un nuovo record in coda...
|
||||
EditRecord = new WoodModel()
|
||||
{
|
||||
Description = "New Wood",
|
||||
Code = "",
|
||||
Type = 1
|
||||
};
|
||||
await DoSave(EditRecord);
|
||||
}
|
||||
|
||||
private async Task DoSave(WoodModel currRec)
|
||||
{
|
||||
// salvo
|
||||
await DLService.ConfWoodUpsertAsync(currRec);
|
||||
await ResetEdit();
|
||||
UpdateTable();
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
}
|
||||
|
||||
private async Task FullUpdate()
|
||||
{
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
AllRecords = await DLService.ConfWoodGetAllAsync();
|
||||
// se ho ricerca testuale faccio filtro ulteriore...
|
||||
if (string.IsNullOrEmpty(SearchVal))
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.Where(x =>
|
||||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
x.Code.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
|
||||
.OrderBy(x => x.Description)
|
||||
.ToList();
|
||||
}
|
||||
totalCount = AllRecords.Count;
|
||||
}
|
||||
|
||||
private async Task ResetEdit()
|
||||
{
|
||||
// reset edit
|
||||
EditRecord = null;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
private void UpdateTable()
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
<tbody>
|
||||
@foreach (var item in bomDict)
|
||||
{
|
||||
@if (item.Key == currIdx && EditRecord != null)
|
||||
@if (EditRecord != null && item.Key == currIdx)
|
||||
{
|
||||
<tr class="table-info">
|
||||
<td>@(item.Key + 1)</td>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using EgwCoreLib.Lux.Core.RestPayload;
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using EgwMultiEngineManager.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
@if (AddVisible)
|
||||
{
|
||||
<div class="modal" tabindex="-1" style="display:block; background-color: rgba(10,10,10,.6);" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title fs-4">Aggiunta Classe Anagrafica</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="ToggleAdd">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (NewRecord != null)
|
||||
{
|
||||
|
||||
<div class="row">
|
||||
<div class="input-group mb-2">
|
||||
<span class="input-group-text" id="basic-addon1">Codice</span>
|
||||
<input type="text" class="form-control text-end" @bind="@NewRecord.ClassCod" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="input-group mb-2">
|
||||
<span class="input-group-text" id="basic-addon1">Descrizione</span>
|
||||
<input type="text" class="form-control text-end" @bind="@NewRecord.Description" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(ErrorMsg))
|
||||
{
|
||||
<div class="alert alert-danger my-3">
|
||||
@ErrorMsg
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button class="btn btn-success w-100" @onclick="DoAdd"><i class="fa-solid fa-save"></i> Save</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-warning w-100" @onclick="ToggleAdd">Cancel <i class="fa-solid fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoReset"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
</th>
|
||||
<th>Cod</th>
|
||||
<th>Descrizione</th>
|
||||
<th class="text-end"># Val</th>
|
||||
<th class="text-end">
|
||||
<button class="btn btn-sm btn-success" @onclick="ToggleAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
<tr class="@checkSel(item)">
|
||||
@if (EditRecord != null && item.ClassCod == EditRecord.ClassCod)
|
||||
{
|
||||
<td class="text-start text-nowrap">
|
||||
<button class="btn btn-sm btn-success" @onclick="() => DoSave(item)"><i class="fa-solid fa-save"></i></button>
|
||||
<button class="btn btn-sm btn-secondary opacity-50"><i class="fa-solid fa-pencil"></i></button>
|
||||
</td>
|
||||
<td>@item.ClassCod</td>
|
||||
<td><input class="form-control form-control-sm border-2 border-info py-1" type="text" style="width: 12rem;" @bind="@item.Description" /></td>
|
||||
<td class="text-end">@item.NumChild</td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-warning" @onclick="DoReset"><i class="fa-solid fa-ban"></i></button>
|
||||
</td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td class="text-start text-nowrap">
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => DoSelect(item)"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
<button class="btn btn-sm btn-info" @onclick="() => DoEdit(item)"><i class="fa-solid fa-pencil"></i></button>
|
||||
@* <button class="btn btn-sm btn-success" @onclick="() => DoClone(item)"><i class="fa-solid fa-clone"></i></button> *@
|
||||
</td>
|
||||
<td>@item.ClassCod</td>
|
||||
<td>@item.Description</td>
|
||||
<td class="text-end">@item.NumChild</td>
|
||||
<td class="text-end">
|
||||
@if (item.NumChild > 0)
|
||||
{
|
||||
<button class="btn btn-sm btn-secondary opacity-50" disabled title="Record Child correlati: cancellazione non permessa"><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash-can"></i></button>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@if (totalCount >= numRecord)
|
||||
{
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
}
|
||||
</table>
|
||||
@@ -0,0 +1,244 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.JSInterop;
|
||||
using NLog.LayoutRenderers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lux.UI.Components.Compo
|
||||
{
|
||||
public partial class GenClassMan
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string> EC_Selected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> EC_Updated { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<GenClassModel> ListGenClass { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public string SearchVal { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected List<GenClassModel> AllRecords = new List<GenClassModel>();
|
||||
protected List<GenClassModel> ListRecords = new List<GenClassModel>();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Genera nuovo record e lo salva
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
protected async Task DoAdd()
|
||||
{
|
||||
if (NewRecord != null)
|
||||
{
|
||||
// verifico non sia duplicato...
|
||||
var recExist = ListRecords.Count(x => x.ClassCod == NewRecord.ClassCod);
|
||||
if (recExist > 0)
|
||||
{
|
||||
ErrorMsg = $"Errore: record già esistente con codice {NewRecord.ClassCod}";
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorMsg = "";
|
||||
// faccio upsert record...
|
||||
await DLService.GenClassUpsertAsync(NewRecord);
|
||||
// segnalo update x reload
|
||||
await EC_Updated.InvokeAsync(true);
|
||||
NewRecord = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoCancel()
|
||||
{
|
||||
ResetEdit();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona record
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoClone(GenClassModel curRec)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eliminazione record
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
protected async Task DoDelete(GenClassModel selRec)
|
||||
{
|
||||
// controlo che NON abbia child obj... altrimenti esco
|
||||
if (selRec.NumChild > 0)
|
||||
return;
|
||||
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.ClassCod} | {selRec.Description}"))
|
||||
return;
|
||||
|
||||
// esegue eliminazione del record...
|
||||
await DLService.GenClassDeleteAsync(selRec);
|
||||
|
||||
// segnalo update x reload
|
||||
await EC_Updated.InvokeAsync(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edit articolo selezionato
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected async void DoEdit(GenClassModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
SelRecord = curRec;
|
||||
await EC_Selected.InvokeAsync(curRec.ClassCod);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset selezione
|
||||
/// </summary>
|
||||
protected async void DoReset()
|
||||
{
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
await EC_Selected.InvokeAsync("");
|
||||
}
|
||||
|
||||
protected async Task DoSave(GenClassModel currRec)
|
||||
{
|
||||
// faccio upsert record...
|
||||
await DLService.GenClassUpsertAsync(currRec);
|
||||
// segnalo update x reload
|
||||
await EC_Updated.InvokeAsync(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selezione articolo x display info
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected async void DoSelect(GenClassModel curRec)
|
||||
{
|
||||
SelRecord = curRec;
|
||||
await EC_Selected.InvokeAsync(curRec.ClassCod);
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
numRecord = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
currPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void ToggleAdd()
|
||||
{
|
||||
AddVisible = !AddVisible;
|
||||
NewRecord = new GenClassModel()
|
||||
{
|
||||
ClassCod = "NewClass",
|
||||
Description = $"Descrizione-{DateTime.Now:yyyy.MM.dd-HH.mm.ss}"
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool AddVisible = false;
|
||||
private int currPage = 1;
|
||||
private GenClassModel? EditRecord = null;
|
||||
private string ErrorMsg = "";
|
||||
private bool isLoading = false;
|
||||
private GenClassModel? NewRecord = null;
|
||||
private int numRecord = 10;
|
||||
|
||||
private GenClassModel? SelRecord = null;
|
||||
|
||||
private int totalCount = 0;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private string checkSel(GenClassModel curRec)
|
||||
{
|
||||
string answ = "";
|
||||
if (SelRecord != null)
|
||||
{
|
||||
answ = curRec.ClassCod == SelRecord.ClassCod ? "table-info" : "";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
private void ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
AllRecords = ListGenClass;
|
||||
// se ho ricerca testuale faccio filtro ulteriore...
|
||||
if (!string.IsNullOrEmpty(SearchVal))
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.Where(x =>
|
||||
x.ClassCod.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
|
||||
.ToList();
|
||||
}
|
||||
totalCount = AllRecords.Count;
|
||||
}
|
||||
|
||||
private void ResetEdit()
|
||||
{
|
||||
// reset edit
|
||||
EditRecord = null;
|
||||
ReloadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
private void UpdateTable()
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.OrderBy(x => x.ClassCod)
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
@if (isLoading || ListRecords == null)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else if (totalCount == 0)
|
||||
{
|
||||
<div class="alert alert-info text-center display-4">Nessun record trovato</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-nowrap">
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoReset"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
</th>
|
||||
@* <th>ID</th> *@
|
||||
<th class="text-nowrap text-center mx-2">Ord.</th>
|
||||
<th class="w-100">Valore</th>
|
||||
<th class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-success" @onclick="DoAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
string cssBtnUp = EditRecord == null && item.Ordinal > 1 ? "btn-outline-primary" : "btn-outline-secondary opacity-50 disabled";
|
||||
string cssBtnDown = EditRecord == null && item.Ordinal < totalCount ? "btn-outline-primary" : "btn-outline-secondary opacity-50 disabled";
|
||||
<tr>
|
||||
@if (EditRecord != null && item.GenValID == EditRecord.GenValID)
|
||||
{
|
||||
<td class="text-start text-nowrap">
|
||||
<button class="btn btn-sm btn-success" @onclick="() => DoSave(item)"><i class="fa-solid fa-save"></i></button>
|
||||
<button class="btn btn-sm btn-secondary opacity-50"><i class="fa-solid fa-pencil" title="Edit @item.GenValID"></i></button>
|
||||
@* <button class="btn btn-sm btn-success" @onclick="() => DoClone(item)" title="Duplicate @item.GenValID"><i class="fa-solid fa-clone"></i></button> *@
|
||||
</td>
|
||||
@* <td>@item.GenValID</td> *@
|
||||
<td class="text-nowrap text-center mx-2">
|
||||
<button class="btn @cssBtnUp btn-sm fa-solid fa-caret-up"></button>
|
||||
@item.Ordinal
|
||||
<button class="btn @cssBtnDown btn-sm fa-solid fa-caret-down"></button>
|
||||
</td>
|
||||
<td class="w-100"><input class="form-control form-control-sm border-2 border-info py-1" type="text" @bind="@item.ValString" /></td>
|
||||
<td class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-warning" @onclick="DoReset"><i class="fa-solid fa-ban"></i></button>
|
||||
</td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td class="text-start text-nowrap">
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => DoSelect(item)" title="Select @item.GenValID"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
<button class="btn btn-sm btn-info" @onclick="() => DoEdit(item)"><i class="fa-solid fa-pencil" title="Edit @item.GenValID"></i></button>
|
||||
@* <button class="btn btn-sm btn-success" @onclick="() => DoClone(item)" title="Duplicate @item.GenValID"><i class="fa-solid fa-clone"></i></button> *@
|
||||
</td>
|
||||
@* <td>@item.GenValID</td> *@
|
||||
<td class="text-nowrap text-center mx-2">
|
||||
<button class="btn @cssBtnUp btn-sm fa-solid fa-caret-up" @onclick="() => MoveRec(item, true)"></button>
|
||||
@item.Ordinal
|
||||
<button class="btn @cssBtnDown btn-sm fa-solid fa-caret-down" @onclick="() => MoveRec(item, false)"></button>
|
||||
</td>
|
||||
<td class="w-100">@item.ValString</td>
|
||||
<td class="text-nowrap text-end">
|
||||
<button class="btn btn-sm btn-danger" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash-can"></i></button>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@if (totalCount >= numRecord)
|
||||
{
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="15">
|
||||
<EgwCoreLib.Razor.DataPager currPage="@currPage" PageSize="@numRecord" totalCount="@totalCount" numPageChanged="SavePage" numRecordChanged="SaveNumRec"></EgwCoreLib.Razor.DataPager>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
using EgwCoreLib.Lux.Core;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Lux.UI.Components.Compo
|
||||
{
|
||||
public partial class GenValMan
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public List<GenClassModel> ListGenClass { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public FiltSelect SelFilt { get; set; } = null!;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Classes
|
||||
|
||||
/// <summary>
|
||||
/// Filtro selezione items
|
||||
/// </summary>
|
||||
public class FiltSelect
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public string SearchVal { get; set; } = "";
|
||||
public string SelCodGroup { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (!(obj is FiltSelect item))
|
||||
return false;
|
||||
|
||||
if (SelCodGroup != item.SelCodGroup)
|
||||
return false;
|
||||
|
||||
if (SearchVal != item.SearchVal)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
|
||||
#endregion Public Classes
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected List<GenValueModel> AllRecords = new List<GenValueModel>();
|
||||
protected List<GenValueModel> ListRecords = new List<GenValueModel>();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Clona record
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoClone(GenValueModel curRec)
|
||||
{
|
||||
#if false
|
||||
editRecord = new ItemModel()
|
||||
{
|
||||
ItemIDParent = curRec.ItemType == Enums.ItemClassType.Bom ? curRec.ItemID : curRec.ItemIDParent,
|
||||
CodGroup = curRec.CodGroup,
|
||||
ItemType = curRec.ItemType == Enums.ItemClassType.Bom ? Enums.ItemClassType.BomAlt : curRec.ItemType,
|
||||
IsService = curRec.IsService,
|
||||
ItemCode = curRec.ItemCode,
|
||||
ExtItemCode = $"{curRec.ExtItemCode} - COPY",
|
||||
SupplCode = curRec.ItemType == Enums.ItemClassType.Bom ? $"{curRec.SupplCode} ALT" : curRec.SupplCode,
|
||||
Description = $"{curRec.Description} - COPY",
|
||||
Cost = curRec.Cost,
|
||||
Margin = curRec.Margin,
|
||||
QtyMin = curRec.QtyMin,
|
||||
QtyMax = curRec.QtyMax,
|
||||
UM = curRec.UM
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// impossta record x eliminazione
|
||||
/// </summary>
|
||||
/// <param name="selRec"></param>
|
||||
protected async Task DoDelete(GenValueModel selRec)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.ClassCod} | {selRec.ValString}"))
|
||||
return;
|
||||
|
||||
// esegue eliminazione del record...
|
||||
await DLService.GenValDeleteAsync(selRec);
|
||||
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
#if false
|
||||
// segnalo update x reload
|
||||
await EC_Updated.InvokeAsync(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Edit articolo selezionato
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEdit(GenValueModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset selezione
|
||||
/// </summary>
|
||||
protected void DoReset()
|
||||
{
|
||||
EditRecord = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selezione articolo x display info
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoSelect(GenValueModel curRec)
|
||||
{
|
||||
SelRecord = curRec;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (!SelFilt.Equals(actFilt) || true)
|
||||
{
|
||||
actFilt = SelFilt;
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
}
|
||||
|
||||
protected void SaveNumRec(int newNum)
|
||||
{
|
||||
numRecord = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected void SavePage(int newNum)
|
||||
{
|
||||
currPage = newNum;
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private FiltSelect actFilt = new FiltSelect();
|
||||
|
||||
private int currPage = 1;
|
||||
|
||||
private GenValueModel? EditRecord = null;
|
||||
|
||||
private bool isLoading = false;
|
||||
|
||||
private int numRecord = 10;
|
||||
|
||||
private GenValueModel? SelRecord = null;
|
||||
|
||||
private int totalCount = 0;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task DoAdd()
|
||||
{
|
||||
// aggiungo un nuovo record in coda...
|
||||
EditRecord = new GenValueModel()
|
||||
{
|
||||
ClassCod = actFilt.SelCodGroup,
|
||||
ValString = $"Nuovo-{DateTime.Now:yy.MM.ss HH.mm.ss}",
|
||||
Ordinal = totalCount + 1
|
||||
};
|
||||
await DoSave(EditRecord);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue spostamento
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
/// <param name="moveUp"></param>
|
||||
/// <returns></returns>
|
||||
private async Task MoveRec(GenValueModel curRec, bool moveUp)
|
||||
{
|
||||
await DLService.GenValMoveAsync(curRec, moveUp);
|
||||
await DoCancel();
|
||||
}
|
||||
|
||||
private async Task DoCancel()
|
||||
{
|
||||
await ResetEdit();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
private async Task DoSave(GenValueModel currRec)
|
||||
{
|
||||
// salvo
|
||||
await DLService.GenValUpsertAsync(currRec);
|
||||
await ResetEdit();
|
||||
UpdateTable();
|
||||
EditRecord = null;
|
||||
SelRecord = null;
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
AllRecords = await DLService.GenValGetFiltAsync(actFilt.SelCodGroup);
|
||||
// se ho ricerca testuale faccio filtro ulteriore...
|
||||
if (string.IsNullOrEmpty(actFilt.SearchVal))
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.OrderBy(x => x.Ordinal)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
AllRecords = AllRecords
|
||||
.Where(x =>
|
||||
x.ClassCod.Contains(actFilt.SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
x.ValString.Contains(actFilt.SearchVal, StringComparison.InvariantCultureIgnoreCase))
|
||||
.OrderBy(x => x.Ordinal)
|
||||
.ToList();
|
||||
}
|
||||
totalCount = AllRecords.Count;
|
||||
}
|
||||
|
||||
private async Task ResetEdit()
|
||||
{
|
||||
// reset edit
|
||||
EditRecord = null;
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
private void UpdateTable()
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Lux.UI.Components.Compo
|
||||
|
||||
@@ -99,5 +99,3 @@ else
|
||||
</tfoot>
|
||||
</table>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using EgwCoreLib.Lux.Core;
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
@@ -68,9 +68,6 @@ namespace Lux.UI.Components.Compo
|
||||
#region Protected Fields
|
||||
|
||||
protected List<ItemModel> AllRecords = new List<ItemModel>();
|
||||
#if false
|
||||
protected List<ItemGroupModel> ListItemGroup = new List<ItemGroupModel>();
|
||||
#endif
|
||||
protected List<ItemModel> ListRecords = new List<ItemModel>();
|
||||
|
||||
#endregion Protected Fields
|
||||
@@ -120,7 +117,7 @@ namespace Lux.UI.Components.Compo
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler eliminare il record? Dettagli: {selRec.ItemID} | {selRec.CodGroup} | {selRec.ItemType} | {selRec.ExtItemCode}"))
|
||||
return;
|
||||
//// esegue eliminazione del record...
|
||||
//await DLService.ItemDeleteAsync(selRec);
|
||||
//await CDService.ItemDeleteAsync(selRec);
|
||||
|
||||
editRecord = null;
|
||||
selRecord = null;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@using EgwCoreLib.Lux.Data.DbModel
|
||||
@using EgwCoreLib.Lux.Data.DbModel.Sales
|
||||
<div class="alert alert-warning text-center display-4">
|
||||
display check finali
|
||||
<button class="btn btn-sm btn-primary" title="Reset selezione" @onclick="DoCancel"><i class="fa-solid fa-arrow-rotate-right"></i></button>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<div class="row">
|
||||
@if (isLoading)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@SelProfile" class="form-select">
|
||||
<option value="">--- Nessuna Selezione ---</option>
|
||||
@foreach (var item in ListProfiles)
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Profilo</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@SelGlass" class="form-select">
|
||||
<option value="">--- Nessuna Selezione ---</option>
|
||||
@foreach (var item in ListGlass)
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Vetro</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@SelWood" class="form-select">
|
||||
<option value="">--- Nessuna Selezione ---</option>
|
||||
@foreach (var item in ListWood)
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Legno</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@SelColor" class="form-select">
|
||||
<option value="">--- Nessuna Selezione ---</option>
|
||||
@foreach (var item in ListColors)
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Colore</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-success w-100" @onclick="DoSave"><i class="fa-solid fa-floppy-disk"></i> Save</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-warning w-100" @onclick="DoCancel"><i class="fa-solid fa-ban"></i> Cancel</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -0,0 +1,129 @@
|
||||
using EgwCoreLib.Lux.Core;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Lux.UI.Components.Compo
|
||||
{
|
||||
public partial class OfferCommonPar
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public OfferModel CurrRecord { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> EC_Close { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<OfferModel> EC_Updated { get; set; }
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gestione selezione Colore
|
||||
/// </summary>
|
||||
protected string SelColor
|
||||
{
|
||||
get => CurrSel.GetVal("Color");
|
||||
set => CurrSel.SetVal("Color", value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gestione selezione Glass
|
||||
/// </summary>
|
||||
protected string SelGlass
|
||||
{
|
||||
get => CurrSel.GetVal("Glass");
|
||||
set => CurrSel.SetVal("Glass", value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gestione selezione Profile
|
||||
/// </summary>
|
||||
protected string SelProfile
|
||||
{
|
||||
get => CurrSel.GetVal("Profile");
|
||||
set => CurrSel.SetVal("Profile", value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gestione selezione Wood
|
||||
/// </summary>
|
||||
protected string SelWood
|
||||
{
|
||||
get => CurrSel.GetVal("Wood");
|
||||
set => CurrSel.SetVal("Wood", value);
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
isLoading = true;
|
||||
// deserializzo se possibile dal record...
|
||||
CurrSel = new ParamDict(CurrRecord.DictPresel);
|
||||
// leggo dati di base
|
||||
var AllColors = await DLService.GenValGetFiltAsync("WoodCol");
|
||||
var AllConfGlass = await DLService.ConfGlassGetAllAsync();
|
||||
var AllConfProfile = await DLService.ConfProfileGetAllAsync();
|
||||
var AllConfWood = await DLService.ConfWoodGetAllAsync();
|
||||
// conversione tipi
|
||||
ListColors = AllColors
|
||||
.Select(x => x.ValString)
|
||||
.ToList();
|
||||
ListGlass = AllConfGlass
|
||||
.Select(x => x.Description)
|
||||
.ToList();
|
||||
ListProfiles = AllConfProfile
|
||||
.Select(x => x.Description)
|
||||
.ToList();
|
||||
ListWood = AllConfWood
|
||||
.Select(x => x.Description)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private ParamDict CurrSel = new ParamDict("");
|
||||
|
||||
private bool isLoading = false;
|
||||
|
||||
private List<string> ListColors = new List<string>();
|
||||
|
||||
private List<string> ListGlass = new List<string>();
|
||||
|
||||
private List<string> ListProfiles = new List<string>();
|
||||
|
||||
private List<string> ListWood = new List<string>();
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task DoCancel()
|
||||
{
|
||||
await EC_Close.InvokeAsync(true);
|
||||
}
|
||||
|
||||
private async Task DoSave()
|
||||
{
|
||||
// aggiorno valore serializzato...
|
||||
CurrRecord.DictPresel = CurrSel.Serialized;
|
||||
// richiesta update con salvataggio record
|
||||
await EC_Updated.InvokeAsync(CurrRecord);
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -1,146 +1,61 @@
|
||||
@using EgwCoreLib.Lux.Core
|
||||
@* <div class="card shadow">
|
||||
<div class="card-dialog card-xl">
|
||||
<div class="card-content">
|
||||
<div class="card-header">
|
||||
<div class="card-title fs-4">Edit Offerta <b>@CurrRecord.OfferCode</b></div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="card" aria-label="Close" @onclick="ClosePopup">
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body"> *@
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.CustomerID" class="form-select">
|
||||
@foreach (var item in CustomersList)
|
||||
{
|
||||
<option value="@item.CustomerID">@item.FirstName @item.LastName (@item.VAT)</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Cliente</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.DealerID" class="form-select">
|
||||
@foreach (var item in DealersList)
|
||||
{
|
||||
<option value="@item.DealerID">@item.CompanyName | @item.FirstName @item.LastName</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Rivenditore</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.OffertState" class="form-select">
|
||||
@foreach (var item in System.Enum.GetValues(typeof(EgwCoreLib.Lux.Core.Enums.OfferStates)))
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Stato</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<input @bind="@CurrRecord.Inserted" class="form-control" type="date">
|
||||
<label class="small">Data Ins.</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<input @bind="@CurrRecord.ValidUntil" class="form-control" type="date">
|
||||
<label class="small">Validità</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-floating mb-3">
|
||||
<textarea @bind="@CurrRecord.Description" class="form-control" type="text"></textarea>
|
||||
<label class="small">Descrizione</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-success w-100" @onclick="DoSave"><i class="fa-solid fa-floppy-disk"></i> Save</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-warning w-100" @onclick="DoCancel"><i class="fa-solid fa-ban"></i> Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
@* </div>
|
||||
</div>
|
||||
</div>
|
||||
</div> *@
|
||||
|
||||
@* <div class="modal" tabindex="-1" style="display:block; background-color: rgba(10,10,10,.6);" role="dialog">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title fs-4">Edit Offerta <b>@CurrRecord.OfferCode</b></div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="ClosePopup">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.CustomerID" class="form-select">
|
||||
@foreach (var item in CustomersList)
|
||||
{
|
||||
<option value="@item.CustomerID">@item.FirstName @item.LastName (@item.VAT)</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Cliente</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.DealerID" class="form-select">
|
||||
@foreach (var item in DealersList)
|
||||
{
|
||||
<option value="@item.DealerID">@item.CompanyName | @item.FirstName @item.LastName</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Rivenditore</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.OffertState" class="form-select">
|
||||
@foreach (var item in Enum.GetValues(typeof(Core.Enum.OfferStates)))
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Stato</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<input @bind="@CurrRecord.Inserted" class="form-control" type="date">
|
||||
<label class="small">Data Ins.</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<input @bind="@CurrRecord.ValidUntil" class="form-control" type="date">
|
||||
<label class="small">Validità</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-floating mb-3">
|
||||
<textarea @bind="@CurrRecord.Description" class="form-control" type="text"></textarea>
|
||||
<label class="small">Descrizione</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-success w-100"><i class="fa-solid fa-floppy-disk"></i> Save</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-warning w-100"><i class="fa-solid fa-ban"></i> Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.CustomerID" class="form-select">
|
||||
@foreach (var item in CustomersList)
|
||||
{
|
||||
<option value="@item.CustomerID">@item.FirstName @item.LastName (@item.VAT)</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Cliente</label>
|
||||
</div>
|
||||
</div>
|
||||
</div> *@
|
||||
<div class="col-3">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.DealerID" class="form-select">
|
||||
@foreach (var item in DealersList)
|
||||
{
|
||||
<option value="@item.DealerID">@item.CompanyName | @item.FirstName @item.LastName</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Rivenditore</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<select @bind="@CurrRecord.OffertState" class="form-select">
|
||||
@foreach (var item in System.Enum.GetValues(typeof(EgwCoreLib.Lux.Core.Enums.OfferStates)))
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
<label class="small">Stato</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<input @bind="@CurrRecord.Inserted" class="form-control" type="date">
|
||||
<label class="small">Data Ins.</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="form-floating mb-3">
|
||||
<input @bind="@CurrRecord.ValidUntil" class="form-control" type="date">
|
||||
<label class="small">Validità</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-floating mb-3">
|
||||
<textarea @bind="@CurrRecord.Description" class="form-control" type="text"></textarea>
|
||||
<label class="small">Descrizione</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-success w-100" @onclick="DoSave"><i class="fa-solid fa-floppy-disk"></i> Save</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button class="btn btn-lg btn-warning w-100" @onclick="DoCancel"><i class="fa-solid fa-ban"></i> Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Threading.Tasks;
|
||||
@@ -46,17 +46,6 @@ namespace Lux.UI.Components.Compo
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task ClosePopup()
|
||||
{
|
||||
await EC_Close.InvokeAsync(true);
|
||||
#if false
|
||||
// Close the Popup
|
||||
ShowPopup = false;
|
||||
// Refresh Users
|
||||
await GetUsers();
|
||||
#endif
|
||||
}
|
||||
|
||||
private async Task DoCancel()
|
||||
{
|
||||
await EC_Close.InvokeAsync(true);
|
||||
@@ -64,9 +53,7 @@ namespace Lux.UI.Components.Compo
|
||||
|
||||
private async Task DoSave()
|
||||
{
|
||||
// fixme todo !!!
|
||||
// effettuare salvataggio record...
|
||||
|
||||
// richiesta update con salvataggio record
|
||||
await EC_Updated.InvokeAsync(CurrRecord);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
@if (EditRecord != null)
|
||||
@if (EditRecord != null && CurrEditMode == EditMode.SerStruc)
|
||||
{
|
||||
<h1>EDITING</h1>
|
||||
<h3>@EditRecord.OfferRowUID</h3>
|
||||
@* <WebWindowConfigurator.WebWindowMaker IN_TemplateDTOList="@AvailTemplateList"
|
||||
IN_SelTemplate="@SelTemplate"
|
||||
EC_OnUpdate="SaveJWD"
|
||||
EC_OnSelectedTemplate="SetTemplate"
|
||||
LiveSVG="@currSvg">
|
||||
</WebWindowConfigurator.WebWindowMaker> *@
|
||||
<WebWindowComplex.TableComp ListPayload="SetupList"
|
||||
LiveData="CurrData"
|
||||
EC_OnUpdate="SaveJWD"
|
||||
EC_OnClose="CloseEdit">
|
||||
</WebWindowComplex.TableComp>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-info bg-opacity-50 bg-gradient d-flex justify-content-between">
|
||||
<div class="px-0">Dettaglio Offerta</div>
|
||||
<div class="px-0">
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => RecalcOffer()">Ricalcola <i class="fa-solid fa-calculator"></i></button>
|
||||
<div class="px-0 fs-4">Dettaglio Offerta</div>
|
||||
<div class="px-0 d-flex justify-content-end">
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-warning" @onclick="() => OfferForceParameters()">Forza Parametri <i class="fa-solid fa-hammer"></i></button>
|
||||
</div>
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => OfferUpdatePrices()">Aggiorna Prezzi <i class="fa-solid fa-calculator"></i></button>
|
||||
</div>
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => OfferUpdateAllCosting()">Ricalcolo Completo <i class="fa-solid fa-calculator"></i></button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="cad-body px-2">
|
||||
@if (isLoading || ListRecords == null)
|
||||
@@ -35,8 +42,10 @@ else
|
||||
<tr>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<th>Def</th>
|
||||
<th>img</th>
|
||||
<th>
|
||||
<button class="btn btn-sm btn-primary" style="min-width: 6rem;" @onclick="ForceReloadData"><i class="fa-solid fa-rotate-right"></i></button>
|
||||
</th>
|
||||
<th>Preview</th>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -45,22 +54,41 @@ else
|
||||
<th>Codice</th>
|
||||
<th>Descrizione</th>
|
||||
<th class="text-end">Qty</th>
|
||||
<th class="text-end">Importo </th>
|
||||
<th class="text-end">Tot</th>
|
||||
<th class="text-end">Importo</th>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<th class="text-end" title="Cambio Materiali">Mat.</th>
|
||||
}
|
||||
<th class="text-end">Totale</th>
|
||||
<th class="text-end">Marg.</th>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<th></th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in ListRecords)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<tr class="@RowClass(item)">
|
||||
<td class="text-nowrap">
|
||||
<span class="px-1">
|
||||
@item.RowNum
|
||||
</span>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<button class="btn btn-sm btn-info" @onclick="() => DoEdit(item)"><i class="fa-solid fa-pencil"></i></button>
|
||||
if (CurrEditMode == EditMode.None)
|
||||
{
|
||||
<button class="btn btn-sm btn-info" @onclick="() => DoEdit(item)"><i class="fa-solid fa-pencil"></i></button>
|
||||
<button class="btn btn-sm btn-warning" @onclick="() => DoClone(item)"><i class="fa-solid fa-clone"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EditRecord != null && EditRecord.OfferRowID == item.OfferRowID)
|
||||
{
|
||||
<button class="btn btn-sm btn-success" title="Annulla Modifiche" @onclick="() => DoSave(item)"><i class="fa-solid fa-floppy-disk"></i></button>
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -70,44 +98,159 @@ else
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<td>
|
||||
<img class="img-fluid" src="@(imgUrl(item.OfferRowUID, item.Environment))" width="48" />
|
||||
@if (string.IsNullOrEmpty(item.SerStruct) || item.SerStruct.Length <= 2)
|
||||
{
|
||||
<img class="img-fluid" src="@(imgUrl(item.OfferRowUID, $"{item.Envir}"))" width="48" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<img class="img-fluid" src="@(imgUrl(item.OfferRowUID, $"{item.Envir}"))" width="48" @onclick="() => DoEditJwd(item)" title="Edit Item" />
|
||||
}
|
||||
</td>
|
||||
}
|
||||
<td>@item.OfferRowUID</td>
|
||||
<td>@item.Note</td>
|
||||
<td class="text-end">@item.Qty</td>
|
||||
<td class="text-end">
|
||||
@if (!(item.BomOk && item.ItemOk))
|
||||
<td class="small">
|
||||
<div>@item.OfferRowUID</div>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit && !string.IsNullOrEmpty(item.SerStruct) && item.SerStruct.Length > 2)
|
||||
{
|
||||
<span class="text-danger me-2" title=""><i class="fa-solid fa-triangle-exclamation"></i></span>
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => RequestBom(item)" title="Richiesta ricalcolo BOM">
|
||||
BOM <i class="fa-solid fa-arrow-right-arrow-left pe-2"></i>
|
||||
@if (item.AwaitBom)
|
||||
{
|
||||
<span class="text-warning spinner-grow spinner-grow-sm" aria-hidden="true"></span>
|
||||
}
|
||||
</button>
|
||||
}
|
||||
@if (item.Envir != EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW || !string.IsNullOrEmpty(item.FileName))
|
||||
{
|
||||
<div class="input-group input-group-sm">
|
||||
@if (EditRecord != null && EditRecord.OfferRowID == item.OfferRowID)
|
||||
{
|
||||
<span>
|
||||
<InputFile class="form-control" OnChange="UploadFile" style="width: 24rem;" />
|
||||
</span>
|
||||
<button class="btn btn-sm btn-info" @onclick="() => ToggleFileEdit(null)"><i class="fa-solid fa-floppy-disk"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="input-group-text small"><b>@item.FileName</b> | @fSize(item.FileSize)</span>
|
||||
<button class="btn btn-sm btn-primary" @onclick="() => ToggleFileEdit(item)"><i class="fa-solid fa-floppy-disk"></i></button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@($"{item.Cost:C2}")
|
||||
</td>
|
||||
<td class="text-end fw-bold">@($"{item.TotalCost:C2}")</td>
|
||||
@if (CurrEditMode == EditMode.RecData && EditRecord != null && EditRecord.OfferRowID == item.OfferRowID)
|
||||
{
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<input class="form-input w-100" style="width: 16rem;" type="text" @bind="@item.Note" />
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<input class="text-end" style="width: 4rem;" type="number" @bind="@item.Qty" />
|
||||
</td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td>@item.Note</td>
|
||||
<td class="text-end">
|
||||
<b>@item.Qty</b>
|
||||
</td>
|
||||
}
|
||||
<td class="text-end text-nowrap">
|
||||
<div class="fw-bold" title="Prezzo Finito">
|
||||
@if (!(item.BomOk && item.ItemOk))
|
||||
{
|
||||
<span class="text-danger me-2" title=""><i class="fa-solid fa-triangle-exclamation"></i></span>
|
||||
}
|
||||
@if (item.AwaitPrice)
|
||||
{
|
||||
<span class="text-warning spinner-grow spinner-grow-sm" aria-hidden="true"></span>
|
||||
}
|
||||
@($"{item.UnitPrice:C2}")
|
||||
</div>
|
||||
<div class="small text-secondary" title="RockBottom Price">(@item.UnitCost.ToString("C2"))</div>
|
||||
</td>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<td class="text-end">
|
||||
@if(!string.IsNullOrEmpty(item.ItemBOM))
|
||||
@if (!string.IsNullOrEmpty(item.ItemBOM))
|
||||
{
|
||||
<button class="btn btn-sm btn-info" title="cambio materiali assegnati" @onclick="() => DoSwapMat(item)"><i class="fa-solid fa-arrow-right-arrow-left"></i></button>
|
||||
<button class="btn btn-sm btn-info" title="Cambio materiali assegnati" @onclick="() => DoSwapMat(item)"><i class="fa-solid fa-arrow-right-arrow-left"></i></button>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
<td class="text-end text-nowrap">
|
||||
<div class="fw-bold" title="Prezzo Finito">
|
||||
@if (item.AwaitPrice)
|
||||
{
|
||||
<span class="text-warning spinner-grow spinner-grow-sm" aria-hidden="true"></span>
|
||||
}
|
||||
@($"{item.TotalPrice:C2}")
|
||||
</div>
|
||||
<div class="small text-secondary" title="RockBottom Price">(@item.TotalCost.ToString("C2"))</div>
|
||||
</td>
|
||||
<td class="text-end text-nowrap" title="Margine / Sconto MAX applicabile">
|
||||
@item.MaxDiscount.ToString("P2")
|
||||
</td>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<td>
|
||||
@if (CurrEditMode == EditMode.RecData && EditRecord != null && EditRecord.OfferRowID == item.OfferRowID)
|
||||
{
|
||||
<button class="btn btn-sm btn-warning" title="Annulla Modifiche" @onclick="DoCancel"><i class="fa-solid fa-ban"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-sm btn-danger" title="Eliminazione riga" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash"></i></button>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="table-success">
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<th colspan="4"></th>
|
||||
}
|
||||
else
|
||||
{
|
||||
<th colspan="3"></th>
|
||||
}
|
||||
<th class="text-end">@($"{GrandTotQty:N0}")</th>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<th colspan="2"></th>
|
||||
}
|
||||
else
|
||||
{
|
||||
<th colspan="1"></th>
|
||||
}
|
||||
<th class="text-end">
|
||||
@($"{GrandTotPrice:C2}")
|
||||
|
||||
<div class="small text-secondary" title="RockBottom Price">(@($"{GrandTotCost:C2}"))</div>
|
||||
</th>
|
||||
<th class="text-end">@($"{GrandTotMargin:P2}")</th>
|
||||
@if (DisplayMode == EgwCoreLib.Lux.Core.Enums.DisplayMode.Edit)
|
||||
{
|
||||
<th></th>
|
||||
}
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (showChangeMat && EditBomRecord != null)
|
||||
@if (EditRecord != null && CurrEditMode == EditMode.BOM)
|
||||
{
|
||||
<div class="modal" tabindex="-1" style="display:block; background-color: rgba(10,10,10,.6);" role="dialog">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title fs-4">Cambio Materiali offerta <b>@EditBomRecord.OfferRowUID</b></div>
|
||||
<div class="modal-title fs-4">Cambio Materiali offerta <b>@EditRecord.OfferRowUID</b></div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="ClosePopup">
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,61 +1,348 @@
|
||||
using EgwCoreLib.Lux.Core;
|
||||
using EgwCoreLib.Lux.Core.RestPayload;
|
||||
using EgwCoreLib.Lux.Data;
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using EgwMultiEngineManager.Data;
|
||||
using Lux.UI.Components.Compo.Config;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.EntityFrameworkCore.Storage.Json;
|
||||
using Microsoft.JSInterop;
|
||||
using NLog.LayoutRenderers;
|
||||
using System.Text;
|
||||
using WebWindowComplex;
|
||||
using WebWindowComplex.DTO;
|
||||
using static EgwCoreLib.Lux.Core.Enums;
|
||||
|
||||
namespace Lux.UI.Components.Compo
|
||||
{
|
||||
public partial class OfferRowMan
|
||||
public partial class OfferRowMan : IDisposable
|
||||
{
|
||||
#region Public Enums
|
||||
|
||||
/// <summary>
|
||||
/// modalità modifica riga offerta
|
||||
/// </summary>
|
||||
public enum EditMode
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Dati generici del record
|
||||
/// </summary>
|
||||
RecData,
|
||||
|
||||
/// <summary>
|
||||
/// Struttura serializzata (es JWD)
|
||||
/// </summary>
|
||||
SerStruc,
|
||||
|
||||
/// <summary>
|
||||
/// BOM editing
|
||||
/// </summary>
|
||||
BOM,
|
||||
|
||||
/// <summary>
|
||||
/// File editing (es BTL)
|
||||
/// </summary>
|
||||
File
|
||||
}
|
||||
|
||||
#endregion Public Enums
|
||||
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public OfferModel CurrRecord { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public DisplayMode DisplayMode { get; set; } = DisplayMode.Standard;
|
||||
|
||||
[Parameter]
|
||||
public int OfferID { get; set; } = 0;
|
||||
public EventCallback<bool> EC_Updated { get; set; }
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Dispose sottoscrizione canale
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
DLService.UpdatePipe.EA_NewMessage -= UpdatePipe_EA_NewMessage;
|
||||
DLService.CalcDonePipe.EA_NewMessage -= CalcDonePipe_EA_NewMessage;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
/// <summary>
|
||||
/// Predisposizione valori live SVG/JWD
|
||||
/// </summary>
|
||||
protected LivePayload CurrData = new LivePayload();
|
||||
|
||||
/// <summary>
|
||||
/// Configurazione elenchi anagrafiche
|
||||
/// </summary>
|
||||
protected BaseListPayload SetupList = new BaseListPayload();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected ConfigDataService CDService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IConfiguration Config { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected CalcRequestService CService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Costo totale calcolato x offerta
|
||||
/// </summary>
|
||||
protected double GrandTotCost
|
||||
{
|
||||
get => AllRecords != null && AllRecords.Count > 0 ? AllRecords.Sum(x => x.TotalCost) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Margine medio calcolato x offerta
|
||||
/// </summary>
|
||||
protected 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Importo totale calcolato x offerta
|
||||
/// </summary>
|
||||
protected double GrandTotPrice
|
||||
{
|
||||
get => AllRecords != null && AllRecords.Count > 0 ? AllRecords.Sum(x => x.TotalPrice) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Num totale obj calcolato x offerta
|
||||
/// </summary>
|
||||
protected double GrandTotQty
|
||||
{
|
||||
get => AllRecords != null && AllRecords.Count > 0 ? AllRecords.Sum(x => x.Qty) : 0;
|
||||
}
|
||||
|
||||
[Inject]
|
||||
protected IWebHostEnvironment HostEnv { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected ImageCacheService ICService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// ID Offerta corrente
|
||||
/// </summary>
|
||||
protected int OfferID
|
||||
{
|
||||
get => CurrRecord.OfferID;
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected void ClosePopup()
|
||||
{
|
||||
showChangeMat = false;
|
||||
EditBomRecord = null;
|
||||
CurrEditMode = EditMode.None;
|
||||
EditRecord = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Annullamento modifica
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task DoCancel()
|
||||
{
|
||||
isLoading = true;
|
||||
CurrEditMode = EditMode.None;
|
||||
EditRecord = null;
|
||||
await Task.Delay(20);
|
||||
await DLService.FlushCacheOffersAsync();
|
||||
await Task.Delay(20);
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clona riga richiesta
|
||||
/// </summary>
|
||||
/// <param name="rec2clone"></param>
|
||||
protected async Task DoClone(OfferRowModel rec2clone)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler duplicare la riga corrente?"))
|
||||
return;
|
||||
|
||||
// calcolo indice riga...
|
||||
int numRow = totalCount + 1;
|
||||
OfferRowModel newRec = new OfferRowModel()
|
||||
{
|
||||
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,
|
||||
OfferID = OfferID,
|
||||
OfferRowUID = "",
|
||||
Qty = rec2clone.Qty,
|
||||
RowNum = numRow,
|
||||
SellingItemID = rec2clone.SellingItemID,
|
||||
SerStruct = rec2clone.SerStruct,
|
||||
StepCost = rec2clone.StepCost,
|
||||
StepPrice = rec2clone.StepPrice,
|
||||
};
|
||||
// salvo sul DB
|
||||
await DLService.OffertRowUpsert(newRec);
|
||||
// chiamo update record che non hanno UID x questo ordine
|
||||
var list2fix = await DLService.OffertRowFixUid(OfferID);
|
||||
if (list2fix != null && list2fix.Count > 0)
|
||||
{
|
||||
// rileggo i miei record...
|
||||
await ReloadData();
|
||||
var listCalc = SorListCalc();
|
||||
foreach (var item in listCalc)
|
||||
{
|
||||
// se UID è tra quelli da ricalcolare...
|
||||
if (list2fix.Contains(item.OfferRowUID))
|
||||
{
|
||||
// chiedo BOM e immagine
|
||||
await reqBomUpdate(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eliminazione riga offerta
|
||||
/// </summary>
|
||||
/// <param name="rec2del"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task DoDelete(OfferRowModel rec2del)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler eliminare la riga corrente?<br/>Codice: {rec2del.OfferRowUID} | {rec2del.Note} | importo tot: {rec2del.TotalPrice}"))
|
||||
return;
|
||||
|
||||
await DLService.OffertRowDelete(rec2del);
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Va in edit della riga richiesta
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEdit(OfferRowModel curRec)
|
||||
{
|
||||
#if false
|
||||
// preparazione dati da record corrente
|
||||
PrepareWindowData(curRec.SerStruct);
|
||||
// reset prev
|
||||
prevJwd = "";
|
||||
#endif
|
||||
// imposto edit record
|
||||
EditRecord = curRec;
|
||||
/// modalitàedit: gestione valori campi record
|
||||
CurrEditMode = EditMode.RecData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apre editor finestre del record richiesto
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
protected void DoEditJwd(OfferRowModel curRec)
|
||||
{
|
||||
EditRecord = curRec;
|
||||
/// modalitàedit: gestione JWD
|
||||
CurrEditMode = EditMode.SerStruc;
|
||||
// preparazione dati da record corrente
|
||||
PrepareWindowData(EditRecord.SerStruct);
|
||||
// reset prev
|
||||
prevJwd = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salvataggio edit record + reload
|
||||
/// </summary>
|
||||
/// <param name="curRec"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task DoSave(OfferRowModel curRec)
|
||||
{
|
||||
isLoading = true;
|
||||
// salvo record modificato...
|
||||
await DLService.OffertRowUpsert(curRec);
|
||||
// reset
|
||||
CurrEditMode = EditMode.None;
|
||||
EditRecord = null;
|
||||
await DLService.FlushCacheOffersAsync();
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
protected void DoSwapMat(OfferRowModel currRow)
|
||||
{
|
||||
showChangeMat = true;
|
||||
EditBomRecord = currRow;
|
||||
CurrBomList = DLService.OffertGetBomList(EditBomRecord);
|
||||
CurrEditMode = EditMode.BOM;
|
||||
EditRecord = currRow;
|
||||
CurrBomList = DLService.OffertGetBomList(EditRecord);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display fileSize scalato
|
||||
/// </summary>
|
||||
/// <param name="size"></param>
|
||||
/// <returns></returns>
|
||||
protected string fSize(long size)
|
||||
{
|
||||
return EgwCoreLib.Utils.FileHelpers.SizeSuffix(size, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calcolo URL immagine
|
||||
/// </summary>
|
||||
/// <param name="imgUid"></param>
|
||||
/// <param name="env"></param>
|
||||
/// <returns></returns>
|
||||
protected string imgUrl(string imgUid, string env)
|
||||
{
|
||||
// cast string su env..
|
||||
@@ -64,10 +351,110 @@ namespace Lux.UI.Components.Compo
|
||||
return ICService.ImageUrl($"{apiUrl}/{imgBasePath}", false, imgUid, envir);
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
/// <summary>
|
||||
/// Forza parametri general selezionati nell'offerta
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task OfferForceParameters()
|
||||
{
|
||||
apiUrl = Config.GetValue<string>("ServerConf:Prog.ApiUrl") ?? "";
|
||||
imgBasePath = Config.GetValue<string>("ServerConf:ImageBaseUrl") ?? "";
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler impostare i parametri selezionati per l'offerta?"))
|
||||
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 DLService.OffertUpdateAwaitState(item.OfferRowID, 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 DLService.OffertRowUpdateSerStruct(item.OfferRowID, newSerStruct);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
// verifica preliminare UID
|
||||
await DLService.OffertRowFixUid(OfferID);
|
||||
|
||||
// ricalcolo di tutte le BOM e relativi prezzi...
|
||||
foreach (var item in listCalc)
|
||||
{
|
||||
// chiedo BOM e immagine
|
||||
await reqBomUpdate(item);
|
||||
}
|
||||
|
||||
//await DoRecalcOffer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiornamento costing completo:
|
||||
/// - verifica UID
|
||||
/// - ricalcolo BOM
|
||||
/// - update prezzi
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task OfferUpdateAllCosting()
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler ricalcolare/validare in toto l'offerta?"))
|
||||
return;
|
||||
|
||||
// metto a waiting tutte le righe con bom...
|
||||
var listCalc = SorListCalc();
|
||||
foreach (var item in listCalc)
|
||||
{
|
||||
await DLService.OffertUpdateAwaitState(item.OfferRowID, true, true);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
// verifica preliminare UID
|
||||
await DLService.OffertRowFixUid(OfferID);
|
||||
|
||||
// fixme todo da riverificare con calcolo BOM funzionante
|
||||
#if false
|
||||
// rileggo i record...
|
||||
await ReloadData();
|
||||
#endif
|
||||
// ricalcolo di tutte le BOM e relativi prezzi...
|
||||
foreach (var item in listCalc)
|
||||
{
|
||||
// chiedo BOM e immagine
|
||||
await reqBomUpdate(item);
|
||||
}
|
||||
#if false
|
||||
await DoRecalcOffer();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica e ricalcolo dei prezzi degli items nell'offerta
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task OfferUpdatePrices()
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler ricalcolare a costi correnti offerta?"))
|
||||
return;
|
||||
|
||||
await DoRecalcOffer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// init obj
|
||||
/// </summary>
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ConfInit();
|
||||
prevJwd = "";
|
||||
await ReloadBaseList();
|
||||
DLService.UpdatePipe.EA_NewMessage += UpdatePipe_EA_NewMessage;
|
||||
DLService.CalcDonePipe.EA_NewMessage += CalcDonePipe_EA_NewMessage;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
@@ -76,30 +463,82 @@ namespace Lux.UI.Components.Compo
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
protected async Task RecalcOffer()
|
||||
/// <summary>
|
||||
/// Lancia la richiesta di ricaolo della BOM dal JWD (o equivalente)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task RequestBom(OfferRowModel currRec)
|
||||
{
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler ricalcolare importi offerta?"))
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler ricalcolare la BOM?"))
|
||||
return;
|
||||
|
||||
await DoRecalcOffer();
|
||||
await reqBomUpdate(currRec);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Css di verifica riga selezionata
|
||||
/// </summary>
|
||||
/// <param name="selRow"></param>
|
||||
/// <returns></returns>
|
||||
protected string RowClass(OfferRowModel selRow)
|
||||
{
|
||||
return EditRecord != null && EditRecord.OfferRowID == selRow.OfferRowID ? "table-info" : "";
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private List<GenValueModel> AllColors = new();
|
||||
|
||||
private List<EnvirParamModel> AllConfEnvir = new();
|
||||
|
||||
private List<GlassModel> AllConfGlass = new();
|
||||
|
||||
private List<HardwareModel> AllConfHardware = new();
|
||||
|
||||
private List<ProfileModel> AllConfProfile = new();
|
||||
|
||||
private List<WoodModel> AllConfWood = new();
|
||||
|
||||
private List<OfferRowModel> AllRecords = new List<OfferRowModel>();
|
||||
|
||||
private string apiUrl = "";
|
||||
|
||||
private List<string> AvailColorMaterialList = new List<string>();
|
||||
|
||||
private List<string> AvailFamilyHardwareList = new List<string>();
|
||||
|
||||
private List<string> AvailGlassList = new List<string>();
|
||||
|
||||
private List<Egw.Window.Data.Hardware> AvailHardwareList = new();
|
||||
|
||||
private List<string> AvailMaterialList = new List<string>();
|
||||
|
||||
private List<string> AvailProfileList = new List<string>();
|
||||
|
||||
private string calcTag = "calc";
|
||||
|
||||
private List<BomItemDTO>? CurrBomList = null;
|
||||
|
||||
/// <summary>
|
||||
/// Modalità editint attiva
|
||||
/// </summary>
|
||||
private EditMode CurrEditMode = EditMode.None;
|
||||
|
||||
private int currPage = 1;
|
||||
|
||||
private OfferRowModel? EditBomRecord = null;
|
||||
private string currSvg = "";
|
||||
|
||||
/// <summary>
|
||||
/// Record in Edit corrente
|
||||
/// </summary>
|
||||
private OfferRowModel? EditRecord = null;
|
||||
|
||||
private string genBasePath = "generic";
|
||||
|
||||
private string GenericBasePath = "";
|
||||
|
||||
private string imgBasePath = "";
|
||||
|
||||
private bool isLoading = false;
|
||||
@@ -108,7 +547,22 @@ namespace Lux.UI.Components.Compo
|
||||
|
||||
private int numRecord = 10;
|
||||
|
||||
private bool showChangeMat = false;
|
||||
/// <summary>
|
||||
/// Versione originale (pre edit)
|
||||
/// </summary>
|
||||
private string origJwd = "";
|
||||
|
||||
/// <summary>
|
||||
/// Versione precedente JWD x test e confronto
|
||||
/// </summary>
|
||||
private string prevJwd = "";
|
||||
|
||||
/// <summary>
|
||||
/// Dizionario richieste
|
||||
/// </summary>
|
||||
private Dictionary<string, string> reqDict = new Dictionary<string, string>();
|
||||
|
||||
private string subChannel = "";
|
||||
|
||||
private int totalCount = 0;
|
||||
|
||||
@@ -116,14 +570,184 @@ namespace Lux.UI.Components.Compo
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Ricevuto SVG, se è il mio lo aggiorno...
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private async void CalcDonePipe_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($"{subChannel}:{EditRecord.OfferRowUID}"))
|
||||
{
|
||||
currSvg = currArgs.newMessage;
|
||||
// salvo in live data...
|
||||
CurrData.SvgPreview = currSvg;
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chiude edit andando eventualmente a salvare
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private async Task CloseEdit(bool doSave)
|
||||
{
|
||||
// ...se ho editing
|
||||
if (EditRecord != null)
|
||||
{
|
||||
bool updateBom = false;
|
||||
// SE richiesto salvataggio...
|
||||
if (doSave)
|
||||
{
|
||||
// salvo su DB!
|
||||
await DLService.OffertRowUpdateSerStruct(EditRecord.OfferRowID, 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("Jwd"))
|
||||
{
|
||||
reqDict["Jwd"] = 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.OfferRowUID}", calcRequestDTO);
|
||||
}
|
||||
EditRecord = null;
|
||||
CurrEditMode = EditMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfInit()
|
||||
{
|
||||
apiUrl = Config.GetValue<string>("ServerConf:Prog.ApiUrl") ?? "";
|
||||
imgBasePath = Config.GetValue<string>("ServerConf:ImageBaseUrl") ?? "";
|
||||
GenericBasePath = Config.GetValue<string>("ServerConf:GenericBaseUrl") ?? "";
|
||||
calcTag = Config.GetValue<string>("ServerConf:CalcTag") ?? "calc";
|
||||
subChannel = Config.GetValue<string>("ServerConf:SvgChannel") ?? "";
|
||||
}
|
||||
|
||||
private async Task DoRecalcOffer()
|
||||
{
|
||||
isLoading = true;
|
||||
// ciclo sulle righe...
|
||||
await setAwaitPrice(true, false);
|
||||
await Task.Delay(50);
|
||||
await DLService.OffertUpdateCost(OfferID);
|
||||
await Task.Delay(50);
|
||||
await setAwaitPrice(false, true);
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
isLoading = false;
|
||||
await EC_Updated.InvokeAsync(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Svuota cache corrente + rilegge dati
|
||||
/// </summary>
|
||||
private async Task ForceReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
CurrEditMode = EditMode.None;
|
||||
EditRecord = null;
|
||||
await Task.Delay(20);
|
||||
await DLService.FlushCacheOffersAsync();
|
||||
await Task.Delay(20);
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preparazione dati x componente edit JWD
|
||||
/// </summary>
|
||||
/// <param name="currJwd"></param>
|
||||
private void PrepareWindowData(string currJwd)
|
||||
{
|
||||
// preparo conf oggetti x controllo
|
||||
SetupList = SetupList = new BaseListPayload()
|
||||
{
|
||||
ColorMaterial = AvailColorMaterialList,
|
||||
FamilyHardware = AvailFamilyHardwareList,
|
||||
Glass = AvailGlassList,
|
||||
Hardware = AvailHardwareList,
|
||||
Material = AvailMaterialList,
|
||||
Profile = AvailProfileList,
|
||||
TemplateDTO = null
|
||||
};
|
||||
CurrData = new LivePayload()
|
||||
{
|
||||
CurrJwd = currJwd,
|
||||
SvgPreview = currSvg
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// init classi configurazione
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task ReloadBaseList()
|
||||
{
|
||||
// lettura config setup varie da DB/Cache Redis
|
||||
AllConfEnvir = await DLService.ConfEnvirParamGetAllAsync();
|
||||
AllConfGlass = await DLService.ConfGlassGetAllAsync();
|
||||
var rawHw = CDService.ElencoHw(EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW, "HW.AGB");
|
||||
// hw filtro solo validi...
|
||||
AllConfHardware = rawHw
|
||||
.Where(x => !x.FamilyName.Equals(x.Description, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
AllConfProfile = await DLService.ConfProfileGetAllAsync();
|
||||
AllConfWood = await DLService.ConfWoodGetAllAsync();
|
||||
AllColors = await DLService.GenValGetFiltAsync("WoodCol");
|
||||
// conversione tipi
|
||||
AvailGlassList = AllConfGlass
|
||||
.Select(x => x.Description)
|
||||
.ToList();
|
||||
AvailProfileList = AllConfProfile
|
||||
.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.Ordinal)
|
||||
.Select(x => x.ValString)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -139,22 +763,174 @@ namespace Lux.UI.Components.Compo
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// salva nel record corrente la BOM aggiornata e poi ricalcola importo...
|
||||
/// Effettua vera richiesta della BOM
|
||||
/// </summary>
|
||||
/// <param name="currRec"></param>
|
||||
/// <returns></returns>
|
||||
private async Task reqBomUpdate(OfferRowModel currRec)
|
||||
{
|
||||
// salvo richiesta BOM su record
|
||||
currRec.AwaitBom = true;
|
||||
currRec.AwaitPrice = true;
|
||||
await DLService.OffertUpdateAwaitState(currRec.OfferRowID, true, true);
|
||||
|
||||
// preparo la domanda serializzata
|
||||
Dictionary<string, string> DictExec = new Dictionary<string, string>();
|
||||
// verifico parametri da conf envir...
|
||||
var envRec = AllConfEnvir.FirstOrDefault(x => x.EnvirID == currRec.Envir);
|
||||
string serKey = envRec != null ? envRec.SerStrucKey : "Jwd";
|
||||
// cablata la BOM
|
||||
DictExec.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.BOM}");
|
||||
//DictExec.Add("Mode", "2");
|
||||
// UID cablato x ora...
|
||||
DictExec.Add("UID", currRec.OfferRowUID);
|
||||
DictExec.Add(serKey, currRec.SerStruct);
|
||||
|
||||
CalcRequestDTO req = new CalcRequestDTO()
|
||||
{
|
||||
EnvType = currRec.Envir,
|
||||
//EnvType = currEnv,
|
||||
DictExec = DictExec
|
||||
};
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
// chiamo la chiamata POST alla API, che manda la richiesta via REDIS
|
||||
await CService.CallRestPost($"{apiUrl}/{genBasePath}", $"{calcTag}/{currRec.OfferRowUID}", req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue salvataggio del file ricevuto
|
||||
/// </summary>
|
||||
/// <param name="secureName">Nome secure da impiegare</param>
|
||||
/// <param name="content">Contenuto file</param>
|
||||
private bool saveFileContent(string folderPath, string secureName, string content)
|
||||
{
|
||||
bool answ = false;
|
||||
if (!string.IsNullOrEmpty(folderPath))
|
||||
{
|
||||
// calcolo path file...
|
||||
string filePath = Path.Combine("unsafe_uploads", folderPath, secureName);
|
||||
File.WriteAllText(filePath, content);
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salvataggio del JWD aggiornato nella mia riga di offerta
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
private async void SaveJWD(Dictionary<string, string> args)
|
||||
{
|
||||
// ...se ho editing
|
||||
if (EditRecord != null)
|
||||
{
|
||||
// SE contiene il mio Jwd...
|
||||
if (args.ContainsKey("Jwd"))
|
||||
{
|
||||
reqDict = args;
|
||||
string serStruct = reqDict["Jwd"];
|
||||
// controllo SE variato...
|
||||
if (!prevJwd.Equals(serStruct))
|
||||
{
|
||||
// aggiorno val prev
|
||||
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.OfferRowUID}", calcRequestDTO);
|
||||
#if false
|
||||
// salvo su DB!
|
||||
await DLService.OffertRowUpdateSerStruct(EditRecord.OfferRowID, serStruct);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task setAwaitPrice(bool awaitPrice, bool flushCache)
|
||||
{
|
||||
foreach (var item in AllRecords)
|
||||
{
|
||||
await DLService.OffertUpdateAwaitState(item.OfferRowID, false, awaitPrice, flushCache);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco SalesOfferRows calcolabili:
|
||||
/// - contengono serializzazione come JWD
|
||||
/// - contengono file come BTL
|
||||
/// </summary>
|
||||
private List<OfferRowModel> 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<OfferRowModel>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle visibilità modifica file indicando ID della OfferRow corrente (o zero se deselect)
|
||||
/// </summary>
|
||||
private void ToggleFileEdit(OfferRowModel? currRec)
|
||||
{
|
||||
CurrEditMode = currRec == null ? EditMode.None : EditMode.File;
|
||||
EditRecord = currRec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salva nel record corrente la BOM aggiornata e poi ricalcola importo...
|
||||
/// </summary>
|
||||
/// <param name="newBomList"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private async void UpdateBom(List<BomItemDTO> newBomList)
|
||||
{
|
||||
if (EditBomRecord != null)
|
||||
if (EditRecord != null)
|
||||
{
|
||||
// salvo BOM nel record corrente...
|
||||
bool fatto = await DLService.OffertRowUpdateBom(EditBomRecord.OfferRowID, newBomList);
|
||||
bool fatto = await DLService.OffertRowUpdateBom(EditRecord.OfferRowID, newBomList);
|
||||
// ricalcolo offerta completa
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Task verifica update ricevuti
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private async void UpdatePipe_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 aprte dei record correnti...
|
||||
var recFound = AllRecords.Any(x => x.OfferRowUID == currArgs.newMessage);
|
||||
if (recFound)
|
||||
{
|
||||
isLoading = true;
|
||||
await Task.Delay(10);
|
||||
#if false
|
||||
if (currArgs.msgUid.Equals($"{subChannel}:{windowUid}"))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
// se si tratta dell'UID corrente --> fa update
|
||||
await DoRecalcOffer();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtro e paginazione
|
||||
/// </summary>
|
||||
@@ -162,12 +938,59 @@ namespace Lux.UI.Components.Compo
|
||||
{
|
||||
// fix paginazione
|
||||
ListRecords = AllRecords
|
||||
.OrderBy(x => x.RowNum)
|
||||
.Skip(numRecord * (currPage - 1))
|
||||
.Take(numRecord)
|
||||
.ToList();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue lettura file + invio richiesta specifica
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
private async Task UploadFile(InputFileChangeEventArgs e)
|
||||
{
|
||||
if (EditRecord != null)
|
||||
{
|
||||
// init dizionari arg richiesta update
|
||||
Dictionary<string, string> fileArgs = new Dictionary<string, string>();
|
||||
|
||||
// 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 DLService.OffertRowUpdateFileData(EditRecord);
|
||||
|
||||
// parametri richiesta
|
||||
fileArgs.Add("Mode", $"{(int)Egw.Window.Data.Enums.QuestionModes.PREVIEW}");
|
||||
fileArgs.Add("Btl", rawContent);
|
||||
// invio!
|
||||
CalcRequestDTO calcRequestDTO = new CalcRequestDTO();
|
||||
calcRequestDTO.EnvType = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM;
|
||||
calcRequestDTO.DictExec = fileArgs;
|
||||
await ICService.CallRestPost($"{apiUrl}/{GenericBasePath}", $"{calcTag}/{EditRecord.OfferRowUID}", calcRequestDTO);
|
||||
|
||||
#if false
|
||||
// salvo in locale il file: SISTEMARE PERMESSI
|
||||
saveFileContent(EditFileRecord.OfferRowUID, trustedFileName, rawContent);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -39,19 +39,35 @@
|
||||
<span class="fa-solid fa-book px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Articoli</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="JobRoute">
|
||||
<span class="fa-solid fa-route px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Cicli</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Offers">
|
||||
<span class="fa-solid fa-cart-shopping px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Offerte</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="GenList">
|
||||
<span class="fa-solid fa-list-check px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Anagrafiche</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="ConfList">
|
||||
<span class="fa-solid fa-list-check px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Configurazioni</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
@* <div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="bi bi-list-ol px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Counter</span>
|
||||
</NavLink>
|
||||
</div> *@
|
||||
|
||||
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="scratch">
|
||||
<span class="bi bi-cloud-moon px-2 fs-4" aria-hidden="true"></span> <span class="@hideText">Scratch</span>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
@page "/ConfList"
|
||||
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<div class=" d-flex justify-content-between">
|
||||
<div class="px-0 fs-3">
|
||||
<b>Configurazioni</b>
|
||||
</div>
|
||||
@* <div class="px-0 d-flex justify-content-between">
|
||||
<div class="px-1">
|
||||
<div class="input-group input-group-sm" title="ricerca">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" @bind="@SearchVal">
|
||||
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div> *@
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body py-1">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 g-2" style="min-height: 24rem;">
|
||||
<ProfileMan></ProfileMan>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 g-2" style="min-height: 24rem;">
|
||||
<WoodMan></WoodMan>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 g-2" style="min-height: 24rem;">
|
||||
<GlassMan></GlassMan>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 g-2" style="min-height: 24rem;">
|
||||
<HardwareMan></HardwareMan>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="small">NB: le configurazioni possono essere RW o Read-Only (ricevute dal sistema CAD/CAM di calcolo)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Lux.UI.Components.Pages
|
||||
{
|
||||
public partial class ConfList
|
||||
{
|
||||
#region Protected Properties
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => searchVal;
|
||||
set
|
||||
{
|
||||
isLoading = true;
|
||||
searchVal = value;
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected void ResetSearch()
|
||||
{
|
||||
SearchVal = "";
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool isLoading = false;
|
||||
private string searchVal = "";
|
||||
|
||||
#endregion Private Fields
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
@page "/GenList"
|
||||
|
||||
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<div class=" d-flex justify-content-between">
|
||||
<div class="px-0 fs-3">
|
||||
<b>Anagrafiche Generiche</b>
|
||||
</div>
|
||||
<div class="px-0 d-flex justify-content-between">
|
||||
<div class="px-1">
|
||||
<div class="input-group input-group-sm" title="ricerca">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" class="form-control" @bind="@SearchVal">
|
||||
<button class="btn btn-outline-secondary" @onclick="ResetSearch"><i class="fas fa-ban"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
@if (isLoading)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="col-6">
|
||||
<GenClassMan ListGenClass="ListGenClass" EC_Selected="SaveSel" EC_Updated="() => ForceReloadAsync()"></GenClassMan>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@if (!string.IsNullOrEmpty(CurrFilt.SelCodGroup))
|
||||
{
|
||||
<GenValMan SelFilt="CurrFilt" ListGenClass="ListGenClass"></GenValMan>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,95 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Lux.UI.Components.Compo;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lux.UI.Components.Pages
|
||||
{
|
||||
public partial class GenList
|
||||
{
|
||||
#region Protected Fields
|
||||
|
||||
protected List<GenClassModel> ListGenClass = new List<GenClassModel>();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected GenValMan.FiltSelect CurrFilt { get; set; } = new GenValMan.FiltSelect();
|
||||
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
protected string SearchVal
|
||||
{
|
||||
get => CurrFilt.SearchVal;
|
||||
set
|
||||
{
|
||||
isLoading = true;
|
||||
CurrFilt.SearchVal = value;
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected string SelCodGroup
|
||||
{
|
||||
get => CurrFilt.SelCodGroup;
|
||||
set
|
||||
{
|
||||
if (CurrFilt.SelCodGroup != value)
|
||||
{
|
||||
isLoading = true;
|
||||
CurrFilt.SelCodGroup = value;
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
isLoading = true;
|
||||
await ReloadBaseData();
|
||||
}
|
||||
|
||||
protected void ResetSearch()
|
||||
{
|
||||
SearchVal = "";
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private ItemModel? editRecord = null;
|
||||
private bool isLoading = false;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task ForceReloadAsync()
|
||||
{
|
||||
await ReloadBaseData();
|
||||
}
|
||||
|
||||
private async Task ReloadBaseData()
|
||||
{
|
||||
isLoading = true;
|
||||
ListGenClass = await DLService.GenClassGetAllAsync();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
private void SaveSel(string codGroup)
|
||||
{
|
||||
SelCodGroup = codGroup;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,38 @@
|
||||
@page "/"
|
||||
@page "/Home"
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
<PageTitle>LUX</PageTitle>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
<div class="alert alert-secondary shadow">
|
||||
<h1>LUX Wood MES</h1>
|
||||
Development Version
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="col-4">
|
||||
<ul class="list-group mb-2 shadow">
|
||||
<li class="list-group-item bg-primary text-light">Sezioni Attive</li>
|
||||
<li class="list-group-item">Anagrafiche generiche</li>
|
||||
<li class="list-group-item">Articoli</li>
|
||||
<li class="list-group-item">Offerte e ricalcoli</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<ul class="list-group mb-2 shadow">
|
||||
<li class="list-group-item bg-primary bg-opacity-50">Sezioni in sviluppo</li>
|
||||
<li class="list-group-item">Anagrafiche Configurazioni (RO)</li>
|
||||
<li class="list-group-item">Configuratore</li>
|
||||
<li class="list-group-item">Cicli</li>
|
||||
<li class="list-group-item">Ordini</li>
|
||||
<li class="list-group-item">Sistema Costing</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<ul class="list-group mb-2 shadow">
|
||||
<li class="list-group-item bg-primary bg-opacity-25">Sezioni TBD</li>
|
||||
<li class="list-group-item">Pianificazione Produzione</li>
|
||||
<li class="list-group-item">Rilievo produzione</li>
|
||||
<li class="list-group-item">Consuntivazione</li>
|
||||
<li class="list-group-item">Stampe</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,4 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using Lux.UI.Components.Compo;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -29,9 +29,6 @@ namespace Lux.UI.Components.Pages
|
||||
isLoading = true;
|
||||
CurrFilt.SearchVal = value;
|
||||
isLoading = false;
|
||||
if (CurrFilt.SearchVal != value)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user