Files
lux/EgwCoreLib.Lux.Data/Domains/BomCalculator.cs
T
2026-03-25 07:24:21 +01:00

146 lines
6.4 KiB
C#

namespace EgwCoreLib.Lux.Data.Domains
{
public static class BomCalculator
{
#region Public Methods
public static List<BomItemDTO> GetBomList(string itemBOM)
{
List<BomItemDTO> answ = new List<BomItemDTO>();
if (!string.IsNullOrEmpty(itemBOM) && itemBOM.Length > 2)
{
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(itemBOM);
if (bomList != null)
{
answ = bomList;
}
}
return answ;
}
/// <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="totItemQty">Numero toale di item dello step BOM</param>
/// <param name="numGroupOk">Controllo coerenza calcoli sui gruppi list2upd</param>
/// <param name="numItemOk">Controllo coerenza calcoli su num list2upd</param>
public static void Validate(
List<ItemGroupModel> itemGroupList,
List<ItemModel> bomGenList,
ref List<BomItemDTO> bomList,
List<BomItemDTO>? bomListPrev,
ref double totCost,
ref double totPrice,
ref int totItemQty,
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);
totItemQty += item.ItemQty;
}
}
#endregion Public Methods
}
}