3862 lines
163 KiB
C#
3862 lines
163 KiB
C#
using EgwCoreLib.Lux.Core.Generic;
|
|
using EgwCoreLib.Lux.Core.RestPayload;
|
|
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.Stats;
|
|
using EgwCoreLib.Lux.Data.DbModel.Task;
|
|
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
|
using EgwCoreLib.Lux.Data.Domains;
|
|
using EgwMultiEngineManager.Data;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using MySqlConnector;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using StackExchange.Redis;
|
|
using System.Data;
|
|
using static EgwCoreLib.Lux.Core.Enums;
|
|
|
|
namespace EgwCoreLib.Lux.Data.Controllers
|
|
{
|
|
internal class LuxController
|
|
{
|
|
// manca costruttore parametrico contoller...
|
|
|
|
#region Internal Methods
|
|
|
|
/// <summary>
|
|
/// Elenco CostDrivers
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<CostDriverModel>> CostDriverGetAllAsync()
|
|
{
|
|
List<CostDriverModel> dbResult = new List<CostDriverModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetCostDriver
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante CostDriverGetAllAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco contatori
|
|
/// </summary>
|
|
/// <param name="yearRef">Anno riferimento, se null da tutti</param>
|
|
/// <returns></returns>
|
|
internal async Task<List<CounterModel>> CountersGetAllAsync(int? yearRef = null)
|
|
{
|
|
List<CounterModel> dbResult = new List<CounterModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetCounters
|
|
.Where(x => yearRef == null || x.RefYear == yearRef)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante CountersGetAllAsync | yearRef: {yearRef}{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera un nuovo valore del contatore per tipo ed anno richiesto, se mancasse crea
|
|
/// </summary>
|
|
/// <param name="yearRef">Anno riferimento</param>
|
|
/// <param name="countName">Counter richiesto</param>
|
|
/// <returns></returns>
|
|
internal async Task<int> CountersGetNext(int yearRef, string countName)
|
|
{
|
|
int newCount = 0;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
var outParam = new MySqlParameter("@pValue", MySqlDbType.Int32)
|
|
{
|
|
Direction = ParameterDirection.Output
|
|
};
|
|
|
|
await dbCtx.Database.ExecuteSqlRawAsync(
|
|
"CALL GetNextCounter(@pYear, @pName, @pValue);",
|
|
new MySqlParameter("@pYear", yearRef),
|
|
new MySqlParameter("@pName", countName),
|
|
outParam
|
|
);
|
|
if (outParam != null)
|
|
{
|
|
int.TryParse($"{outParam.Value}", out newCount);
|
|
}
|
|
}
|
|
return newCount;
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
|
|
#if false
|
|
|
|
/// <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 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 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 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>
|
|
/// Esegue un mass update dei valori di margine, qtyMax, costo di un set di dati ricevuto
|
|
/// </summary>
|
|
/// <param name="list2upd">Elenco items da aggiornare</param>
|
|
/// <param name="setCost">Costo standard (al volume m3)</param>
|
|
/// <param name="defMargin">Margine da impostare per tutti</param>
|
|
/// <param name="defQtyMax">Valore qty max da impostare per tutti</param>
|
|
/// <param name="defUM">Valore UM da impostare per tutti</param>
|
|
/// <param name="roundVal">Valore di arrotondamento richiesto (0 = non arrotondo)</param>
|
|
/// <param name="scaleFactor">Valore di scala da unità in ingresso x unità di costo (mm x mm x m --> m3)</param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ArgumentException"></exception>
|
|
internal async Task<bool> ItemMassUpdate(List<BomItemDTO> list2upd, double setCost, double defMargin, double defQtyMax, string defUM, int roundVal, double scaleFactor)
|
|
{
|
|
bool answ = false;
|
|
if (list2upd == null || !list2upd.Any())
|
|
return answ;
|
|
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// Validate input
|
|
if (setCost <= 0)
|
|
throw new ArgumentException("setCost must be greater than 0.");
|
|
|
|
// Step 1: Extract width and height from ExtItemCode
|
|
var itemUpdates = new List<ItemModel>();
|
|
|
|
foreach (var item in list2upd)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(item.ItemCode))
|
|
continue;
|
|
|
|
// Try to parse ExtItemCode: "Pine-200.0x360.0"
|
|
if (!item.ItemCode.Contains("-") || !item.ItemCode.Contains("x"))
|
|
{
|
|
// Skip invalid format
|
|
continue;
|
|
}
|
|
|
|
// Split by "-" to get prefix and number part
|
|
var parts = item.ItemCode.Split('-', 2);
|
|
if (parts.Length < 2)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string numberPart = parts[1]; // e.g. "200.0x360.0"
|
|
|
|
// Split by "x" to get width and height
|
|
var widthHeight = numberPart.Split('x', 2);
|
|
if (widthHeight.Length < 2)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!double.TryParse(widthHeight[0], NumberStyles.Any, CultureInfo.InvariantCulture, out double width) ||
|
|
!double.TryParse(widthHeight[1], NumberStyles.Any, CultureInfo.InvariantCulture, out double height))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Step 2: Calculate Cost using formula:
|
|
// Cost = setCost / 1,000,000 * width * height
|
|
double calculatedCost = (setCost / scaleFactor) * width * height;
|
|
// if requested do round ceiling
|
|
if (roundVal > 0)
|
|
{
|
|
calculatedCost = Math.Ceiling(calculatedCost / roundVal) * roundVal;
|
|
}
|
|
|
|
// Optional: you can also apply margin to cost if needed, but you said "Cost = ..."
|
|
// So we're just computing it based on width/height
|
|
|
|
// Step 4: Create a new ItemModel with updated values
|
|
var updatedItem = new ItemModel
|
|
{
|
|
ItemID = item.ItemID,
|
|
ExtItemCode = item.ItemCode, // keep original
|
|
Cost = calculatedCost,
|
|
Margin = defMargin,
|
|
QtyMax = defQtyMax,
|
|
UM = defUM
|
|
};
|
|
|
|
itemUpdates.Add(updatedItem);
|
|
}
|
|
|
|
// Step 5: Update database using EF Core (EF Core doesn't support "update" on entire list directly)
|
|
// We'll use .UpdateRange() or a raw update via .Where() and .SetProperty()
|
|
|
|
// ✅ Use EF Core's Update method (for bulk update)
|
|
if (itemUpdates.Any())
|
|
{
|
|
// Update only the ones that exist in the DB
|
|
var existingItems = await dbCtx.DbSetItem
|
|
.Where(i => itemUpdates.Select(ui => ui.ItemID).Contains(i.ItemID))
|
|
.ToListAsync();
|
|
|
|
if (existingItems.Any())
|
|
{
|
|
// Update existing records using EF Core's Update method
|
|
foreach (var updatedItem in itemUpdates)
|
|
{
|
|
var existing = existingItems.FirstOrDefault(i => i.ItemID == updatedItem.ItemID);
|
|
if (existing != null)
|
|
{
|
|
// Update only the fields we're setting
|
|
existing.Cost = updatedItem.Cost;
|
|
existing.Margin = updatedItem.Margin;
|
|
existing.QtyMax = updatedItem.QtyMax;
|
|
}
|
|
}
|
|
|
|
await dbCtx.SaveChangesAsync();
|
|
}
|
|
}
|
|
}
|
|
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(newCount);
|
|
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;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Add 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())
|
|
{
|
|
// Controllo ed inserisco eventuali gruppi mancanti
|
|
UpdateCodGroup(bomList);
|
|
|
|
// prendo solo elementi a prezzo 0 da salvare sul DB
|
|
var item2save = bomList
|
|
.Where(x => x.Price == 0)
|
|
.ToList();
|
|
List<ItemModel> listInserted = new List<ItemModel>();
|
|
|
|
// 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 --> verifico x inserire!!!
|
|
if (currRec == null)
|
|
{
|
|
// verifico NON sia tra gli list2upd già in fase di inserimento
|
|
if (!listInserted.Any(x => x.CodGroup == item.ClassCode && x.ExtItemCode == item.ItemCode))
|
|
{
|
|
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);
|
|
listInserted.Add(newRec);
|
|
}
|
|
}
|
|
}
|
|
|
|
// salvo...
|
|
dbCtx.SaveChanges();
|
|
|
|
}
|
|
return answ;
|
|
}
|
|
/// <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 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Eliminazione record richiesto
|
|
/// </summary>
|
|
/// <param name="rec2del"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> JobStepDeleteAsync(JobStepModel rec2del)
|
|
{
|
|
bool result = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var dbResult = await dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.JobStepID == rec2del.JobStepID)
|
|
.FirstOrDefaultAsync();
|
|
if (dbResult != null)
|
|
{
|
|
// cerco righe successive
|
|
var list2move = dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.JobID == rec2del.JobID && x.Index > dbResult.Index)
|
|
.ToList();
|
|
// se ci sono aggiorno!
|
|
if (list2move != null && list2move.Count > 0)
|
|
{
|
|
foreach (var item in list2move)
|
|
{
|
|
item.Index--;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
}
|
|
// elimino record
|
|
dbCtx.DbSetJobStep.Remove(dbResult);
|
|
await dbCtx.SaveChangesAsync();
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobStepDeleteAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco JobStep dato JobID parent
|
|
/// </summary>
|
|
/// <param name="jobID"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<JobStepModel>> JobStepGetAsync(int jobID)
|
|
{
|
|
List<JobStepModel> dbResult = new List<JobStepModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.JobID == jobID)
|
|
.Include(c => c.JobNav)
|
|
.Include(c => c.PhaseNav)
|
|
.Include(c => c.ResourceNav)
|
|
.Include(c => c.TagNav)
|
|
.Include(c => c.ResourceNav.DriverNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobStepGetAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue spostamento nell'ordinamento
|
|
/// 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> JobStepMoveAsync(JobStepModel selRec, bool moveUp)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.JobStepID == selRec.JobStepID)
|
|
.FirstOrDefault();
|
|
|
|
if (currRec != null)
|
|
{
|
|
// recupero info del num rec del suo gruppo
|
|
int numRec = dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.JobID == selRec.JobID)
|
|
.Count();
|
|
|
|
// verifico NON sia primo/ultimo...
|
|
bool canMove = false;
|
|
int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1;
|
|
if (moveUp)
|
|
{
|
|
canMove = newPos > 0;
|
|
}
|
|
else
|
|
{
|
|
canMove = newPos <= numRec;
|
|
}
|
|
// se abilitato --> aggiorno i 2 record...
|
|
if (canMove)
|
|
{
|
|
var otherRec = dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.Index == newPos)
|
|
.FirstOrDefault();
|
|
if (otherRec != null)
|
|
{
|
|
otherRec.Index = currRec.Index;
|
|
dbCtx.Entry(otherRec).State = EntityState.Modified;
|
|
currRec.Index = newPos;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobStepMoveAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record
|
|
/// </summary>
|
|
/// <param name="upsRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> JobStepUpsertAsync(JobStepModel upsRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetJobStep
|
|
.Where(x => x.JobStepID == upsRec.JobStepID && upsRec.JobStepID > 0)
|
|
.FirstOrDefault();
|
|
// se trovato --> aggiorno
|
|
if (currRec != null)
|
|
{
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(upsRec);
|
|
}
|
|
// se mancasse --> aggiungo
|
|
else
|
|
{
|
|
dbCtx.DbSetJobStep.Add(upsRec);
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobStepUpsertAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add dell'elenco dei tags associati
|
|
/// </summary>
|
|
/// <param name="JobID">ID Job richiesto</param>
|
|
/// <param name="reqTagList">Elenco Tags richiesto</param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> JobTask2TagsUpsertAsync(int JobID, List<string> reqTagList)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetJobTask
|
|
.Where(x => x.JobID == JobID)
|
|
.Include(t => t.TagNav)
|
|
.FirstOrDefault();
|
|
// se trovato --> aggiorno
|
|
if (currRec != null)
|
|
{
|
|
var currentTags = currRec.TagNav.Select(t => t.CodTag).ToList();
|
|
|
|
// calcolo modifiche
|
|
var toAdd = reqTagList.Except(currentTags).ToList();
|
|
var toRemove = currentTags.Except(reqTagList).ToList();
|
|
|
|
// aggiunte
|
|
foreach (var tag in toAdd)
|
|
{
|
|
currRec.TagNav.Add(new JobTaskTagModel
|
|
{
|
|
JobID = JobID,
|
|
CodTag = tag
|
|
});
|
|
}
|
|
// rimozioni
|
|
foreach (var tag in toRemove)
|
|
{
|
|
var entity = currRec.TagNav.FirstOrDefault(t => t.CodTag == tag);
|
|
if (entity != null)
|
|
dbCtx.Remove(entity);
|
|
}
|
|
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobTask2TagsUpsertAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Eliminazione record richiesto
|
|
/// </summary>
|
|
/// <param name="rec2del"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> JobTaskDeleteAsync(JobTaskModel rec2del)
|
|
{
|
|
bool result = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var dbResult = await dbCtx
|
|
.DbSetJobTask
|
|
.Where(x => x.JobID == rec2del.JobID)
|
|
.FirstOrDefaultAsync();
|
|
if (dbResult != null)
|
|
{
|
|
// cerco righe successive
|
|
var list2move = dbCtx
|
|
.DbSetJobTask
|
|
.Where(x => x.Index > dbResult.Index)
|
|
.ToList();
|
|
// se ci sono aggiorno!
|
|
if (list2move != null && list2move.Count > 0)
|
|
{
|
|
foreach (var item in list2move)
|
|
{
|
|
item.Index--;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
}
|
|
dbCtx.DbSetJobTask.Remove(dbResult);
|
|
await dbCtx.SaveChangesAsync();
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobTaskDeleteAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera elenco Jobs (conf) da DB
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<JobTaskModel>> JobTaskGetAllAsync()
|
|
{
|
|
List<JobTaskModel> dbResult = new List<JobTaskModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetJobTask
|
|
.Include(c => c.TagNav)
|
|
.Include(c => c.JobStepNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobTaskGetAllAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue spostamento nell'ordinamento
|
|
/// 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> JobTaskMoveAsync(JobTaskModel selRec, bool moveUp)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetJobTask
|
|
.Where(x => x.JobID == selRec.JobID)
|
|
.FirstOrDefault();
|
|
|
|
if (currRec != null)
|
|
{
|
|
// recupero info del num rec del suo gruppo
|
|
int numRec = dbCtx
|
|
.DbSetJobTask
|
|
.Count();
|
|
|
|
// verifico NON sia primo/ultimo...
|
|
bool canMove = false;
|
|
int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1;
|
|
if (moveUp)
|
|
{
|
|
canMove = newPos > 0;
|
|
}
|
|
else
|
|
{
|
|
canMove = newPos <= numRec;
|
|
}
|
|
// se abilitato --> aggiorno i 2 record...
|
|
if (canMove)
|
|
{
|
|
var otherRec = dbCtx
|
|
.DbSetJobTask
|
|
.Where(x => x.Index == newPos)
|
|
.FirstOrDefault();
|
|
if (otherRec != null)
|
|
{
|
|
otherRec.Index = currRec.Index;
|
|
dbCtx.Entry(otherRec).State = EntityState.Modified;
|
|
currRec.Index = newPos;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobTaskMoveAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record
|
|
/// </summary>
|
|
/// <param name="upsRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> JobTaskUpsertAsync(JobTaskModel upsRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetJobTask
|
|
.Where(x => x.JobID == upsRec.JobID)
|
|
.FirstOrDefault();
|
|
// se trovato --> aggiorno
|
|
if (currRec != null)
|
|
{
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(upsRec);
|
|
}
|
|
// se mancasse --> aggiungo
|
|
else
|
|
{
|
|
dbCtx.DbSetJobTask.Add(upsRec);
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante JobTaskUpsertAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue il cloning completo di un offerta e di TUTTE le relative righe di offerta...
|
|
/// </summary>
|
|
/// <param name="rec2clone"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OfferClone(OfferModel rec2clone)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOffer
|
|
.Where(x => x.OfferID == rec2clone.OfferID)
|
|
.Include(x => x.OfferRowNav)
|
|
.FirstOrDefault();
|
|
|
|
// ultimo record OFFERTA x calcolo refNum
|
|
var lastRec = dbCtx
|
|
.DbSetOffer
|
|
.Where(x => x.RefYear == adesso.Year)
|
|
.OrderByDescending(x => x.RefNum)
|
|
.FirstOrDefault();
|
|
int newRefNum = lastRec != null ? lastRec.RefNum + 1 : 1;
|
|
|
|
// se trovo --> duplico!
|
|
if (currRec != null)
|
|
{
|
|
// recupero ultimo num offerta dell'anno corrente...
|
|
OfferModel newRec = new OfferModel()
|
|
{
|
|
ConsNote = rec2clone.ConsNote,
|
|
CustomerID = rec2clone.CustomerID,
|
|
DealerID = rec2clone.DealerID,
|
|
Description = rec2clone.Description,
|
|
DictPresel = rec2clone.DictPresel,
|
|
Discount = rec2clone.Discount,
|
|
DueDateProm = rec2clone.DueDateProm,
|
|
DueDateReq = rec2clone.DueDateReq,
|
|
Envir = rec2clone.Envir,
|
|
Inserted = adesso,
|
|
Modified = adesso,
|
|
OffertState = OfferStates.Open,
|
|
RefNum = newRefNum,
|
|
RefRev = 1,
|
|
RefYear = adesso.Year,
|
|
ValidUntil = currRec.ValidUntil
|
|
};
|
|
|
|
// sistemo child...
|
|
newRec.OfferRowNav = currRec.OfferRowNav
|
|
.Select(c => new OfferRowModel()
|
|
{
|
|
AwaitBom = c.AwaitBom,
|
|
AwaitPrice = c.AwaitPrice,
|
|
BomCost = c.BomCost,
|
|
BomOk = c.BomOk,
|
|
BomPrice = c.BomPrice,
|
|
Envir = c.Envir,
|
|
FileName = c.FileName,
|
|
FileResource = c.FileResource,
|
|
FileSize = c.FileSize,
|
|
Inserted = adesso,
|
|
ItemBOM = c.ItemBOM,
|
|
ItemJCD = c.ItemJCD,
|
|
ItemOk = c.ItemOk,
|
|
ItemSteps = c.ItemSteps,
|
|
ItemTags = c.ItemTags,
|
|
JobID = c.JobID,
|
|
Modified = c.Modified,
|
|
Note = c.Note,
|
|
ProdItemQty = c.ProdItemQty,
|
|
Qty = c.Qty,
|
|
RowNum = c.RowNum,
|
|
SellingItemID = c.SellingItemID,
|
|
SerStruct = c.SerStruct,
|
|
StepCost = c.StepCost,
|
|
StepFlowTime = c.StepFlowTime,
|
|
StepLeadTime = c.StepLeadTime,
|
|
StepPrice = c.StepPrice,
|
|
//OrderID = dbRec.OrderID,
|
|
OfferRowUID = c.OfferRowDtx
|
|
})
|
|
.ToList();
|
|
|
|
// infine aggiungo riga ordine e relativi child
|
|
dbCtx.DbSetOffer.Add(newRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OfferClone{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 offerte da DB filtrate x periodo e stato
|
|
/// </summary>
|
|
/// <param name="inizio"></param>
|
|
/// <param name="fine"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<OfferModel>> OfferGetFilt(DateTime inizio, DateTime fine)
|
|
{
|
|
List<OfferModel> dbResult = new List<OfferModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetOffer
|
|
.Where(x => x.Inserted >= inizio && x.Inserted <= fine)
|
|
.Include(c => c.CustomerNav)
|
|
.Include(d => d.DealerNav)
|
|
.Include(o => o.OfferRowNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OfferGetFilt{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera da DB riga offerta dato Primary ID
|
|
/// </summary>
|
|
/// <param name="OfferRowID"></param>
|
|
/// <returns></returns>
|
|
internal async Task<OfferRowModel?> OfferRowGetByIdAsync(int OfferRowID)
|
|
{
|
|
OfferRowModel? dbResult = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetOfferRow
|
|
.Include(s => s.SellingItemNav)
|
|
.FirstOrDefaultAsync(x => x.OfferRowID == OfferRowID);
|
|
}
|
|
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>
|
|
/// Recupera da DB riga offerta dato UID
|
|
/// </summary>
|
|
/// <param name="OfferRowUID"></param>
|
|
/// <returns></returns>
|
|
internal OfferRowModel? OfferRowGetByUID(string OfferRowUID)
|
|
{
|
|
OfferRowModel? dbResult = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = dbCtx
|
|
.DbSetOfferRow
|
|
.Include(s => s.SellingItemNav)
|
|
.FirstOrDefault(x => x.OfferRowUID == OfferRowUID);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OfferRowGetByUID{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
internal async Task<bool> OffersCheckExpired()
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
// recupero offerta...
|
|
var listExpired = dbCtx
|
|
.DbSetOffer
|
|
.Where(x => x.ValidUntil < adesso && x.OffertState == OfferStates.Open)
|
|
.ToList();
|
|
|
|
// se trovo le aggiorno come stato
|
|
if (listExpired != null)
|
|
{
|
|
foreach (var item in listExpired)
|
|
{
|
|
item.OffertState = OfferStates.Expired;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffersCheckExpired{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// Elimina riga e sposta eventuali righe successive...
|
|
/// </summary>
|
|
/// <param name="rec2Del"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertRowDelete(OfferRowModel rec2Del)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferRowID == rec2Del.OfferRowID)
|
|
.FirstOrDefault();
|
|
|
|
// se non trovo aggiungo
|
|
if (currRec != null)
|
|
{
|
|
// recupero indice attuale...
|
|
int currRowNum = rec2Del.RowNum;
|
|
// cerco righe successive
|
|
var list2move = dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferID == rec2Del.OfferID && x.RowNum > currRowNum)
|
|
.ToList();
|
|
// se ci sono aggiorno!
|
|
if (list2move != null && list2move.Count > 0)
|
|
{
|
|
foreach (var item in list2move)
|
|
{
|
|
item.RowNum--;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
}
|
|
// infine rimuovo riga
|
|
dbCtx.DbSetOfferRow.Remove(currRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertRowDelete{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornamento valore ImgType da tipo Prodotto sellingItem ancestor
|
|
/// </summary>
|
|
/// <param name="offertID"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertRowFixImgTypeAsync(int offertID)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
var currList = await dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferID == offertID)
|
|
.Include(s => s.SellingItemNav)
|
|
.ToListAsync();
|
|
// se trovato --> verifico valori differenti, aggiorno e restituisco da calcolare
|
|
if (currList != null)
|
|
{
|
|
var list2fix = currList.Where(x => x.ImgType == ImageType.ND).ToList();
|
|
if (list2fix != null && list2fix.Count > 0)
|
|
{
|
|
// sistemo ImgType
|
|
foreach (var item in list2fix)
|
|
{
|
|
// se è calcolato il selling item --> img calcolata
|
|
if (item.SellingItemNav != null && (item.SellingItemNav.SourceType == ItemSourceType.Jwd || item.SellingItemNav.SourceType == ItemSourceType.FileBTL))
|
|
item.ImgType = ImageType.Calculated;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
// salvo...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornamento valore UID non calcolato + ritorno elenco UID da aggiornare
|
|
/// </summary>
|
|
/// <param name="offertID"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<string>> OffertRowFixUidAsync(int offertID)
|
|
{
|
|
List<string> answ = new List<string>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currList = await dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferID == offertID)
|
|
.ToListAsync();
|
|
// se trovato --> verifico valori differenti, aggiorno e restituisco da calcolare
|
|
if (currList != null)
|
|
{
|
|
var list2fix = currList.Where(x => string.IsNullOrEmpty(x.OfferRowUID) || x.OfferRowUID != x.OfferRowDtx).ToList();
|
|
if (list2fix != null && list2fix.Count > 0)
|
|
{
|
|
// salvo elenco
|
|
answ = list2fix.Select(x => x.OfferRowDtx).ToList();
|
|
// sistemo UID
|
|
foreach (var item in list2fix)
|
|
{
|
|
item.OfferRowUID = item.OfferRowDtx;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
// salvo...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertRowFixUidAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <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>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertRowUpdateAwaitStateAsync(int offerRowID, bool? awaitBom, bool? awaitPrice)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero righe offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferRowID == offerRowID)
|
|
.FirstOrDefault();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.AwaitBom = awaitBom ?? currRec.AwaitBom;
|
|
currRec.AwaitPrice = awaitPrice ?? currRec.AwaitPrice;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertRowUpdateAwaitStateAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <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 totItemQty = 0;
|
|
int numGroupOk = 0;
|
|
int numItemOk = 0;
|
|
int numElems = newBomList.Count;
|
|
// validazione e completamento BOM
|
|
BomCalculator.Validate(itemGroupList, bomGenList, ref newBomList, null, ref totCost, ref totPrice, ref totItemQty, 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;
|
|
currRec.ProdItemQty = totItemQty;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
// salvo modifiche...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertRowUpdateBom{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorno sul DB i dati del file associato
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertRowUpdateFileDataAsync(OfferRowModel updRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// recupero righe offerta...
|
|
var currRec = await dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferRowID == updRec.OfferRowID)
|
|
.FirstOrDefaultAsync();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.FileName = updRec.FileName;
|
|
currRec.FileResource = updRec.FileResource;
|
|
currRec.FileSize = updRec.FileSize;
|
|
currRec.SerStruct = updRec.SerStruct;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua update serStruct per l'offerta indicata
|
|
/// </summary>
|
|
/// <param name="offerRowID">ID singola riga offerta</param>
|
|
/// <param name="serStruct">Valore serializzatoe</param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertRowUpdateSerStruct(int offerRowID, string serStruct)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero righe offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferRowID == offerRowID)
|
|
.FirstOrDefault();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.SerStruct = serStruct;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertRowUpdateSerStruct{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record riga offerta
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertRowUpsertAsync(OfferRowModel updRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// recupero offerta...
|
|
var currRec = await dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferRowID == updRec.OfferRowID)
|
|
.FirstOrDefaultAsync();
|
|
|
|
// se non trovo aggiungo
|
|
if (currRec == null)
|
|
{
|
|
dbCtx.DbSetOfferRow.Add(updRec);
|
|
// se ci sono record successivi li devo spostare...
|
|
var list2move = await dbCtx
|
|
.DbSetOfferRow
|
|
.Where(x => x.OfferID == updRec.OfferID && x.RowNum >= updRec.RowNum)
|
|
.ToListAsync();
|
|
if (list2move != null && list2move.Count > 0)
|
|
{
|
|
foreach (var item2move in list2move)
|
|
{
|
|
item2move.RowNum++;
|
|
dbCtx.Entry(item2move).State = EntityState.Modified;
|
|
}
|
|
}
|
|
}
|
|
// altrimenti aggiorno
|
|
else
|
|
{
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
int result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
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 totItemQty = 0;
|
|
int numGroupOk = 0;
|
|
int numItemOk = 0;
|
|
int numElems = bomList.Count;
|
|
// validazione e completamento BOM
|
|
BomCalculator.Validate(itemGroupList, bomGenList, ref bomList, null, ref totCost, ref totPrice, ref totItemQty, 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;
|
|
currRec.ProdItemQty = totItemQty;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
}
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertUpdateCost{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record offerta
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OffertUpsert(OfferModel updRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOffer
|
|
.Where(x => x.OfferID == updRec.OfferID)
|
|
.FirstOrDefault();
|
|
|
|
// se non trovo aggiungo
|
|
if (currRec == null)
|
|
{
|
|
dbCtx.DbSetOffer.Add(updRec);
|
|
}
|
|
// altrimenti aggiorno
|
|
else
|
|
{
|
|
// verifico eventuale riapertura SE fosse expired ma la data è valida...
|
|
if (currRec.OffertState == OfferStates.Expired && updRec.ValidUntil > DateTime.Today)
|
|
{
|
|
updRec.OffertState = OfferStates.Open;
|
|
}
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OffertUpsert{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.sourceType == 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 totItemQty = 0;
|
|
int numGroupOk = 0;
|
|
int numItemOk = 0;
|
|
int numElems = bomList.Count;
|
|
// validazione e completamento BOM
|
|
BomCalculator.Validate(itemGroupList, bomGenList, ref bomList, bomListPrev, ref totCost, ref totPrice, ref totItemQty, 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;
|
|
// setto ok await di BOM e Price
|
|
currRec.AwaitBom = false;
|
|
currRec.AwaitPrice = false;
|
|
currRec.ProdItemQty = totItemQty;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo...
|
|
var result = dbCtx.SaveChanges();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OfferUpsertFromBom{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce record ordine + righe Ordine dato ID
|
|
/// </summary>
|
|
/// <param name="orderId"></param>
|
|
/// <returns></returns>
|
|
internal async Task<OrderModel?> OrderById(int orderId)
|
|
{
|
|
OrderModel? dbRec = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
// recupero ordine...
|
|
dbRec = dbCtx
|
|
.DbSetOrder
|
|
.Where(x => x.OrderID == orderId)
|
|
.Include(x => x.OrderRowNav)
|
|
.FirstOrDefault();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderById{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbRec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Genera un nuovo record ordine come cloning completo di un offerta e di TUTTE le relative righe di offerta + rif offerta
|
|
/// </summary>
|
|
/// <param name="rec2clone"></param>
|
|
/// <returns></returns>
|
|
internal async Task<OrderModel?> OrderFromOffer(OfferModel rec2clone)
|
|
{
|
|
OrderModel? newRec = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
|
try
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOffer
|
|
.Where(x => x.OfferID == rec2clone.OfferID)
|
|
.Include(x => x.OfferRowNav)
|
|
.FirstOrDefault();
|
|
|
|
// ultimo record ORDINE x calcolo refNum
|
|
var lastRec = dbCtx
|
|
.DbSetOrder
|
|
.Where(x => x.RefYear == adesso.Year)
|
|
.OrderByDescending(x => x.RefNum)
|
|
.FirstOrDefault();
|
|
int newRefNum = lastRec != null ? lastRec.RefNum + 1 : 1;
|
|
|
|
// se trovo --> duplico!
|
|
if (currRec != null)
|
|
{
|
|
// recupero ultimo num offerta dell'anno corrente...
|
|
newRec = new OrderModel()
|
|
{
|
|
ConsNote = rec2clone.ConsNote,
|
|
CustomerID = rec2clone.CustomerID,
|
|
DealerID = rec2clone.DealerID,
|
|
Description = rec2clone.Description,
|
|
DictPresel = rec2clone.DictPresel,
|
|
Discount = rec2clone.Discount,
|
|
DueDateProm = rec2clone.DueDateProm,
|
|
DueDateReq = rec2clone.DueDateReq,
|
|
Envir = rec2clone.Envir,
|
|
Inserted = adesso,
|
|
Modified = adesso,
|
|
OfferID = rec2clone.OfferID,
|
|
OrderState = OrderStates.Created,
|
|
RefNum = newRefNum,
|
|
RefRev = 1,
|
|
RefYear = adesso.Year,
|
|
ValidUntil = currRec.ValidUntil
|
|
};
|
|
|
|
// sistemo child offer...
|
|
newRec.OrderRowNav = currRec.OfferRowNav
|
|
.Select(c => new OrderRowModel()
|
|
{
|
|
AwaitBom = c.AwaitBom,
|
|
AwaitPrice = c.AwaitPrice,
|
|
BomCost = c.BomCost,
|
|
BomOk = c.BomOk,
|
|
BomPrice = c.BomPrice,
|
|
Envir = c.Envir,
|
|
FileName = c.FileName,
|
|
FileResource = c.FileResource,
|
|
FileSize = c.FileSize,
|
|
Inserted = adesso,
|
|
ItemBOM = c.ItemBOM,
|
|
ItemJCD = c.ItemJCD,
|
|
ItemOk = c.ItemOk,
|
|
ItemSteps = c.ItemSteps,
|
|
ItemTags = c.ItemTags,
|
|
JobID = c.JobID,
|
|
Modified = adesso,
|
|
Note = c.Note,
|
|
ProdItemQty = c.ProdItemQty,
|
|
Qty = c.Qty,
|
|
RowNum = c.RowNum,
|
|
SellingItemID = c.SellingItemID,
|
|
SerStruct = c.SerStruct,
|
|
StepCost = c.StepCost,
|
|
StepFlowTime = c.StepFlowTime,
|
|
StepLeadTime = c.StepLeadTime,
|
|
StepPrice = c.StepPrice
|
|
})
|
|
.ToList();
|
|
// infine aggiungo riga ordine e relativi child
|
|
dbCtx.DbSetOrder.Add(newRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var numSave = await dbCtx.SaveChangesAsync();
|
|
|
|
// se ok sistemo UID...
|
|
if (numSave > 0 && newRec != null)
|
|
{
|
|
// sistemo UID...
|
|
foreach (var item in newRec.OrderRowNav)
|
|
{
|
|
item.OrderRowUID = item.OrderRowCode;
|
|
// alternativa da valutare..
|
|
if (false)
|
|
{
|
|
// genero tanti record collegati alla riga d'ordine...
|
|
for (int i = 0; i < item.ProdItemQtyTot; i++)
|
|
{
|
|
var child = new ProductionItemModel
|
|
{
|
|
OrderRowID = item.OrderRowID,
|
|
//OrderRowNav = item,
|
|
ItemCode = i + 1,
|
|
ExtItemCode = $"{item.OrderRowCode}-{i + 1:000}",
|
|
ProdBatchID = null
|
|
};
|
|
// aggiungo record
|
|
item.ProdItemNav.Add(child);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item.ProdItemNav = Enumerable.Range(1, (int)item.ProdItemQtyTot)
|
|
.Select(i => new ProductionItemModel
|
|
{
|
|
//OrderRowID = item.OrderRowID,
|
|
OrderRowNav = item,
|
|
ItemCode = i,
|
|
ExtItemCode = $"{item.OrderRowCode}-{i:000}",
|
|
ProdBatchID = null,
|
|
ProdItemTag = null //nullo e POI verrà sistemato
|
|
})
|
|
.ToList();
|
|
}
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
// salvo ulteriori variazioni
|
|
await dbCtx.SaveChangesAsync();
|
|
// tutti gli ordini e anno corrente...
|
|
await dbCtx.Database.ExecuteSqlRawAsync("CALL stp_ProdItem_UpdateProdItemTag(0,0);");
|
|
|
|
// committo in un unica transazione (da provare!!!)
|
|
await transaction.CommitAsync();
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await transaction.RollbackAsync();
|
|
Log.Error($"Eccezione durante OrderFromOffer{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return newRec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ordini da DB filtrati x periodo
|
|
/// </summary>
|
|
/// <param name="inizio"></param>
|
|
/// <param name="fine"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<OrderModel>> OrderGetFilt(DateTime inizio, DateTime fine)
|
|
{
|
|
List<OrderModel> dbResult = new List<OrderModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetOrder
|
|
.Where(x => x.Inserted >= inizio && x.Inserted <= fine)
|
|
.Include(c => c.CustomerNav)
|
|
.Include(d => d.DealerNav)
|
|
.Include(o => o.OrderRowNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderGetFilt{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina riga e sposta eventuali righe successive...
|
|
/// </summary>
|
|
/// <param name="rec2Del"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderRowDelete(OrderRowModel rec2Del)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowID == rec2Del.OrderRowID)
|
|
.FirstOrDefault();
|
|
|
|
// se trovo procedo
|
|
if (currRec != null)
|
|
{
|
|
// recupero indice attuale...
|
|
int currRowNum = rec2Del.RowNum;
|
|
// cerco righe successive
|
|
var list2move = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderID == rec2Del.OrderID && x.RowNum > currRowNum)
|
|
.ToList();
|
|
// se ci sono aggiorno!
|
|
if (list2move != null && list2move.Count > 0)
|
|
{
|
|
foreach (var item in list2move)
|
|
{
|
|
item.RowNum--;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
}
|
|
// infine rimuovo riga
|
|
dbCtx.DbSetOrderRow.Remove(currRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowDelete{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornamento valore UID non calcolato + ritorno elenco UID da aggiornare
|
|
/// </summary>
|
|
/// <param name="orderID"></param>
|
|
/// <returns></returns>
|
|
internal List<string> OrderRowFixUid(int orderID)
|
|
{
|
|
List<string> answ = new List<string>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currList = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderID == orderID)
|
|
.ToList();
|
|
// se trovato --> verifico valori differenti, aggiorno e restituisco da calcolare
|
|
if (currList != null)
|
|
{
|
|
var list2fix = currList.Where(x => string.IsNullOrEmpty(x.OrderRowUID) || x.OrderRowUID != x.OrderRowCode).ToList();
|
|
if (list2fix != null && list2fix.Count > 0)
|
|
{
|
|
// salvo elenco
|
|
answ = list2fix.Select(x => x.OrderRowCode).ToList();
|
|
// sistemo UID
|
|
foreach (var item in list2fix)
|
|
{
|
|
item.OrderRowUID = item.OrderRowCode;
|
|
dbCtx.Entry(item).State = EntityState.Modified;
|
|
}
|
|
// salvo...
|
|
var result = dbCtx.SaveChanges();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowFixUid{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco righe Ordine specificato
|
|
/// </summary>
|
|
/// <param name="OrderID"></param>
|
|
/// <returns></returns>
|
|
internal List<OrderRowModel> OrderRowGetByOffer(int OrderID)
|
|
{
|
|
List<OrderRowModel> dbResult = new List<OrderRowModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderID == OrderID)
|
|
.Include(s => s.SellingItemNav)
|
|
//.Include(d => d.DealerNav)
|
|
.ToList();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowGetByOffer{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco righe ordine dato stato richiesto
|
|
/// </summary>
|
|
/// <param name="reqState"></param>
|
|
/// <returns></returns>
|
|
internal List<OrderRowModel> OrderRowGetByState(OrderStates reqState, DateTime dtStart, DateTime dtEnd)
|
|
{
|
|
List<OrderRowModel> dbResult = new List<OrderRowModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowState == reqState && x.Inserted >= dtStart && x.Inserted <= dtEnd)
|
|
.Include(s => s.SellingItemNav)
|
|
//.Include(d => d.DealerNav)
|
|
.ToList();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowGetByState{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco righe ordine dato periodo + stato richiesto MINIMO
|
|
/// </summary>
|
|
/// <param name="reqState"></param>
|
|
/// <returns></returns>
|
|
internal List<OrderRowModel> OrderRowGetByStateMin(OrderStates reqState, DateTime dtStart, DateTime dtEnd)
|
|
{
|
|
List<OrderRowModel> dbResult = new List<OrderRowModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowState >= reqState && x.Inserted >= dtStart && x.Inserted <= dtEnd)
|
|
.Include(s => s.SellingItemNav)
|
|
//.Include(d => d.DealerNav)
|
|
.ToList();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowGetByStateMin{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Riga Ordine dato suo UID
|
|
/// </summary>
|
|
/// <param name="OrderRowUID"></param>
|
|
/// <returns></returns>
|
|
internal OrderRowModel OrderRowGetByUID(string OrderRowUID)
|
|
{
|
|
OrderRowModel? dbResult = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = dbCtx
|
|
.DbSetOrderRow
|
|
.Include(s => s.SellingItemNav)
|
|
.FirstOrDefault(x => x.OrderRowUID == OrderRowUID);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowGetByUID{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validazione record:
|
|
/// - controllo state vs estimate
|
|
/// - segnala il numero dei record aggiornati
|
|
/// </summary>
|
|
/// <param name="list2chk">Elenco record da verificare</param>
|
|
internal async Task<int> OrderRowListValidate(List<OrderRowModel> list2chk)
|
|
{
|
|
int numDone = 0;
|
|
// verifica preliminare: serve SSE stato e estimate non corrispondono...
|
|
var list2fix = list2chk
|
|
.Where(x => x.OrderRowState == OrderStates.Created && !string.IsNullOrEmpty(x.ProdEstimate))
|
|
.ToList();
|
|
if (list2fix.Any())
|
|
{
|
|
// per ogni record processo intera validazione
|
|
foreach (var item in list2fix)
|
|
{
|
|
bool fatto = await OrderRowUpsertProdEst(item.OrderRowUID, item.ProdEstimate);
|
|
numDone += fatto ? 1 : 0;
|
|
}
|
|
}
|
|
return numDone;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua update stato await BOM/PRICE per l'Ordine indicato
|
|
/// </summary>
|
|
/// <param name="orderRowID">ID singola riga ordine</param>
|
|
/// <param name="awaitBom">Se non nullo è il nuovo stato await BOM</param>
|
|
/// <param name="awaitPrice">Se non nullo è stato await Price</param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderRowUpdateAwaitState(int orderRowID, bool? awaitBom, bool? awaitPrice)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero righe ordine...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowID == orderRowID)
|
|
.FirstOrDefault();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.AwaitBom = awaitBom ?? currRec.AwaitBom;
|
|
currRec.AwaitPrice = awaitPrice ?? currRec.AwaitPrice;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowUpdateAwaitState{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorno sul DB i dati del file associato
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderRowUpdateFileData(OrderRowModel updRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero righe offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowID == updRec.OrderRowID)
|
|
.FirstOrDefault();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.FileName = updRec.FileName;
|
|
currRec.FileResource = updRec.FileResource;
|
|
currRec.FileSize = updRec.FileSize;
|
|
currRec.SerStruct = updRec.SerStruct;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowUpdateFileData{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua update serStruct per l'Ordine indicato
|
|
/// </summary>
|
|
/// <param name="orderRowID">ID singola riga Ordine</param>
|
|
/// <param name="serStruct">Valore serializzatoe</param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderRowUpdateSerStruct(int orderRowID, string serStruct)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero righe offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowID == orderRowID)
|
|
.FirstOrDefault();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.SerStruct = serStruct;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowUpdateSerStruct{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorna stato riga ordine
|
|
/// </summary>
|
|
/// <param name="orderRowID"></param>
|
|
/// <param name="reqState"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderRowUpdateState(int orderRowID, OrderStates reqState)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero righe offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowID == orderRowID)
|
|
.FirstOrDefault();
|
|
|
|
// aggiorno parametri (se inviati)
|
|
if (currRec != null)
|
|
{
|
|
currRec.OrderRowState = reqState;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowUpdateState{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add riga ordine
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderRowUpsert(OrderRowModel updRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowID == updRec.OrderRowID)
|
|
.FirstOrDefault();
|
|
|
|
// se non trovo aggiungo
|
|
if (currRec == null)
|
|
{
|
|
dbCtx.DbSetOrderRow.Add(updRec);
|
|
// se ci sono record successivi li devo spostare...
|
|
var list2move = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderID == updRec.OrderID && x.RowNum >= updRec.RowNum)
|
|
.ToList();
|
|
if (list2move != null && list2move.Count > 0)
|
|
{
|
|
foreach (var item2move in list2move)
|
|
{
|
|
item2move.RowNum++;
|
|
dbCtx.Entry(item2move).State = EntityState.Modified;
|
|
}
|
|
}
|
|
}
|
|
// altrimenti aggiorno
|
|
else
|
|
{
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowUpsert{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record del solo ProdEstimate
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <param name="prodEstim"></param>
|
|
internal async Task<bool> OrderRowUpsertProdEst(string uID, string prodEstim)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowUID == uID)
|
|
.FirstOrDefault();
|
|
|
|
// se trovo aggiorno
|
|
if (currRec != null)
|
|
{
|
|
// genero WLD x controllo
|
|
var currWLD = new WorkLoadDetailDTO(currRec.OrderRowUID, currRec.ProdEstimate);
|
|
|
|
// faccio update in cascata dei record collegati x macchine e items
|
|
var listMachDb = dbCtx
|
|
.DbSetProdPlant
|
|
.Select(x => x.ProdPlantCod)
|
|
.ToList();
|
|
List<string> listMaccCurr = currWLD.MachineCalcResults.Select(x => x.Name).OrderBy(x => x).ToList() ?? new List<string>();
|
|
if (listMaccCurr != null && listMaccCurr.Any())
|
|
{
|
|
var listDiff = listMaccCurr.Except(listMachDb).ToList();
|
|
if (listDiff.Any())
|
|
{
|
|
foreach (var macch in listDiff)
|
|
{
|
|
dbCtx
|
|
.DbSetProdPlant
|
|
.Add(new ProductionPlantModel() { ProdPlantCod = macch, ProdPlantDescript = macch });
|
|
}
|
|
}
|
|
}
|
|
// resetta assegnazioni prodgroup agli items...
|
|
List<ProductionItemModel> listItem2upd = await dbCtx
|
|
.DbSetProdItem
|
|
.Where(x => x.OrderRowID == currRec.OrderRowID && x.ProdGroupID != null)
|
|
.ToListAsync();
|
|
if (listItem2upd != null && listItem2upd.Count > 0)
|
|
{
|
|
// li aggiorna tutti resettando ProdGroupID
|
|
listItem2upd.ForEach(x => x.ProdGroupID = null);
|
|
}
|
|
|
|
// elimina eventuali oggetti ProductionGroup precedenti
|
|
List<ProductionGroupModel> listProdGroup2Rem = await dbCtx
|
|
.DbSetProdGroup
|
|
.Where(x => x.OrderRowID == currRec.OrderRowID)
|
|
.ToListAsync();
|
|
// rimuovo...
|
|
if (listProdGroup2Rem != null && listProdGroup2Rem.Count > 0)
|
|
{
|
|
dbCtx.DbSetProdGroup.RemoveRange(listProdGroup2Rem);
|
|
}
|
|
|
|
/*----------------------------------
|
|
* Generazione ProdGroup
|
|
* FixMe ToDo !!!
|
|
*
|
|
* rifare onsiderando le REALI combinazioni scaturite x questo specifico caso e
|
|
* - ENUMERARE le combinazioni
|
|
* - ogni combinazione sarà un caso specifico tra 0...N dove N è il totale delle macchine gestite
|
|
* - i successivi calcoli di balance/stima saranno fatti x questo SPECIFICO ID GROUP così da fare prima... a sto punto GroupIP potrebbe essere un int 0...n oppure l'id del record... forse meglio il counter 0..n
|
|
*
|
|
* */
|
|
int grpIdx = 1;
|
|
// preparo x add nuovi ProductionGroup da analisi ritorno stime
|
|
List<ProductionGroupModel> listProdGroup2Add = new List<ProductionGroupModel>();
|
|
// 1: non lavorabili...
|
|
if (currWLD.ListUnWorkable.Count > 0)
|
|
{
|
|
// calcolo il dizionario degli elementi...
|
|
Dictionary<string, ProdMachineDetailDto> newWorkGroupList = new();
|
|
ProdMachineDetailDto detProd = new ProdMachineDetailDto()
|
|
{
|
|
TagList = currWLD.ListUnWorkable
|
|
};
|
|
newWorkGroupList.Add("", detProd);
|
|
string rawWGL = JsonConvert.SerializeObject(newWorkGroupList);
|
|
ProductionGroupModel newRec = new ProductionGroupModel()
|
|
{
|
|
OrderRowID = currRec.OrderRowID,
|
|
GrpIdx = grpIdx++,
|
|
WorkGroupListRaw = rawWGL
|
|
};
|
|
listProdGroup2Add.Add(newRec);
|
|
}
|
|
|
|
// dizionario x macchina delle parts LAVORABILI su impianto..
|
|
var machineTags = currWLD.MachineCalcResults
|
|
.ToDictionary(
|
|
m => m.Name,
|
|
m => m.PartList
|
|
.Where(p => p.CalcResult == EgwCoreLib.Lux.Core.Enums.PartVerificationResult.MACHINABLE)
|
|
.ToList()
|
|
);
|
|
|
|
// ciclo x tutte le combinazioni di gruppi lavorabilità...
|
|
foreach (var item in currWLD.LoadDetail)
|
|
{
|
|
// calcolo il dizionario degli elementi...
|
|
Dictionary<string, ProdMachineDetailDto> newWorkGroupList = new();
|
|
foreach (var machineName in item.Machines)
|
|
{
|
|
decimal effectiveTime = 0;
|
|
// Recuperiamo i dati della macchina dal dizionario
|
|
if (machineTags.TryGetValue(machineName, out var machineParts))
|
|
{
|
|
// Creiamo un set dei tag del gruppo per una ricerca veloce O(1)
|
|
var groupTagsSet = item.Tags.ToHashSet();
|
|
|
|
// Sommiamo il tempo solo per i pezzi che appartengono a questo gruppo
|
|
effectiveTime = machineParts
|
|
.Where(p => groupTagsSet.Contains(p.Tag))
|
|
.Sum(p => p.Time);
|
|
}
|
|
|
|
ProdMachineDetailDto detProd = new ProdMachineDetailDto()
|
|
{
|
|
TagList = item.Tags,
|
|
Time = effectiveTime // Tempo reale specifico per questa macchina/gruppo
|
|
};
|
|
newWorkGroupList.Add(machineName, detProd);
|
|
}
|
|
string rawWGL = JsonConvert.SerializeObject(newWorkGroupList);
|
|
ProductionGroupModel newRec = new ProductionGroupModel()
|
|
{
|
|
OrderRowID = currRec.OrderRowID,
|
|
GrpIdx = grpIdx++,
|
|
WorkGroupListRaw = rawWGL
|
|
};
|
|
listProdGroup2Add.Add(newRec);
|
|
}
|
|
// aggiungo i record...
|
|
dbCtx.DbSetProdGroup.AddRange(listProdGroup2Add);
|
|
|
|
// aggiorno info Estimation, tempi e stato
|
|
currRec.ProdEstimate = prodEstim;
|
|
if (!string.IsNullOrEmpty(prodEstim))
|
|
{
|
|
currRec.OrderRowState = OrderStates.Estimated;
|
|
}
|
|
var totEstim = listProdGroup2Add.Sum(x => x.TotalEstimTime);
|
|
currRec.ProdEstimTime = totEstim;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderRowUpsertProdEst{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> OrderUpsert(OrderModel updRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// recupero offerta...
|
|
var currRec = dbCtx
|
|
.DbSetOrder
|
|
.Where(x => x.OrderID == updRec.OrderID)
|
|
.FirstOrDefault();
|
|
|
|
// se non trovo aggiungo
|
|
if (currRec == null)
|
|
{
|
|
dbCtx.DbSetOrder.Add(updRec);
|
|
}
|
|
// altrimenti aggiorno
|
|
else
|
|
{
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante OrderUpsert{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco record Fasi da DB
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<PhaseModel>> PhasesGetAllAsync()
|
|
{
|
|
List<PhaseModel> dbResult = new List<PhaseModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetPhase
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante PhasesGetAllAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco record ProductionGroup dato OrderRow
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<ProductionGroupModel>> ProdGroupByOrderRow(int OrderRowID)
|
|
{
|
|
List<ProductionGroupModel> dbResult = new List<ProductionGroupModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetProdGroup
|
|
.Where(x => x.OrderRowID == OrderRowID)
|
|
.Include(i => i.ItemsNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdGroupByOrderRow{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco record ProductionGroup dato Stato dell'OrderRow
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<ProductionGroupModel>> ProdGroupByOrderState(OrderStates reqState)
|
|
{
|
|
List<ProductionGroupModel> dbResult = new List<ProductionGroupModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetProdGroup
|
|
.Include(o => o.OrderRowNav)
|
|
.Where(x => x.OrderRowNav.OrderRowState == reqState)
|
|
.Include(i => i.ItemsNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdGroupByOrderState{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record di un singolo ProdGroup da fase Balance
|
|
/// </summary>
|
|
/// <param name="uID">UID dell'item offerta di cui si è ricevuto l'oggetto Balance'</param>
|
|
/// <param name="rGroup">Prod Group di riferimento</param>
|
|
/// <param name="rawBalance"></param>
|
|
internal async Task<bool> ProdGroupUpsertBalance(string uID, string rGroup, string rawBalance)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// Tentativo di deserializzazione
|
|
var data = JsonConvert.DeserializeObject<Dictionary<string, ProdMachineDetailDto>>(rawBalance);
|
|
// proseguo solo se è valida la deserializzazione...
|
|
if (data != null)
|
|
{
|
|
// Togliamo la 'G' e convertiamo in int (gestisce automaticamente "01" -> 1)
|
|
int grpIdx = int.Parse(rGroup.TrimStart('G'));
|
|
// recupero ord row (parent)...
|
|
var ordRowRec = dbCtx
|
|
.DbSetOrderRow
|
|
.Where(x => x.OrderRowUID == uID)
|
|
.FirstOrDefault();
|
|
if (ordRowRec != null)
|
|
{
|
|
// recupero record specifico
|
|
var currRec = dbCtx
|
|
.DbSetProdGroup
|
|
.Where(x => x.OrderRowID == ordRowRec.OrderRowID && x.GrpIdx == grpIdx)
|
|
.FirstOrDefault();
|
|
|
|
// se trovato aggiorno
|
|
if (currRec != null)
|
|
{
|
|
currRec.WorkGroupListRaw = rawBalance;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
// altrimenti aggiungo
|
|
else
|
|
{
|
|
ProductionGroupModel newRec = new ProductionGroupModel()
|
|
{
|
|
OrderRowID = ordRowRec.OrderRowID,
|
|
GrpIdx = grpIdx,
|
|
WorkGroupListRaw = rawBalance
|
|
};
|
|
dbCtx
|
|
.DbSetProdGroup
|
|
.Add(newRec);
|
|
}
|
|
|
|
// segno ordine come Assigned se non lo fosse...
|
|
if (ordRowRec.OrderRowState != OrderStates.Assigned)
|
|
{
|
|
ordRowRec.OrderRowState = OrderStates.Assigned;
|
|
dbCtx.Entry(ordRowRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo TUTTI i cambiamenti...
|
|
var result = await dbCtx.SaveChangesAsync();
|
|
answ = result > 0;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdGroupUpsertBalance{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assegnazione in blocco degli item agli ODL corrispondenti
|
|
/// </summary>
|
|
/// <param name="dbList"></param>
|
|
/// <param name="dictParts"></param>
|
|
/// <returns></returns>
|
|
internal async Task<int> ProdItem2ODL_AssignAsync(List<ProductionODLModel> dbList, Dictionary<(int phaseId, int resId, string machine, int index), List<string>> dictParts)
|
|
{
|
|
int totalCreated = 0;
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// 1. Recuperiamo tutti i ProdBatchID coinvolti per fare una sola query
|
|
List<int> batchIds = dbList.Select(o => o.ProdBatchID).Distinct().ToList();
|
|
|
|
if (batchIds != null && batchIds.Count > 0)
|
|
{
|
|
// 2. Carichiamo in memoria i ProdItem necessari (solo ID e Tag per risparmiare RAM)
|
|
var itemsList = await dbCtx.DbSetProdItem
|
|
.Where(x => batchIds.Contains(x.ProdBatchID ?? 0) && x.ProdItemTag != null && x.ProdItemTag != "")
|
|
.Select(x => new { x.ProdItemID, x.ProdItemTag })
|
|
.ToListAsync();
|
|
|
|
// 1. Usiamo il "!" (null-forgiving operator) dopo x.ProdItemTag
|
|
// perché il filtro .Where sopra garantisce che non sia null.
|
|
var itemLookup = itemsList
|
|
.GroupBy(x => x.ProdItemTag!)
|
|
.ToDictionary(
|
|
g => g.Key,
|
|
g => g.First().ProdItemID,
|
|
StringComparer.OrdinalIgnoreCase
|
|
);
|
|
|
|
using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
|
try
|
|
{
|
|
var relationsToInsert = new List<ProductionItem2ODLModel>();
|
|
|
|
foreach (var odl in dbList)
|
|
{
|
|
var key = (odl.PhaseID ?? 0, odl.ResourceID ?? 0, odl.ProdPlantCod, odl.Index);
|
|
|
|
if (dictParts.TryGetValue(key, out List<string> tagList))
|
|
{
|
|
foreach (var tag in tagList)
|
|
{
|
|
// 3. Cerchiamo l'ID corrispondente al tag nel nostro lookup locale
|
|
if (itemLookup.TryGetValue(tag, out int realItemId))
|
|
{
|
|
relationsToInsert.Add(new ProductionItem2ODLModel
|
|
{
|
|
ProdODLID = odl.ProdODLID,
|
|
ProdItemID = realItemId,
|
|
DtAssign = DateTime.Now
|
|
});
|
|
}
|
|
else
|
|
{
|
|
//Log.Warning($"Tag {tag} non trovato nel database per i batch selezionati.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (relationsToInsert.Any())
|
|
{
|
|
await dbCtx.DbSetProdItem2ODL.AddRangeAsync(relationsToInsert);
|
|
totalCreated = relationsToInsert.Count;
|
|
await dbCtx.SaveChangesAsync();
|
|
}
|
|
|
|
await transaction.CommitAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await transaction.RollbackAsync();
|
|
Log.Error($"Errore nel salvataggio relazioni ODL-Parts: {exc.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
return totalCreated;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue assegnazione bulk dei ProdItem ad un unico ProdBatch parent (per ora totale x RigaOrd)
|
|
/// </summary>
|
|
/// <param name="OrderRowId"></param>
|
|
/// <param name="ProdBatchId"></param>
|
|
/// <returns></returns>
|
|
internal async Task<int> ProdItemBulkAssignProdBatch(int OrderRowId, int ProdBatchId)
|
|
{
|
|
int totalUpdated = 0;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
|
try
|
|
{
|
|
int rowsAffected = await dbCtx.DbSetProdItem
|
|
.Where(p => p.OrderRowID == OrderRowId)
|
|
.ExecuteUpdateAsync(setters => setters
|
|
.SetProperty(p => p.ProdBatchID, ProdBatchId)
|
|
);
|
|
|
|
totalUpdated += rowsAffected;
|
|
await transaction.CommitAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await transaction.RollbackAsync();
|
|
Log.Error($"Eccezione durante ProdItemBulkAssignProdBatch{Environment.NewLine}{exc}");
|
|
//throw;
|
|
}
|
|
}
|
|
return totalUpdated;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue assegnazione bulk dei ProdItem ad un unico ProdGroup parent
|
|
/// </summary>
|
|
/// <param name="OrderRowId"></param>
|
|
/// <param name="ProdGroupId"></param>
|
|
/// <param name="itemsToAssign"></param>
|
|
/// <returns></returns>
|
|
internal async Task<int> ProdItemBulkAssignProdGroup(int OrderRowId, int ProdGroupId, Dictionary<string, double> itemsToAssign)
|
|
{
|
|
int totalUpdated = 0;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
|
try
|
|
{
|
|
foreach (var entry in itemsToAssign)
|
|
{
|
|
// Esegue un UPDATE diretto: UPDATE production_item SET ProdAssignID = x, EstimTime = y WHERE ProdItemTag = z
|
|
int rowsAffected = await dbCtx.DbSetProdItem
|
|
.Where(p => p.OrderRowID == OrderRowId && p.ProdItemTag == entry.Key)
|
|
.ExecuteUpdateAsync(setters => setters
|
|
.SetProperty(p => p.ProdGroupID, ProdGroupId)
|
|
.SetProperty(p => p.EstimTime, entry.Value)
|
|
);
|
|
|
|
totalUpdated += rowsAffected;
|
|
}
|
|
await transaction.CommitAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await transaction.RollbackAsync();
|
|
Log.Error($"Eccezione durante ProdItemBulkAssignProdGroup{Environment.NewLine}{exc}");
|
|
//throw;
|
|
}
|
|
}
|
|
return totalUpdated;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco ProdItem dato OrderRow
|
|
/// </summary>
|
|
/// <param name="orderRowId"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<ProductionItemModel>> ProdItemByOrderRow(int orderRowId)
|
|
{
|
|
List<ProductionItemModel> dbResult = new List<ProductionItemModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetProdItem
|
|
.Where(x => x.OrderRowID == orderRowId)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdItemByOrderRow{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset impostazione ProdItem x ripartire senza setting ProdGroup
|
|
/// </summary>
|
|
/// <param name="orderRowID"></param>
|
|
/// <returns></returns>
|
|
internal async Task<int> ProdItemResetProdGroup(int orderRowID)
|
|
{
|
|
int numItem = 0;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
numItem = await dbCtx.DbSetProdItem
|
|
.Where(p => p.OrderRowID == orderRowID)
|
|
.ExecuteUpdateAsync(setters => setters
|
|
.SetProperty(p => p.ProdGroupID, (int?)null)
|
|
.SetProperty(p => p.EstimTime, 0)
|
|
);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdItemResetProdGroup{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return numItem;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco PODL non assegnati con struttura DTO appiattita
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<OdlAssignDto>?> ProdOdlAssignGetAsync()
|
|
{
|
|
List<OdlAssignDto>? dbResults = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResults = await dbCtx.DbSetProdODL
|
|
.Where(x => !x.DateAssign.HasValue)
|
|
.Select(odl => new OdlAssignDto
|
|
{
|
|
Envir = odl.ProdBatchNav.Envir,
|
|
ProdODLID = odl.ProdODLID,
|
|
Description = odl.Description,
|
|
EstimTime = odl.EstimTime,
|
|
Index = odl.Index,
|
|
OdlTag = odl.OdlTag,
|
|
PhaseID = odl.PhaseID,
|
|
ProdBatchID = odl.ProdBatchID,
|
|
ProdPlantCod = odl.ProdPlantCod,
|
|
Qty = odl.Qty,
|
|
ResourceID = odl.ResourceID,
|
|
ItemList = odl.Item2OdlNav.Select(i => new ItemAssignDto
|
|
{
|
|
ProdItemID = i.ProdItemID,
|
|
OrderID = i.ProductionItemNav.OrderRowNav.OrderNav.OrderID,
|
|
OrderRowID = i.ProductionItemNav.OrderRowNav.OrderRowID,
|
|
OrderTag = i.ProductionItemNav.OrderRowNav.OrderNav.OrderCode,
|
|
OrderRowTag = i.ProductionItemNav.OrderRowNav.OrderRowCode,
|
|
ProdItemTag = i.ProductionItemNav.ProdItemTag ?? "***"
|
|
}).ToList()
|
|
})
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProductionOdlUnassignAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResults;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero record ProdOdl dato Tag/uID
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <returns></returns>
|
|
internal async Task<ProductionODLModel?> ProdOdlGetByUidAsync(string uID)
|
|
{
|
|
ProductionODLModel? answ = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
answ = await dbCtx
|
|
.DbSetProdODL
|
|
.Where(x => x.OdlTag == uID)
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdOdlGetByUidAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorna record ProdOdl (se trovato) con BOM (raw) ricevuta
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <param name="bomRaw"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> ProdOdlUpdateBomAsync(string uID, string bomRaw)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetProdODL
|
|
.Where(x => x.OdlTag == uID)
|
|
.FirstOrDefault();
|
|
// se trovato --> salvo BOM e calcolo costi
|
|
if (currRec != null)
|
|
{
|
|
currRec.RawBoM = bomRaw;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo...
|
|
var result = dbCtx.SaveChanges();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdOdlUpdateBomAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorna record ProdOdl (se trovato) con ItemListRaw (raw) inviata x calcolo PROD
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <param name="itemListRaw"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> ProdOdlUpdateItemRawAsync(string uID, string itemListRaw)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetProdODL
|
|
.Where(x => x.OdlTag == uID)
|
|
.FirstOrDefault();
|
|
// se trovato --> salvo BOM e calcolo costi
|
|
if (currRec != null)
|
|
{
|
|
currRec.RawItemRawList = itemListRaw;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo...
|
|
var result = dbCtx.SaveChanges();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdOdlUpdateItemRawAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiorna record ProdOdl (se trovato) con RawMaterialList (raw) ricevuta da calcolo PROD
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <param name="materialListRaw"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> ProdOdlUpdateRawMaterialAsync(string uID, string materialListRaw)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetProdODL
|
|
.Where(x => x.OdlTag == uID)
|
|
.FirstOrDefault();
|
|
// se trovato --> salvo BOM e calcolo costi
|
|
if (currRec != null)
|
|
{
|
|
currRec.RawMaterials = materialListRaw;
|
|
dbCtx.Entry(currRec).State = EntityState.Modified;
|
|
}
|
|
|
|
// salvo...
|
|
var result = dbCtx.SaveChanges();
|
|
answ = result > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdOdlUpdateRawMaterialAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
internal async Task<List<ProductionPlantModel>> ProdPlantGetAllAsync()
|
|
{
|
|
List<ProductionPlantModel> dbResult = new List<ProductionPlantModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetProdPlant
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProdPlantGetAllAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creazione di un Batch con relativo Tag e info x creazione ODL correlati
|
|
/// </summary>
|
|
/// <param name="newRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<ProductionBatchModel?> ProductionBatchCreateAsync(ProductionBatchModel newRec)
|
|
{
|
|
ProductionBatchModel dbResult = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
// Definiamo i parametri di input
|
|
var pDesc = new MySqlParameter("@pDescription", newRec.Description ?? (object)DBNull.Value);
|
|
var pDate = new MySqlParameter("@pDueDate", newRec.DueDate);
|
|
var pPref = new MySqlParameter("@pPrefix", "BC.");
|
|
var pYear = new MySqlParameter("@pYear", newRec.DueDate.Year);
|
|
var pEnv = new MySqlParameter("@pEnv", newRec.Envir);
|
|
|
|
// Eseguiamo la procedura e mappiamo il risultato direttamente sul modello
|
|
// Nota: DbSetProdBatch deve essere configurato nel DbContext
|
|
var result = await dbCtx
|
|
.DbSetProdBatch
|
|
.FromSqlRaw("CALL stp_ProdBatch_insert(@pDescription, @pDueDate, @pPrefix, @pYear, @pEnv)", pDesc, pDate, pPref, pYear, pEnv)
|
|
.ToListAsync();
|
|
|
|
dbResult = result.FirstOrDefault() ?? new ProductionBatchModel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception("Errore durante ProductionBatchCreateAsync", ex);
|
|
}
|
|
return dbResult;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Insert sul DB di un elenco ODL con calcolo della relativa KEY a cui poter, successivamente, collegare i record child (items)
|
|
/// </summary>
|
|
/// <param name="listOdl2ins"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="Exception"></exception>
|
|
internal async Task<List<ProductionODLModel>> ProductionOdlCreateAsync(List<ProductionODLModel> listOdl2ins)
|
|
{
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// avvio transazione
|
|
using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
|
|
|
try
|
|
{
|
|
int cYear = DateTime.Today.Year;
|
|
|
|
// insert in blocco
|
|
dbCtx.DbSetProdODL.AddRange(listOdl2ins);
|
|
|
|
// 3. Salvataggio massivo
|
|
// EF Core 8 ottimizzerà gli insert in batch dove possibile
|
|
await dbCtx.SaveChangesAsync();
|
|
|
|
// stored update Tags
|
|
var pProdBatchID = new MySqlParameter("@pDueDate", listOdl2ins.FirstOrDefault()?.ProdBatchID ?? 0);
|
|
var pPref = new MySqlParameter("@pPrefix", "ODL.");
|
|
var pYear = new MySqlParameter("@pYear", cYear);
|
|
await dbCtx.Database.ExecuteSqlRawAsync("CALL stp_ProdOdl_UpdateTag(@pProdBatchID, @pPrefix, @pYear)", pProdBatchID, pPref, pYear);
|
|
|
|
// 4. Conferma transazione
|
|
await transaction.CommitAsync();
|
|
|
|
// A questo punto, ogni oggetto in 'listOdl2ins' ha il ProdODLID aggiornato dal DB
|
|
return listOdl2ins;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await transaction.RollbackAsync();
|
|
// Logga l'errore secondo le tue necessità
|
|
throw new Exception("Errore durante la creazione massiva degli ODL", ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco PODL non assegnati
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<ProductionODLModel>?> ProductionOdlUnassignAsync()
|
|
{
|
|
List<ProductionODLModel>? dbRestults = null;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbRestults = await dbCtx
|
|
.DbSetProdODL
|
|
.Where(x => !x.DateAssign.HasValue)
|
|
.Include(x => x.Item2OdlNav)
|
|
//.ThenInclude(i => i.ProductionItemNav)
|
|
//.ThenInclude(o => o.OrderRowNav)
|
|
//.ThenInclude(o => o.OrderNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ProductionOdlUnassignAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbRestults;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Eliminazione record
|
|
/// </summary>
|
|
/// <param name="rec2del"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> ResourcesDeleteAsync(ResourceModel rec2del)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetResource
|
|
.Where(x => rec2del.ResourceID > 0 && x.ResourceID == rec2del.ResourceID)
|
|
.FirstOrDefault();
|
|
// se trovato --> elimino
|
|
if (currRec != null)
|
|
{
|
|
dbCtx.DbSetResource.Remove(rec2del);
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ResourcesDeleteAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco record risorse da DB
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<ResourceModel>> ResourcesGetAllAsync()
|
|
{
|
|
List<ResourceModel> dbResult = new List<ResourceModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetResource
|
|
.Include(d => d.DriverNav)
|
|
.Include(j => j.JobStepNav)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ResourcesGetAllAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add record
|
|
/// </summary>
|
|
/// <param name="upsRec"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> ResourcesUpsertAsync(ResourceModel upsRec)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
var currRec = dbCtx
|
|
.DbSetResource
|
|
.Where(x => upsRec.ResourceID > 0 && x.ResourceID == upsRec.ResourceID)
|
|
.FirstOrDefault();
|
|
// se trovato --> aggiorno
|
|
if (currRec != null)
|
|
{
|
|
dbCtx.Entry(currRec).CurrentValues.SetValues(upsRec);
|
|
}
|
|
// se mancasse --> aggiungo
|
|
else
|
|
{
|
|
dbCtx.DbSetResource.Add(upsRec);
|
|
}
|
|
// salvo...
|
|
int numAct = await dbCtx.SaveChangesAsync();
|
|
answ = numAct > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante ResourcesUpsertAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue merge dei dati nella tab profili del DB con le info accessorie...
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <param name="execEnvironment"></param>
|
|
/// <param name="rawContent"></param>
|
|
/// <returns></returns>
|
|
internal async Task<bool> SaveProfileListAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string rawContent)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// solo se ho qualcosa da controllare...
|
|
if (!string.IsNullOrEmpty(rawContent))
|
|
{
|
|
// in primis recupero profili attuali
|
|
var dbList = await dbCtx
|
|
.DbSetConfProfile
|
|
.ToListAsync();
|
|
|
|
// ciclo sul contenuto ricevuto, se mancasse aggiungo!
|
|
List<string> list2check = JsonConvert.DeserializeObject<List<string>>(rawContent) ?? new List<string>();
|
|
List<ProfileModel> rec2ins = new List<ProfileModel>();
|
|
foreach (var item in list2check)
|
|
{
|
|
if (!dbList.Any(x => x.Code == item))
|
|
{
|
|
rec2ins.Add(new ProfileModel() { Code = item, Description = $"{item} - NEW" });
|
|
}
|
|
}
|
|
|
|
// se ho dati li inserisco...
|
|
if (rec2ins.Count > 0)
|
|
{
|
|
dbCtx.DbSetConfProfile.AddRange(rec2ins);
|
|
// salvo...
|
|
int numDone = await dbCtx.SaveChangesAsync();
|
|
answ = numDone > 0;
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio info serializzate x soglie e dati opzionali sul DB
|
|
/// </summary>
|
|
/// <param name="uID"></param>
|
|
/// <param name="execEnvironment"></param>
|
|
/// <param name="rawThreshold"></param>
|
|
/// <param name="rawData"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
internal async Task<bool> SaveProfileThreshAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string rawThreshold, string rawData)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// solo se ho qualcosa da controllare...
|
|
if (!string.IsNullOrEmpty(rawThreshold) || !string.IsNullOrEmpty(rawData))
|
|
{
|
|
// in primis recupero profilo da aggiornare
|
|
var dbRec = await dbCtx
|
|
.DbSetConfProfile
|
|
.Where(x => x.Code == uID)
|
|
.FirstOrDefaultAsync();
|
|
|
|
// se ho record aggiorno...
|
|
if (dbRec != null)
|
|
{
|
|
dbRec.ProfDataRaw = rawData;
|
|
dbRec.ThreshDataRaw = rawThreshold;
|
|
dbCtx.Entry(dbRec).State = EntityState.Modified;
|
|
}
|
|
// alrimenti creo + aggiorno
|
|
else
|
|
{
|
|
dbCtx.DbSetConfProfile.Add(new ProfileModel()
|
|
{
|
|
Code = uID,
|
|
Description = $"{uID} - NEW PROFILE",
|
|
ProfDataRaw = rawData,
|
|
ThreshDataRaw = rawThreshold
|
|
});
|
|
}
|
|
// salvo...
|
|
int numDone = await dbCtx.SaveChangesAsync();
|
|
answ = numDone > 0;
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco da DB delel stats aggregate dato periodo inizio/fine
|
|
/// </summary>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<StatsAggregatedModel>> StatsAggrGetAsync(DateTime dtStart, DateTime dtEnd)
|
|
{
|
|
List<StatsAggregatedModel> answ = new List<StatsAggregatedModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// recupero ed ordino per data-ora
|
|
answ = await dbCtx
|
|
.DbSetStatsAggr
|
|
.Where(x => x.Hour >= dtStart && x.Hour <= dtEnd)
|
|
.AsNoTracking()
|
|
.OrderBy(x => x.Hour)
|
|
.ToListAsync();
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Range periodo per chiamate aggregate
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<Utils.DtUtils.Periodo> StatsAggrRangeAsync()
|
|
{
|
|
Utils.DtUtils.Periodo answ = new Utils.DtUtils.Periodo(Utils.DtUtils.PeriodSet.Today);
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
var query = dbCtx.DbSetStatsAggr.AsQueryable();
|
|
|
|
var minHour = await query.MinAsync(x => x.Hour);
|
|
var maxHour = await query.MaxAsync(x => x.Hour);
|
|
answ.Inizio = minHour;
|
|
answ.Fine = maxHour;
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue insert statistiche aggregate sul DB
|
|
/// </summary>
|
|
/// <param name="listRecords">Elenco dei record da inserire</param>
|
|
/// <param name="removeOld">Se true preventivamente elimina record nel periodo richiesto</param>
|
|
/// <returns></returns>
|
|
internal async Task<long> StatsAggrUpsertAsync(List<StatsAggregatedModel> listRecords, bool removeOld)
|
|
{
|
|
int answ = 0;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// in primis se richiesto calcolo range periodo e svuoto...
|
|
if (removeOld)
|
|
{
|
|
var firstRec = listRecords.OrderBy(x => x.Hour).FirstOrDefault();
|
|
var lastRec = listRecords.OrderByDescending(x => x.Hour).FirstOrDefault();
|
|
|
|
if (firstRec != null && lastRec != null)
|
|
{
|
|
DateTime startDate = firstRec.Hour;
|
|
DateTime endDate = lastRec.Hour;
|
|
// uso direttamente ExecuteDelete
|
|
await dbCtx
|
|
.DbSetStatsAggr
|
|
.Where(x => x.Hour >= startDate && x.Hour <= endDate)
|
|
.ExecuteDeleteAsync();
|
|
}
|
|
}
|
|
|
|
// ora preparo inserimento massivo
|
|
await dbCtx
|
|
.DbSetStatsAggr
|
|
.AddRangeAsync(listRecords);
|
|
|
|
// salvo!
|
|
answ = await dbCtx.SaveChangesAsync();
|
|
|
|
// libero memoria del changeTracker
|
|
dbCtx.ChangeTracker.Clear();
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera dati stats di dettaglio dato filtro envir/tipo (opzionali) e periodo
|
|
/// </summary>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <param name="sEnvir"></param>
|
|
/// <param name="sType"></param>
|
|
/// <returns></returns>
|
|
internal async Task<List<StatsDetailModel>> StatsDetailModelGetAsync(DateTime dtStart, DateTime dtEnd, string sEnvir = "", string sType = "")
|
|
{
|
|
List<StatsDetailModel> answ = new List<StatsDetailModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// recupero ed ordino per data-ora
|
|
var query = dbCtx.DbSetStatsDet
|
|
.Where(x => x.Hour >= dtStart && x.Hour <= dtEnd);
|
|
|
|
if (!string.IsNullOrEmpty(sEnvir))
|
|
query = query.Where(x => x.Environment == sEnvir);
|
|
|
|
if (!string.IsNullOrEmpty(sType))
|
|
query = query.Where(x => x.Type == sType);
|
|
|
|
answ = await query
|
|
.AsNoTracking()
|
|
.OrderBy(x => x.Hour)
|
|
.ThenBy(x => x.Environment)
|
|
.ThenBy(x => x.Type)
|
|
.ToListAsync();
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Range periodo x chiamate detail eventualmente filtrate
|
|
/// </summary>
|
|
/// <param name="sEnvir"></param>
|
|
/// <param name="sType"></param>
|
|
/// <returns></returns>
|
|
internal async Task<Utils.DtUtils.Periodo> StatsDetailModelRangeAsync(string sEnvir, string sType)
|
|
{
|
|
Utils.DtUtils.Periodo answ = new Utils.DtUtils.Periodo(Utils.DtUtils.PeriodSet.Today);
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
var query = dbCtx.DbSetStatsDet.AsQueryable();
|
|
|
|
if (!string.IsNullOrEmpty(sEnvir))
|
|
query = query.Where(x => x.Environment == sEnvir);
|
|
|
|
if (!string.IsNullOrEmpty(sType))
|
|
query = query.Where(x => x.Type == sType);
|
|
|
|
var minHour = await query.MinAsync(x => x.Hour);
|
|
var maxHour = await query.MaxAsync(x => x.Hour);
|
|
answ.Inizio = minHour;
|
|
answ.Fine = maxHour;
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue insert statistiche di dettaglio sul DB
|
|
/// </summary>
|
|
/// <param name="listRecords">Elenco dei record da inserire</param>
|
|
/// <param name="removeOld">Se true preventivamente elimina record nel periodo richiesto</param>
|
|
/// <returns></returns>
|
|
internal async Task<long> StatsDetailModelUpsertAsync(List<StatsDetailModel> listRecords, bool removeOld)
|
|
{
|
|
int answ = 0;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// in primis se richiesto calcolo range periodo e svuoto...
|
|
if (removeOld)
|
|
{
|
|
var firstRec = listRecords.OrderBy(x => x.Hour).FirstOrDefault();
|
|
var lastRec = listRecords.OrderByDescending(x => x.Hour).FirstOrDefault();
|
|
|
|
if (firstRec != null && lastRec != null)
|
|
{
|
|
DateTime startDate = firstRec.Hour;
|
|
DateTime endDate = lastRec.Hour;
|
|
// uso direttamente ExecuteDelete
|
|
await dbCtx
|
|
.DbSetStatsDet
|
|
.Where(x => x.Hour >= startDate && x.Hour <= endDate)
|
|
.ExecuteDeleteAsync();
|
|
}
|
|
}
|
|
|
|
// ora preparo inserimento massivo
|
|
await dbCtx
|
|
.DbSetStatsDet
|
|
.AddRangeAsync(listRecords);
|
|
|
|
// salvo!
|
|
answ = await dbCtx.SaveChangesAsync();
|
|
|
|
// libero memoria del changeTracker
|
|
dbCtx.ChangeTracker.Clear();
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco completo Tags
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal async Task<List<TagsModel>> TagsGetAllAsync()
|
|
{
|
|
List<TagsModel> dbResult = new List<TagsModel>();
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
try
|
|
{
|
|
dbResult = await dbCtx
|
|
.DbSetTags
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione durante TagsGetAllAsync{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
#if true
|
|
internal bool UpdateCodGroup(List<BomItemDTO> bomList)
|
|
{
|
|
bool answ = false;
|
|
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
|
using (DataLayerContext dbCtx = new DataLayerContext())
|
|
{
|
|
// in primis calcolo i distinct dei CodGroup x eventuale insert preventivo
|
|
List<string> distCodGroups = bomList
|
|
.Select(i => i.ClassCode)
|
|
.Distinct()
|
|
.Where(c => !string.IsNullOrWhiteSpace(c))
|
|
.ToList();
|
|
|
|
// recupero l'elenco degli itemGroup gestiti
|
|
var itemGroupList = dbCtx
|
|
.DbSetItemGroup
|
|
.ToList();
|
|
// elenco da inserire...
|
|
var codGroupsToInsert = distCodGroups
|
|
.Where(x => !itemGroupList.Any(i => i.CodGroup == x))
|
|
.Select(x => new ItemGroupModel() { CodGroup = x, Description = x })
|
|
.ToList();
|
|
// se ci sono inserisco!
|
|
if (codGroupsToInsert != null && codGroupsToInsert.Count > 0)
|
|
{
|
|
dbCtx
|
|
.DbSetItemGroup
|
|
.AddRange(codGroupsToInsert);
|
|
// salvo...
|
|
dbCtx.SaveChanges();
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
#endif
|
|
|
|
#endregion Internal Methods
|
|
|
|
#region Private Fields
|
|
|
|
private static IConfiguration _configuration;
|
|
|
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
#endregion Private Fields
|
|
}
|
|
} |