146 lines
6.4 KiB
C#
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
|
|
}
|
|
} |