Files
lux/EgwCoreLib.Lux.Data/Controllers/LuxController.cs
T
2025-10-02 15:48:48 +02:00

1311 lines
54 KiB
C#

using EgwCoreLib.Lux.Core.RestPayload;
using EgwCoreLib.Lux.Data.DbModel.Utils;
using EgwCoreLib.Lux.Data.DbModel.Sales;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using NLog.LayoutRenderers;
using static EgwCoreLib.Lux.Core.Enums;
using EgwCoreLib.Lux.Data.DbModel.Items;
using EgwCoreLib.Lux.Data.DbModel.Config;
namespace EgwCoreLib.Lux.Data.Controllers
{
internal class LuxController
{
// manca costruttore parametrico contoller...
#region Internal Methods
/// <summary>
/// Elenco completo Config Glass
/// </summary>
/// <returns></returns>
internal async Task<List<GlassModel>> ConfGlassGetAllAsync()
{
List<GlassModel> dbResult = new List<GlassModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetConfGlass
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ConfGlassGetAllAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco completo Config Profile
/// </summary>
/// <returns></returns>
internal async Task<List<ProfileModel>> ConfProfileGetAllAsync()
{
List<ProfileModel> dbResult = new List<ProfileModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetConfProfile
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ConfProfileGetAllAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco completo Config Wood
/// </summary>
/// <returns></returns>
internal async Task<List<WoodModel>> ConfWoodGetAllAsync()
{
List<WoodModel> dbResult = new List<WoodModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetConfWood
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ConfWoodGetAllAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco completo Customers da DB
/// </summary>
/// <returns></returns>
internal List<CustomerModel> CustomersGetAll()
{
List<CustomerModel> dbResult = new List<CustomerModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetCustomer
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante CustomersGetAll{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco completo Dealers da DB
/// </summary>
/// <returns></returns>
internal List<DealerModel> DealersGetAll()
{
List<DealerModel> dbResult = new List<DealerModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetDealer
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante DealersGetAll{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Esegue eliminazione
/// </summary>
/// <param name="rec2del"></param>
/// <returns></returns>
internal async Task<bool> GenClassDeleteAsync(GenClassModel rec2del)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var dbResult = dbCtx
.DbSetGenClass
.Where(x => x.ClassCod == rec2del.ClassCod)
.FirstOrDefault();
var numChild = dbCtx
.DbSetGenVal
.Count(x => x.ClassCod == rec2del.ClassCod);
// se trovato e NON HA record child --> elimino
if (dbResult != null && numChild == 0)
{
dbCtx.DbSetGenClass.Remove(dbResult);
await dbCtx.SaveChangesAsync();
}
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenClassDeleteAsync{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Elenco completo GenClass
/// </summary>
/// <returns></returns>
internal async Task<List<GenClassModel>> GenClassGetAllAsync()
{
List<GenClassModel> dbResult = new List<GenClassModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetGenClass
.Include(o => o.GenValNav)
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenClassGetAllAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Upsert record GenClass
/// </summary>
/// <param name="upsRec"></param>
/// <returns></returns>
internal async Task<bool> GenClassUpsertAsync(GenClassModel upsRec)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var currRec = dbCtx
.DbSetGenClass
.Where(x => x.ClassCod == upsRec.ClassCod)
.FirstOrDefault();
// se trovato --> aggiorno
if (currRec != null)
{
currRec.Description = upsRec.Description;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
// se mancasse --> aggiungo
else
{
dbCtx.DbSetGenClass.Add(upsRec);
}
// salvo...
int numAct = await dbCtx.SaveChangesAsync();
answ = numAct > 0;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenClassUpsertAsync{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Esegue eliminazione
/// </summary>
/// <param name="rec2del"></param>
/// <returns></returns>
internal async Task<bool> GenValDeleteAsync(GenValueModel rec2del)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var dbResult = dbCtx
.DbSetGenVal
.Where(x => x.GenValID == rec2del.GenValID)
.FirstOrDefault();
// se trovato --> elimino e sposto i rimanenti...
if (dbResult != null)
{
// modifico record successivi...
var list2Move = dbCtx
.DbSetGenVal
.Where(x => x.ClassCod == rec2del.ClassCod && x.Ordinal > dbResult.Ordinal)
.ToList();
foreach (var item in list2Move)
{
item.Ordinal--;
dbCtx.Entry(item).State = EntityState.Modified;
}
// elimino
dbCtx.DbSetGenVal.Remove(dbResult);
// salvo tutto
await dbCtx.SaveChangesAsync();
}
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenValDeleteAsync{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Elenco valori x classe richiesta
/// </summary>
/// <param name="codClass"></param>
/// <returns></returns>
internal async Task<List<GenValueModel>> GenValGetFiltAsync(string codClass)
{
List<GenValueModel> dbResult = new List<GenValueModel>();
if (!string.IsNullOrEmpty(codClass))
{
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetGenVal
.Where(x => x.ClassCod == codClass)
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenValGetFiltAsync{Environment.NewLine}{exc}");
}
}
}
return dbResult;
}
/// <summary>
/// Esegue spostamento nell'ordinamento relativo alla classe
/// NB: verifica spostamento sia ammissibile: se primo rec non "sale", se ultimo non "scende"...
/// </summary>
/// <param name="selRec"></param>
/// <param name="moveUp"></param>
/// <returns></returns>
internal async Task<bool> GenValMoveAsync(GenValueModel selRec, bool moveUp)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var currRec = dbCtx
.DbSetGenVal
.Where(x => x.GenValID == selRec.GenValID)
.FirstOrDefault();
if (currRec != null)
{
// recupero info del num rec del suo gruppo
int numRec = dbCtx
.DbSetGenVal
.Count(x => x.ClassCod == selRec.ClassCod);
// verifico NON sia primo/ultimo...
bool canMove = false;
int newPos = moveUp ? currRec.Ordinal - 1 : currRec.Ordinal + 1;
if (moveUp)
{
canMove = newPos > 0;
}
else
{
canMove = newPos <= numRec;
}
// se abilitato --> aggiorno i 2 record...
if (canMove)
{
var otherRec = dbCtx
.DbSetGenVal
.Where(x => x.ClassCod == selRec.ClassCod && x.Ordinal == newPos)
.FirstOrDefault();
if (otherRec != null)
{
otherRec.Ordinal = currRec.Ordinal;
dbCtx.Entry(otherRec).State = EntityState.Modified;
currRec.Ordinal = newPos;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
// salvo...
int numAct = await dbCtx.SaveChangesAsync();
answ = numAct > 0;
}
}
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenValMoveAsync{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Esegue Upsert del record ricevuto
/// </summary>
/// <param name="upsRec"></param>
/// <returns></returns>
internal async Task<bool> GenValUpsertAsync(GenValueModel upsRec)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var currRec = dbCtx
.DbSetGenVal
.Where(x => x.GenValID == upsRec.GenValID)
.FirstOrDefault();
// se trovato --> aggiorno
if (currRec != null)
{
currRec.ValString = upsRec.ValString;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
// se mancasse --> aggiungo
else
{
dbCtx.DbSetGenVal.Add(upsRec);
}
// salvo...
int numAct = await dbCtx.SaveChangesAsync();
answ = numAct > 0;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante GenValUpsertAsync{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Eliminazione record item
/// </summary>
/// <param name="rec2del"></param>
/// <returns></returns>
internal async Task<bool> ItemDeleteAsync(ItemModel rec2del)
{
bool result = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var dbResult = await dbCtx
.DbSetItem
.Where(x => x.ItemID == rec2del.ItemID)
.FirstOrDefaultAsync();
if (dbResult != null)
{
dbCtx.DbSetItem.Remove(dbResult);
await dbCtx.SaveChangesAsync();
}
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemDeleteAsync{Environment.NewLine}{exc}");
}
}
return result;
}
/// <summary>
/// Elenco completo Items
/// </summary>
/// <returns></returns>
internal List<ItemModel> ItemGetAll()
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetAll{Environment.NewLine}{exc}");
}
}
return dbResult;
}
#if false
/// <summary>
/// Elenco item Child da ID Parent (per sostituzione)
/// </summary>
/// <param name="ItemIdParent">ID parent (valido quindi >0)</param>
/// <returns></returns>
internal List<ItemModel> ItemGetChild(int ItemIdParent)
{
List<ItemModel> dbResult = new List<ItemModel>();
if (ItemIdParent > 0)
{
//using (DataLayerContext dbCtx = new DataLayerContext(configuration))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.Where(x => x.ItemID == ItemIdParent || x.ItemIDParent == ItemIdParent)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetChild{Environment.NewLine}{exc}");
}
}
}
return dbResult;
}
#endif
/// <summary>
/// Elenco item alternativi da ID di un record (per sostituzione)
/// </summary>
/// <param name="ItemId">ID item corrente (valido quindi >0)</param>
/// <returns></returns>
internal List<ItemModel> ItemGetAlt(int ItemId)
{
List<ItemModel> dbResult = new List<ItemModel>();
if (ItemId > 0)
{
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
// cerco singolo record x partire...
var currRec = dbCtx
.DbSetItem
.Where(x => x.ItemID == ItemId)
.FirstOrDefault();
if ((currRec != null))
{
// se è un record che ha parentId > 0 --> cerco da quello record analoghi + parent
if (currRec.ItemIDParent > 0)
{
dbResult = dbCtx
.DbSetItem
.Where(x => x.ItemID == currRec.ItemIDParent || x.ItemIDParent == currRec.ItemIDParent)
.ToList();
}
// altrimenti cerco child collegati
else
{
dbResult = dbCtx
.DbSetItem
.Where(x => x.ItemID == currRec.ItemID || x.ItemIDParent == currRec.ItemID)
.ToList();
}
}
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetAlt{Environment.NewLine}{exc}");
}
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca filtro x gruppo/tipo
/// </summary>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <returns></returns>
internal List<ItemModel> ItemGetFilt(string CodGroup, ItemClassType ItemType)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType))
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFilt{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca completa
/// </summary>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <param name="SearchVal"></param>
/// <returns></returns>
internal List<ItemModel> ItemGetFilt(string CodGroup, ItemClassType ItemType, string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType)
&& (string.IsNullOrEmpty(SearchVal) ||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFilt{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca filtro x gruppo/tipo Async
/// </summary>
/// <param name="SearchVal"></param>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <returns></returns>
internal async Task<List<ItemModel>> ItemGetFiltAsync(string CodGroup, ItemClassType ItemType)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType))
.Include(g => g.ItemGroupNav)
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFiltAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca completa Async
/// </summary>
/// <param name="CodGroup"></param>
/// <param name="ItemType"></param>
/// <param name="SearchVal"></param>
/// <returns></returns>
internal async Task<List<ItemModel>> ItemGetFiltAsync(string CodGroup, ItemClassType ItemType, string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup)
&& (ItemType == ItemClassType.ND || x.ItemType == ItemType)
&& (string.IsNullOrEmpty(SearchVal) ||
x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) ||
x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
)
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetFiltAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca
/// </summary>
/// <param name="SearchVal"></param>
/// <returns></returns>
internal List<ItemModel> ItemGetSearch(string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItem
.Where(x => x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetSearch{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco item da ricerca async
/// </summary>
/// <param name="SearchVal"></param>
/// <returns></returns>
internal async Task<List<ItemModel>> ItemGetSearchAsync(string SearchVal)
{
List<ItemModel> dbResult = new List<ItemModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetItem
.Where(x => x.Description.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.ExtItemCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.SupplCode.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase))
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetSearchAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco completo ItemGroup gestiti
/// </summary>
/// <returns></returns>
internal List<ItemGroupModel> ItemGroupGetAll()
{
List<ItemGroupModel> dbResult = new List<ItemGroupModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetItemGroup
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGroupGetAllAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco completo ItemGroup gestiti async
/// </summary>
/// <returns></returns>
internal async Task<List<ItemGroupModel>> ItemGroupGetAllAsync()
{
List<ItemGroupModel> dbResult = new List<ItemGroupModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetItemGroup
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGroupGetAllAsync{Environment.NewLine}{exc}");
}
}
return dbResult;
}
internal bool ItemUpsert(ItemModel newRec)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var currRec = dbCtx
.DbSetItem
.Where(x => x.ItemID == newRec.ItemID)
.FirstOrDefault();
// se trovato --> aggiorno
if (currRec != null)
{
currRec.Description = newRec.Description;
currRec.SupplCode = newRec.SupplCode;
currRec.ItemCode = newRec.ItemCode;
currRec.Cost = newRec.Cost;
currRec.Description = newRec.Description;
currRec.IsService = newRec.IsService;
currRec.Margin = newRec.Margin;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
// se mancasse --> aggiungo
else
{
dbCtx.DbSetItem.Add(newRec);
}
// salvo...
dbCtx.SaveChanges();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemGetSearch{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Inserisce o aggiorna il record
/// </summary>
/// <param name="currRec"></param>
/// <returns></returns>
internal async Task<bool> ItemUpsertAsync(ItemModel currRec)
{
bool result = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var dbResult = await dbCtx
.DbSetItem
.Where(x => x.ItemID == currRec.ItemID)
.FirstOrDefaultAsync();
if (dbResult != null)
{
//dbCtx.DbSetItem.Remove(dbResult);
dbResult.CodGroup = currRec.CodGroup;
dbResult.ItemType = currRec.ItemType;
dbResult.IsService = currRec.IsService;
dbResult.ItemCode = currRec.ItemCode;
dbResult.ExtItemCode = currRec.ExtItemCode;
dbResult.Cost = currRec.Cost;
dbResult.Margin = currRec.Margin;
dbResult.Description = currRec.Description;
dbResult.QtyMin = currRec.QtyMin;
dbResult.QtyMax = currRec.QtyMax;
dbResult.UM = currRec.UM;
dbCtx.Entry(dbResult).State = EntityState.Modified;
}
else
{
dbCtx.DbSetItem.Add(currRec);
}
await dbCtx.SaveChangesAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemUpsertAsync{Environment.NewLine}{exc}");
}
}
return result;
}
/// <summary>
/// Upsert item ricevuti da BOM calcolata
/// </summary>
/// <param name="bomList"></param>
/// <returns></returns>
internal bool ItemUpsertFromBom(List<BomItemDTO> bomList)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
// prendo solo elementi a prezzo 0 da salvare sul DB
var item2save = bomList
.Where(x => x.Price == 0)
.ToList();
// ciclo x ogni elemento della BOM, cercando x gruppo e ExtItemCode
foreach (var item in item2save)
{
var currRec = dbCtx
.DbSetItem
.Where(x => x.CodGroup == item.ClassCode && x.ExtItemCode == item.ItemCode)
.FirstOrDefault();
// se nullo --> lo devo inserire!!!
if (currRec == null)
{
ItemModel newRec = new ItemModel()
{
CodGroup = item.ClassCode,
ItemType = Core.Enums.ItemClassType.Bom,
IsService = false,
// da calcolare meglio x gruppo
ItemCode = 0,
ExtItemCode = item.ItemCode,
SupplCode = "BOM ITEM",
Description = $"BOM | {item.ClassCode} | {item.ItemCode}",
Cost = 0,
Margin = 0,
QtyMin = 0,
QtyMax = 0,
UM = "#"
};
dbCtx.DbSetItem.Add(newRec);
}
}
// salvo...
dbCtx.SaveChanges();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ItemUpsertFromBom{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Elenco completo offerte da DB
/// </summary>
/// <returns></returns>
internal async Task<List<OfferModel>> OfferGetAll()
{
List<OfferModel> dbResult = new List<OfferModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = await dbCtx
.DbSetOffer
.Include(c => c.CustomerNav)
.Include(d => d.DealerNav)
.Include(o => o.OfferRowNav)
.ToListAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OfferGetAll{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco righe offerta specificata
/// </summary>
/// <param name="OfferID"></param>
/// <returns></returns>
internal List<OfferRowModel> OfferRowGetByOffer(int OfferID)
{
List<OfferRowModel> dbResult = new List<OfferRowModel>();
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetOfferRow
.Where(x => x.OfferID == OfferID)
.Include(s => s.SellingItemNav)
//.Include(d => d.DealerNav)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OfferRowGetByOffer{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Effettua update 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>
/// <returns></returns>
internal async Task<bool> OffertRowUpdateBom(int OfferRowID, List<BomItemDTO> newBomList)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
// recupero riga offerta da aggiornare...
var currRec = dbCtx
.DbSetOfferRow
.Where(x => x.OfferRowID == OfferRowID)
.FirstOrDefault();
// se è valida --> procedo!
if (currRec != null)
{
// recupero l'elenco degli itemGroup gestiti
var itemGroupList = dbCtx
.DbSetItemGroup
.ToList();
// recupero il subset item da BOM / BomAlt...
var bomGenList = dbCtx
.DbSetItem
.Where(x => (x.ItemType == Core.Enums.ItemClassType.Bom || x.ItemType == Core.Enums.ItemClassType.BomAlt))
.ToList();
// calcolo il NUOVO costo e lo aggiorno...
double totCost = 0;
double totPrice = 0;
int numGroupOk = 0;
int numItemOk = 0;
int numElems = newBomList.Count;
// validazione e completamento BOM
validateBom(itemGroupList, bomGenList, ref newBomList, null, ref totCost, ref totPrice, ref numGroupOk, ref numItemOk);
// salvo BOM...
string itemBom = JsonConvert.SerializeObject(newBomList);
currRec.ItemBOM = itemBom;
// salvo arrotondato alla 3° decimale
currRec.BomCost = Math.Round(totCost, 3);
currRec.BomPrice = Math.Round(totPrice, 3);
currRec.BomOk = numElems == numGroupOk;
currRec.ItemOk = numElems == numItemOk;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
// salvo modifiche...
await dbCtx.SaveChangesAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OffertRowUpdateBom{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Effettua update dei costi di tutte le righe dell'offerta indicata
/// </summary>
/// <param name="OfferID"></param>
/// <returns></returns>
internal async Task<bool> OffertUpdateCost(int OfferID)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
// recupero righe offerta...
var offRowList = dbCtx
.DbSetOfferRow
.Where(x => x.OfferID == OfferID)
.ToList();
// recupero l'elenco degli itemGroup gestiti
var itemGroupList = dbCtx
.DbSetItemGroup
.ToList();
// recupero il subset item da BOM / BomAlt...
var bomGenList = dbCtx
.DbSetItem
.Where(x => (x.ItemType == Core.Enums.ItemClassType.Bom || x.ItemType == Core.Enums.ItemClassType.BomAlt))
.ToList();
// ciclo!
foreach (var currRec in offRowList)
{
// se contiene qualcosa x BOM...
if (!string.IsNullOrEmpty(currRec.ItemBOM) && currRec.ItemBOM.Length > 2)
{
// deserializzo
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
// se ho trovato elementi...
if (bomList != null)
{
// calcolo il NUOVO costo e lo aggiorno...
double totCost = 0;
double totPrice = 0;
int numGroupOk = 0;
int numItemOk = 0;
int numElems = bomList.Count;
// validazione e completamento BOM
validateBom(itemGroupList, bomGenList, ref bomList, null, ref totCost, ref totPrice, ref numGroupOk, ref numItemOk);
// salvo BOM...
string itemBom = JsonConvert.SerializeObject(bomList);
currRec.ItemBOM = itemBom;
// salvo arrotondato alla 3° decimale
currRec.BomCost = Math.Round(totCost, 3);
currRec.BomPrice = Math.Round(totPrice, 3);
currRec.BomOk = numElems == numGroupOk;
currRec.ItemOk = numElems == numItemOk;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
}
}
// salvo TUTTI i cambiamenti...
await dbCtx.SaveChangesAsync();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OffertUpdateCost{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Esegue upsert del record offerta data la BOM ricevuta
/// </summary>
/// <param name="uID"></param>
/// <param name="bomList"></param>
internal bool OfferUpsertFromBom(string uID, List<BomItemDTO> bomList)
{
bool answ = false;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
var currRec = dbCtx
.DbSetOfferRow
.Where(x => x.OfferRowUID == uID)
.FirstOrDefault();
// se trovato --> salvo BOM e calcolo costi
if (currRec != null)
{
// recupero l'elenco degli itemGroup gestiti
var itemGroupList = dbCtx
.DbSetItemGroup
.ToList();
// recupero il subset item da BOM...
var bomGenList = dbCtx
.DbSetItem
//.Where(x => x.ItemType == Core.Enums.ItemClassType.Bom)
.Where(x => (x.ItemType == Core.Enums.ItemClassType.Bom || x.ItemType == Core.Enums.ItemClassType.BomAlt))
.ToList();
// recupero la BOM list precedente
var bomListPrev = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
// calcolo il NUOVO costo e lo aggiorno...
double totCost = 0;
double totPrice = 0;
int numGroupOk = 0;
int numItemOk = 0;
int numElems = bomList.Count;
// validazione e completamento BOM
validateBom(itemGroupList, bomGenList, ref bomList, bomListPrev, ref totCost, ref totPrice, ref numGroupOk, ref numItemOk);
// salvo BOM...
string itemBom = JsonConvert.SerializeObject(bomList);
currRec.ItemBOM = itemBom;
// salvo arrotondato alla 3° decimale
currRec.BomCost = Math.Round(totCost, 3);
currRec.BomPrice = Math.Round(totPrice, 3);
currRec.BomOk = numElems == numGroupOk;
currRec.ItemOk = numElems == numItemOk;
dbCtx.Entry(currRec).State = EntityState.Modified;
}
// salvo...
dbCtx.SaveChanges();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OfferUpsertFromBom{Environment.NewLine}{exc}");
}
}
return answ;
}
#endregion Internal Methods
#region Private Fields
private static IConfiguration _configuration;
private static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Private Methods
/// <summary>
/// Esegue completamento e la validazione dei dati BOM da lista articoli + gruppi,
/// validando i dati stessi
/// </summary>
/// <param name="itemGroupList">Elenco ItemGroup da considerare</param>
/// <param name="bomGenList">Item di tipo BOM/BomAlt AMMESSI</param>
/// <param name="bomList">Lista BOM ricevuta da validare</param>
/// <param name="bomList">Lista BOM precedente da confrontare x scelta alternativi</param>
/// <param name="totCost">Costo netto componenti BOM calcolato</param>
/// <param name="totPrice">Prezzo complessivo calcolato (con aggiunta marginalità)</param>
/// <param name="numGroupOk">Controllo coerenza calcoli sui gruppi items</param>
/// <param name="numItemOk">Controllo coerenza calcoli su num items</param>
private static void validateBom(List<ItemGroupModel> itemGroupList, List<ItemModel> bomGenList, ref List<BomItemDTO> bomList, List<BomItemDTO>? bomListPrev, ref double totCost, ref double totPrice, ref int numGroupOk, ref int numItemOk)
{
double margin = 0;
// ciclo x ogni elemento della BOM, cercando x gruppo e ExtItemCode
foreach (var item in bomList)
{
// init del margine
margin = 0;
// verifico item group esistente...
if (itemGroupList.Where(x => x.CodGroup == item.ClassCode).Count() > 0)
{
numGroupOk++;
}
// 2025.09.16: se il prezzo arriva dalla BOM calcolata uso quello...
if (item.Price > 0)
{
// resetto ItemID ma NON il prezzo
item.ItemID = 0;
// conto l'item
numItemOk++;
item.PriceEff = item.Price;
// dovrei recuperare margine da BOM... da rivedere, x ora cablato 20%...
margin = 0.2;
}
else
{
/*************************************************
* Ricerca costo item:
* - se ho un itemID --> cerco record ESATTO e sostituisco descrizioni & co...
* - se non ho itemID --> cerco dati di selezione + qtyRange
*************************************************/
ItemModel? recCost = null;
bool selExact = item.ItemID > 0;
if (selExact)
{
recCost = bomGenList
.Where(x => x.ItemID == item.ItemID)
.FirstOrDefault();
}
else
{
recCost = bomGenList
.Where(x => x.CodGroup == item.ClassCode
&& x.ItemIDParent == 0 // voglio NON sia un record CHILD
&& x.ExtItemCode == item.ItemCode
&& item.Qty >= x.QtyMin
&& item.Qty < x.QtyMax)
.OrderByDescending(x => x.Cost)
.FirstOrDefault();
// 2025.09.24: se ho un elenco item della BOM precedente
if (bomListPrev != null && bomListPrev.Count > 0 && recCost != null)
{
// ...cerco item trovato come PARENT di altri item
var listAlt = bomGenList.Where(x => x.ItemIDParent == recCost.ItemID).ToList();
// che cerco nella nella BOM precedente...
var result = listAlt
.Join(
bomListPrev,
l1 => l1.ItemID,
l2 => l2.ItemID,
(l1, l2) => l1)
.ToList();
// nel caso ne trovassi solo 1 uso quello al posto del recCost...
if (result.Count == 1)
{
recCost = result.FirstOrDefault();
}
}
}
// se trovato valorizzo!
if (recCost != null)
{
numItemOk++;
item.ItemID = recCost.ItemID;
//item.PriceEff = recCost.BomCost * (1 + recCost.Margin);
item.PriceEff = recCost.Cost;
// se selezione esatta sovrascrivo altri valori
if (selExact)
{
item.ItemCode = recCost.ExtItemCode;
//item.DescriptionCode = recCost.Name;
}
margin = recCost.Margin;
}
else
{
item.ItemID = 0;
item.PriceEff = 0;
}
}
// ...e aggiorno totale
totCost += item.TotalCost;
// e prezzo totale compreso margine
totPrice += item.TotalCost * (1 + margin);
}
}
#endregion Private Methods
}
}