Gestione task EXT non producibili (con transaction bulk x mysql), parziale
This commit is contained in:
@@ -21,6 +21,49 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
{
|
||||
// manca costruttore parametrico contoller...
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Esegue assegnazione bulk dei ProdItem ad un unico ProdAssign parent
|
||||
/// </summary>
|
||||
/// <param name="ProdAssignId"></param>
|
||||
/// <param name="itemsToAssign"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<int> ProdItemBulkAssignItems(int ProdAssignId, 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 ProdLabel = z
|
||||
int rowsAffected = await dbCtx.DbSetProdItem
|
||||
.Where(p => p.ProdLabel == entry.Key)
|
||||
.ExecuteUpdateAsync(setters => setters
|
||||
.SetProperty(p => p.ProdAssignID, ProdAssignId)
|
||||
.SetProperty(p => p.EstimTime, entry.Value)
|
||||
);
|
||||
|
||||
totalUpdated += rowsAffected;
|
||||
}
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
Log.Error($"Eccezione durante ProdItemBulkAssignItems{Environment.NewLine}{exc}");
|
||||
//throw;
|
||||
}
|
||||
}
|
||||
return totalUpdated;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
internal async Task<List<EnvirParamModel>> ConfEnvirParamGetAllAsync()
|
||||
@@ -2665,7 +2708,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
catch (Exception exc)
|
||||
{
|
||||
#if false
|
||||
await transaction.RollbackAsync();
|
||||
await transaction.RollbackAsync();
|
||||
#endif
|
||||
Log.Error($"Eccezione durante OrderFromOffer{Environment.NewLine}{exc}");
|
||||
}
|
||||
@@ -2832,6 +2875,31 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
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>
|
||||
@@ -3072,31 +3140,6 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Upsert record
|
||||
/// </summary>
|
||||
@@ -3163,6 +3206,139 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco record ProductionAssign dato OrderRow
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal async Task<List<ProductionAssignModel>> ProdAssignByOrderRow(int OrderRowID)
|
||||
{
|
||||
List<ProductionAssignModel> dbResult = new List<ProductionAssignModel>();
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
dbResult = await dbCtx
|
||||
.DbSetProdAssign
|
||||
.Where(x => x.OrderRowID == OrderRowID)
|
||||
.Include(i => i.ItemsNav)
|
||||
.ToListAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante ProdAssignByOrderRow{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica esistenza record ProductionAssign per OrderRow dato elenco plant, creando i missing e tornando poi lista
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal async Task<List<ProductionAssignModel>> ProdAssignCheckExist(int OrderRowID, List<string> ListPlant)
|
||||
{
|
||||
List<ProductionAssignModel> dbResult = new List<ProductionAssignModel>();
|
||||
// Rimuoviamo i duplicati dalla lista in input a monte per evitare tentativi di inserimento doppi
|
||||
var uniqueInputPlants = ListPlant.Distinct().ToList();
|
||||
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
await using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
// record esistenti
|
||||
var existRec = await dbCtx.DbSetProdAssign
|
||||
.AsNoTracking()
|
||||
.Where(p => p.OrderRowID == OrderRowID)
|
||||
.Select(p => p.ProdPlantCod)
|
||||
.ToListAsync();
|
||||
|
||||
// elementi da inserire
|
||||
var plantsToAdd = uniqueInputPlants.Except(existRec).ToList();
|
||||
|
||||
if (plantsToAdd.Any())
|
||||
{
|
||||
// 3. Crea i nuovi oggetti
|
||||
var newAssignments = plantsToAdd.Select(plantCod => new ProductionAssignModel
|
||||
{
|
||||
OrderRowID = OrderRowID,
|
||||
ProdPlantCod = plantCod
|
||||
});
|
||||
|
||||
// 4. Aggiunta massiva e salvataggio
|
||||
await dbCtx.DbSetProdAssign.AddRangeAsync(newAssignments);
|
||||
await dbCtx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// recupero elenco
|
||||
dbResult = await dbCtx
|
||||
.DbSetProdAssign
|
||||
.Where(x => x.OrderRowID == OrderRowID)
|
||||
.Include(i => i.ItemsNav)
|
||||
.ToListAsync();
|
||||
// Conferma la transazione
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
Log.Error($"Eccezione durante ProdAssignCheckExist{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elimina record ProductionAssign + svincola record item dipendenti
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal async Task<bool> ProdAssignDelete(int ProdAssignID)
|
||||
{
|
||||
bool removed = false;
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
await using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
// 1. Carica il record parent con i relativi figli
|
||||
var parent = await dbCtx.DbSetProdAssign
|
||||
.Include(p => p.ItemsNav)
|
||||
.FirstOrDefaultAsync(p => p.ProdAssignID == ProdAssignID);
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
// 2. Disassociazione dei figli
|
||||
// Iteriamo sui figli e settiamo a null il riferimento al parent
|
||||
foreach (var item in parent.ItemsNav)
|
||||
{
|
||||
// Nota: La proprietà FK nel modello Item deve essere nullable (es. int?)
|
||||
item.ProdAssignID = null;
|
||||
}
|
||||
|
||||
// 3. Eliminazione del parent
|
||||
dbCtx.DbSetProdAssign.Remove(parent);
|
||||
|
||||
// 4. Salvataggio atomico
|
||||
await dbCtx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await transaction.CommitAsync();
|
||||
removed = true;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
Log.Error($"Eccezione durante ProdAssignDelete{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco ProdItem dato OrderRow
|
||||
/// </summary>
|
||||
|
||||
@@ -50,9 +50,6 @@ namespace EgwCoreLib.Lux.Data.DbModel.Production
|
||||
/// <summary>
|
||||
/// Etichetta dell'item
|
||||
/// </summary>
|
||||
#if false
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
|
||||
#endif
|
||||
public string ProdLabel { get; set; } = "";
|
||||
#if false
|
||||
public string ProdLabel
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>0.9.2512.2317</Version>
|
||||
<Version>0.9.2512.2411</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -65,22 +65,28 @@
|
||||
@if (DetailRecord.NumKo > 0)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="px-0">Non producibili: <span class="fw-bold px-1">@DetailRecord.NumKo</span></div>
|
||||
<div class="px-0"><button class="btn btn-danger">Send EXT <i class="fa-solid fa-triangle-exclamation"></i></button></div>
|
||||
<div class="col-9">Non producibili: <span class="fw-bold px-1">@DetailRecord.NumKo</span></div>
|
||||
<div class="col-3">
|
||||
<button class="btn btn-sm btn-danger w-100">Send EXT <i class="fa-solid fa-triangle-exclamation"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
@if (DetailRecord.NumOkVin > 0)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="px-0">Vincolati: <span class="fw-bold px-1">@DetailRecord.NumOkVin</span></div>
|
||||
<div class="px-0"><button class="btn btn-info">Assegna <i class="fa-solid fa-thumbtack"></i></button></div>
|
||||
<div class="col-9">Vincolati: <span class="fw-bold px-1">@DetailRecord.NumOkVin</span></div>
|
||||
<div class="col-3">
|
||||
<button class="btn btn-sm btn-info w-100">Assegna <i class="fa-solid fa-thumbtack"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
@if (DetailRecord.NumOk > 0)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<div class="px-0">Producibili ovunque: <span class="fw-bold px-1">@DetailRecord.NumOk</span></div>
|
||||
<div class="px-0"><button class="btn btn-success" @onclick="() => ToggleBalance(DetailRecord.ListWorkable)">Dividi <i class="fa-solid fa-scissors"></i></button></div>
|
||||
<div class="col-9">Producibili ovunque: <span class="fw-bold px-1">@DetailRecord.NumOk</span></div>
|
||||
<div class="col-3">
|
||||
<button class="btn btn-sm btn-success w-100" @onclick="() => ToggleBalance(DetailRecord.ListWorkable)">Dividi <i class="fa-solid fa-scissors"></i></button>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using EgwCoreLib.Lux.Core.Generic;
|
||||
using EgwCoreLib.Lux.Core.RestPayload;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using NLog.Targets.Wrappers;
|
||||
|
||||
namespace Lux.UI.Components.Compo.WorkLoad
|
||||
{
|
||||
@@ -97,6 +98,15 @@ namespace Lux.UI.Components.Compo.WorkLoad
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assegnazione item unworkable a EXT
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task SendUnworkExt()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>LUX - Web Windows MES</i>
|
||||
<h4>Versione: 0.9.2512.2318</h4>
|
||||
<h4>Versione: 0.9.2512.2411</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.9.2512.2318
|
||||
0.9.2512.2411
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>0.9.2512.2318</version>
|
||||
<version>0.9.2512.2411</version>
|
||||
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip</url>
|
||||
<changelog>http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
|
||||
Reference in New Issue
Block a user