From d0ea040b78ab626fedd4c15f85446f5e5874bf13 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Wed, 24 Dec 2025 12:18:30 +0100 Subject: [PATCH] Gestione task EXT non producibili (con transaction bulk x mysql), parziale --- .../Controllers/LuxController.cs | 228 ++++++++++++++++-- .../DbModel/Production/ProductionItemModel.cs | 3 - Lux.API/Lux.API.csproj | 2 +- .../Components/Compo/WorkLoad/TimeEstim.razor | 18 +- .../Compo/WorkLoad/TimeEstim.razor.cs | 10 + Resources/ChangeLog.html | 2 +- Resources/VersNum.txt | 2 +- Resources/manifest.xml | 2 +- 8 files changed, 228 insertions(+), 39 deletions(-) diff --git a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs index 91bca091..0bdd8bfa 100644 --- a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs +++ b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs @@ -21,6 +21,49 @@ namespace EgwCoreLib.Lux.Data.Controllers { // manca costruttore parametrico contoller... + #region Public Methods + + /// + /// Esegue assegnazione bulk dei ProdItem ad un unico ProdAssign parent + /// + /// + /// + /// + public async Task ProdItemBulkAssignItems(int ProdAssignId, Dictionary 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> 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; } + /// + /// Validazione record: + /// - controllo state vs estimate + /// - segnala il numero dei record aggiornati + /// + /// Elenco record da verificare + internal async Task OrderRowListValidate(List 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; + } + /// /// Effettua update stato await BOM/PRICE per l'Ordine indicato /// @@ -3072,31 +3140,6 @@ namespace EgwCoreLib.Lux.Data.Controllers return answ; } - /// - /// Validazione record: - /// - controllo state vs estimate - /// - segnala il numero dei record aggiornati - /// - /// Elenco record da verificare - internal async Task OrderRowListValidate(List 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; - } - /// /// Upsert record /// @@ -3163,6 +3206,139 @@ namespace EgwCoreLib.Lux.Data.Controllers return dbResult; } + /// + /// Elenco record ProductionAssign dato OrderRow + /// + /// + internal async Task> ProdAssignByOrderRow(int OrderRowID) + { + List dbResult = new List(); + //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; + } + + /// + /// Verifica esistenza record ProductionAssign per OrderRow dato elenco plant, creando i missing e tornando poi lista + /// + /// + internal async Task> ProdAssignCheckExist(int OrderRowID, List ListPlant) + { + List dbResult = new List(); + // 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; + } + + /// + /// Elimina record ProductionAssign + svincola record item dipendenti + /// + /// + internal async Task 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; + } + /// /// Elenco ProdItem dato OrderRow /// diff --git a/EgwCoreLib.Lux.Data/DbModel/Production/ProductionItemModel.cs b/EgwCoreLib.Lux.Data/DbModel/Production/ProductionItemModel.cs index 7a2b32e8..c40c8bf9 100644 --- a/EgwCoreLib.Lux.Data/DbModel/Production/ProductionItemModel.cs +++ b/EgwCoreLib.Lux.Data/DbModel/Production/ProductionItemModel.cs @@ -50,9 +50,6 @@ namespace EgwCoreLib.Lux.Data.DbModel.Production /// /// Etichetta dell'item /// -#if false - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] -#endif public string ProdLabel { get; set; } = ""; #if false public string ProdLabel diff --git a/Lux.API/Lux.API.csproj b/Lux.API/Lux.API.csproj index 458d8a91..deae0c72 100644 --- a/Lux.API/Lux.API.csproj +++ b/Lux.API/Lux.API.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 0.9.2512.2317 + 0.9.2512.2411 diff --git a/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor b/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor index 726d8f88..4a350d38 100644 --- a/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor +++ b/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor @@ -65,22 +65,28 @@ @if (DetailRecord.NumKo > 0) {
  • -
    Non producibili: @DetailRecord.NumKo
    -
    +
    Non producibili: @DetailRecord.NumKo
    +
    + +
  • } @if (DetailRecord.NumOkVin > 0) {
  • -
    Vincolati: @DetailRecord.NumOkVin
    -
    +
    Vincolati: @DetailRecord.NumOkVin
    +
    + +
  • } @if (DetailRecord.NumOk > 0) {
  • -
    Producibili ovunque: @DetailRecord.NumOk
    -
    +
    Producibili ovunque: @DetailRecord.NumOk
    +
    + +
  • } diff --git a/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor.cs b/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor.cs index d884599e..8d55eae8 100644 --- a/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor.cs +++ b/Lux.UI/Components/Compo/WorkLoad/TimeEstim.razor.cs @@ -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 } } + /// + /// Assegnazione item unworkable a EXT + /// + /// + protected async Task SendUnworkExt() + { + // + } + #endregion Protected Methods #region Private Fields diff --git a/Resources/ChangeLog.html b/Resources/ChangeLog.html index e04114dd..7e72b26c 100644 --- a/Resources/ChangeLog.html +++ b/Resources/ChangeLog.html @@ -1,6 +1,6 @@ LUX - Web Windows MES -

    Versione: 0.9.2512.2318

    +

    Versione: 0.9.2512.2411


    Note di rilascio:
    • diff --git a/Resources/VersNum.txt b/Resources/VersNum.txt index a6082b57..b7f6c91e 100644 --- a/Resources/VersNum.txt +++ b/Resources/VersNum.txt @@ -1 +1 @@ -0.9.2512.2318 +0.9.2512.2411 diff --git a/Resources/manifest.xml b/Resources/manifest.xml index 84aa9e46..6d400441 100644 --- a/Resources/manifest.xml +++ b/Resources/manifest.xml @@ -1,6 +1,6 @@ - 0.9.2512.2318 + 0.9.2512.2411 http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html false