diff --git a/EgwCoreLib.Lux.Core/EgwCoreLib.Lux.Core.csproj b/EgwCoreLib.Lux.Core/EgwCoreLib.Lux.Core.csproj index fdc9023c..74d46620 100644 --- a/EgwCoreLib.Lux.Core/EgwCoreLib.Lux.Core.csproj +++ b/EgwCoreLib.Lux.Core/EgwCoreLib.Lux.Core.csproj @@ -21,8 +21,8 @@ - - + + diff --git a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs index 3e401d2a..6a130296 100644 --- a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs +++ b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs @@ -2,6 +2,7 @@ using EgwCoreLib.Lux.Data.DbModel.Config; using EgwCoreLib.Lux.Data.DbModel.Items; using EgwCoreLib.Lux.Data.DbModel.Sales; +using EgwCoreLib.Lux.Data.DbModel.Task; using EgwCoreLib.Lux.Data.DbModel.Utils; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -724,37 +725,6 @@ namespace EgwCoreLib.Lux.Data.Controllers return dbResult; } -#if false - /// - /// Elenco item Child da ID Parent (per sostituzione) - /// - /// ID parent (valido quindi >0) - /// - internal List ItemGetChild(int ItemIdParent) - { - List dbResult = new List(); - if (ItemIdParent > 0) - { - //using (DataLayerContext dbCtx = new DataLayerContext(configuration)) - using (DataLayerContext dbCtx = new DataLayerContext()) - { - try - { - dbResult = dbCtx - .DbSetItem - .Where(x => x.ItemID == ItemIdParent || x.ItemIDParent == ItemIdParent) - .ToList(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante ItemGetChild{Environment.NewLine}{exc}"); - } - } - } - return dbResult; - } -#endif - /// /// Elenco item alternativi da ID di un record (per sostituzione) /// @@ -1183,6 +1153,198 @@ namespace EgwCoreLib.Lux.Data.Controllers return answ; } + /// + /// Eliminazione record richiesto + /// + /// + /// + internal async Task 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) + { + dbCtx.DbSetJobTask.Remove(dbResult); + await dbCtx.SaveChangesAsync(); + } + } + catch (Exception exc) + { + Log.Error($"Eccezione durante JobTaskDeleteAsync{Environment.NewLine}{exc}"); + } + } + return result; + } + + /// + /// Recupera elenco Jobs (conf) da DB + /// + /// + internal async Task> JobTaskGetAllAsync() + { + List dbResult = new List(); + //using (DataLayerContext dbCtx = new DataLayerContext(_config)) + using (DataLayerContext dbCtx = new DataLayerContext()) + { + try + { + dbResult = await dbCtx + .DbSetJobTask + .Include(c => c.JobStepNav) + .ToListAsync(); + } + catch (Exception exc) + { + Log.Error($"Eccezione durante JobTaskGetAllAsync{Environment.NewLine}{exc}"); + } + } + return dbResult; + } + + /// + /// Esegue spostamento nell'ordinamento relativo alla classe + /// NB: verifica spostamento sia ammissibile: se primo rec non "sale", se ultimo non "scende"... + /// + /// + /// + /// + internal async Task 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.Ordinal - 1 : currRec.Ordinal + 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.Ordinal == newPos) + .FirstOrDefault(); + if (otherRec != null) + { + otherRec.Ordinal = currRec.Ordinal; + dbCtx.Entry(otherRec).State = EntityState.Modified; + currRec.Ordinal = 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; + } + +#if false + /// + /// Elenco item Child da ID Parent (per sostituzione) + /// + /// ID parent (valido quindi >0) + /// + internal List ItemGetChild(int ItemIdParent) + { + List dbResult = new List(); + if (ItemIdParent > 0) + { + //using (DataLayerContext dbCtx = new DataLayerContext(configuration)) + using (DataLayerContext dbCtx = new DataLayerContext()) + { + try + { + dbResult = dbCtx + .DbSetItem + .Where(x => x.ItemID == ItemIdParent || x.ItemIDParent == ItemIdParent) + .ToList(); + } + catch (Exception exc) + { + Log.Error($"Eccezione durante ItemGetChild{Environment.NewLine}{exc}"); + } + } + } + return dbResult; + } +#endif + + /// + /// Upsert record + /// + /// + /// + internal async Task 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; + } + /// /// Elenco completo offerte da DB /// diff --git a/EgwCoreLib.Lux.Data/DataLayerContext.cs b/EgwCoreLib.Lux.Data/DataLayerContext.cs index af58ebce..005c6e26 100644 --- a/EgwCoreLib.Lux.Data/DataLayerContext.cs +++ b/EgwCoreLib.Lux.Data/DataLayerContext.cs @@ -53,6 +53,7 @@ namespace EgwCoreLib.Lux.Data public virtual DbSet DbSetEnvirPar { get; set; } public virtual DbSet DbSetItemGroup { get; set; } + public virtual DbSet DbSetJobTask { get; set; } public virtual DbSet DbSetItem { get; set; } public virtual DbSet DbSetSellItem { get; set; } public virtual DbSet DbSetTags { get; set; } @@ -65,7 +66,7 @@ namespace EgwCoreLib.Lux.Data public virtual DbSet DbSetORDerRow { get; set; } public virtual DbSet DbSetResource { get; set; } public virtual DbSet DbSetPhase { get; set; } - public virtual DbSet DbSetJob { get; set; } + public virtual DbSet DbSetJob { get; set; } public virtual DbSet DbSetJobRow { get; set; } public virtual DbSet DbSetJobRowItem { get; set; } public virtual DbSet DbSetProdBatch { get; set; } diff --git a/EgwCoreLib.Lux.Data/DbModel/Items/SellingItemModel.cs b/EgwCoreLib.Lux.Data/DbModel/Items/SellingItemModel.cs index 921755d0..af073718 100644 --- a/EgwCoreLib.Lux.Data/DbModel/Items/SellingItemModel.cs +++ b/EgwCoreLib.Lux.Data/DbModel/Items/SellingItemModel.cs @@ -82,6 +82,6 @@ namespace EgwCoreLib.Lux.Data.DbModel.Items /// Navigazione Job/Cicli /// [ForeignKey("JobID")] - public virtual JobModel JobNav { get; set; } = null!; + public virtual JobTaskModel JobNav { get; set; } = null!; } } diff --git a/EgwCoreLib.Lux.Data/DbModel/Task/JobDriverConfigModel.cs b/EgwCoreLib.Lux.Data/DbModel/Task/JobDriverConfigModel.cs index 749c55fa..097b0cfc 100644 --- a/EgwCoreLib.Lux.Data/DbModel/Task/JobDriverConfigModel.cs +++ b/EgwCoreLib.Lux.Data/DbModel/Task/JobDriverConfigModel.cs @@ -63,7 +63,7 @@ namespace EgwCoreLib.Lux.Data.DbModel.Task /// Navigazione JOB /// [ForeignKey("JobID")] - public virtual JobModel JobNav { get; set; } = null!; + public virtual JobTaskModel JobNav { get; set; } = null!; /// /// Navigazione JobDriver diff --git a/EgwCoreLib.Lux.Data/DbModel/Task/JobStepModel.cs b/EgwCoreLib.Lux.Data/DbModel/Task/JobStepModel.cs index e0881858..88356d37 100644 --- a/EgwCoreLib.Lux.Data/DbModel/Task/JobStepModel.cs +++ b/EgwCoreLib.Lux.Data/DbModel/Task/JobStepModel.cs @@ -93,7 +93,7 @@ namespace EgwCoreLib.Lux.Data.DbModel.Task /// Navigazione Job/Cicli /// [ForeignKey("JobID")] - public virtual JobModel JobNav { get; set; } = null!; + public virtual JobTaskModel JobNav { get; set; } = null!; /// /// Navigazione Driver costo diff --git a/EgwCoreLib.Lux.Data/DbModel/Task/JobModel.cs b/EgwCoreLib.Lux.Data/DbModel/Task/JobTaskModel.cs similarity index 77% rename from EgwCoreLib.Lux.Data/DbModel/Task/JobModel.cs rename to EgwCoreLib.Lux.Data/DbModel/Task/JobTaskModel.cs index 036f2c66..f6a229b2 100644 --- a/EgwCoreLib.Lux.Data/DbModel/Task/JobModel.cs +++ b/EgwCoreLib.Lux.Data/DbModel/Task/JobTaskModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using EgwCoreLib.Lux.Data.DbModel.Utils; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; // @@ -10,7 +11,7 @@ namespace EgwCoreLib.Lux.Data.DbModel.Task /// Definizione macro dei Cicli di Lavoro / Job /// [Table("task_job")] - public class JobModel + public class JobTaskModel { /// /// ID del record @@ -28,14 +29,23 @@ namespace EgwCoreLib.Lux.Data.DbModel.Task /// public int Ordinal { get; set; } = 0; + /// + /// indica protezione cancellazione + /// + public bool Lock { get; set; } = false; + /// /// Navigation verso JobStep /// public virtual ICollection JobStepNav { get; set; } = new List(); /// - /// indica protezione cancellazione + /// Numero Step compresi /// - public bool Lock { get; set; } = false; + [NotMapped] + public int NumChild + { + get => JobStepNav?.Count ?? 0; + } } } diff --git a/EgwCoreLib.Lux.Data/EgwCoreLib.Lux.Data.csproj b/EgwCoreLib.Lux.Data/EgwCoreLib.Lux.Data.csproj index 60fe44c1..aef8dd92 100644 --- a/EgwCoreLib.Lux.Data/EgwCoreLib.Lux.Data.csproj +++ b/EgwCoreLib.Lux.Data/EgwCoreLib.Lux.Data.csproj @@ -27,7 +27,7 @@ - + diff --git a/EgwCoreLib.Lux.Data/Migrations/20251021091403_InitDb.Designer.cs b/EgwCoreLib.Lux.Data/Migrations/20251021091403_InitDb.Designer.cs index cb3b00d8..6eb13b49 100644 --- a/EgwCoreLib.Lux.Data/Migrations/20251021091403_InitDb.Designer.cs +++ b/EgwCoreLib.Lux.Data/Migrations/20251021091403_InitDb.Designer.cs @@ -2122,7 +2122,7 @@ namespace EgwCoreLib.Lux.Data.Migrations }); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Property("JobID") .ValueGeneratedOnAdd() @@ -2645,7 +2645,7 @@ namespace EgwCoreLib.Lux.Data.Migrations modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Items.SellingItemModel", b => { - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -2839,7 +2839,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany("JobStepNav") .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -2882,7 +2882,7 @@ namespace EgwCoreLib.Lux.Data.Migrations b.Navigation("OfferRowNav"); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Navigation("JobStepNav"); }); diff --git a/EgwCoreLib.Lux.Data/Migrations/20251024163741_AddStepDto.Designer.cs b/EgwCoreLib.Lux.Data/Migrations/20251024163741_AddStepDto.Designer.cs index eee3e215..b74da7e3 100644 --- a/EgwCoreLib.Lux.Data/Migrations/20251024163741_AddStepDto.Designer.cs +++ b/EgwCoreLib.Lux.Data/Migrations/20251024163741_AddStepDto.Designer.cs @@ -2212,7 +2212,7 @@ namespace EgwCoreLib.Lux.Data.Migrations }); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Property("JobID") .ValueGeneratedOnAdd() @@ -2735,7 +2735,7 @@ namespace EgwCoreLib.Lux.Data.Migrations modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Items.SellingItemModel", b => { - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -2929,7 +2929,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany("JobStepNav") .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -2977,7 +2977,7 @@ namespace EgwCoreLib.Lux.Data.Migrations b.Navigation("OrderRowNav"); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Navigation("JobStepNav"); }); diff --git a/EgwCoreLib.Lux.Data/Migrations/20251028104837_AddJobDriverConf.Designer.cs b/EgwCoreLib.Lux.Data/Migrations/20251028104837_AddJobDriverConf.Designer.cs index 71ada074..461e5615 100644 --- a/EgwCoreLib.Lux.Data/Migrations/20251028104837_AddJobDriverConf.Designer.cs +++ b/EgwCoreLib.Lux.Data/Migrations/20251028104837_AddJobDriverConf.Designer.cs @@ -2386,7 +2386,7 @@ namespace EgwCoreLib.Lux.Data.Migrations }); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Property("JobID") .ValueGeneratedOnAdd() @@ -2939,7 +2939,7 @@ namespace EgwCoreLib.Lux.Data.Migrations modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Items.SellingItemModel", b => { - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -3120,7 +3120,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Cascade) @@ -3160,7 +3160,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany("JobStepNav") .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -3208,7 +3208,7 @@ namespace EgwCoreLib.Lux.Data.Migrations b.Navigation("OrderRowNav"); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Navigation("JobStepNav"); }); diff --git a/EgwCoreLib.Lux.Data/Migrations/20251028105530_FixDecimalVals.Designer.cs b/EgwCoreLib.Lux.Data/Migrations/20251028105530_FixDecimalVals.Designer.cs index 8e78473a..aa051745 100644 --- a/EgwCoreLib.Lux.Data/Migrations/20251028105530_FixDecimalVals.Designer.cs +++ b/EgwCoreLib.Lux.Data/Migrations/20251028105530_FixDecimalVals.Designer.cs @@ -2386,7 +2386,7 @@ namespace EgwCoreLib.Lux.Data.Migrations }); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Property("JobID") .ValueGeneratedOnAdd() @@ -2939,7 +2939,7 @@ namespace EgwCoreLib.Lux.Data.Migrations modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Items.SellingItemModel", b => { - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -3120,7 +3120,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Cascade) @@ -3160,7 +3160,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany("JobStepNav") .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -3208,7 +3208,7 @@ namespace EgwCoreLib.Lux.Data.Migrations b.Navigation("OrderRowNav"); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Navigation("JobStepNav"); }); diff --git a/EgwCoreLib.Lux.Data/Migrations/DataLayerContextModelSnapshot.cs b/EgwCoreLib.Lux.Data/Migrations/DataLayerContextModelSnapshot.cs index b852a117..47d59730 100644 --- a/EgwCoreLib.Lux.Data/Migrations/DataLayerContextModelSnapshot.cs +++ b/EgwCoreLib.Lux.Data/Migrations/DataLayerContextModelSnapshot.cs @@ -2383,7 +2383,7 @@ namespace EgwCoreLib.Lux.Data.Migrations }); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Property("JobID") .ValueGeneratedOnAdd() @@ -2936,7 +2936,7 @@ namespace EgwCoreLib.Lux.Data.Migrations modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Items.SellingItemModel", b => { - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -3117,7 +3117,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany() .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Cascade) @@ -3157,7 +3157,7 @@ namespace EgwCoreLib.Lux.Data.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", "JobNav") + b.HasOne("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", "JobNav") .WithMany("JobStepNav") .HasForeignKey("JobID") .OnDelete(DeleteBehavior.Restrict) @@ -3205,7 +3205,7 @@ namespace EgwCoreLib.Lux.Data.Migrations b.Navigation("OrderRowNav"); }); - modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobModel", b => + modelBuilder.Entity("EgwCoreLib.Lux.Data.DbModel.Task.JobTaskModel", b => { b.Navigation("JobStepNav"); }); diff --git a/EgwCoreLib.Lux.Data/ModelBuilderExtensions.cs b/EgwCoreLib.Lux.Data/ModelBuilderExtensions.cs index 214737fa..77b76d1e 100644 --- a/EgwCoreLib.Lux.Data/ModelBuilderExtensions.cs +++ b/EgwCoreLib.Lux.Data/ModelBuilderExtensions.cs @@ -231,14 +231,14 @@ namespace EgwCoreLib.Lux.Data ); // inizializzazione cicli di lavoro - modelBuilder.Entity().HasData( - new JobModel { JobID = 1, Description = "Rivendita / servizi", Ordinal = 4, Lock = true }, - new JobModel { JobID = 2, Description = "Serramento Legno - Ciclo Completo con installazione", Ordinal = 3, Lock = true }, - new JobModel { JobID = 3, Description = "Realizzazione Trave", Ordinal = 5, Lock = true }, - new JobModel { JobID = 4, Description = "Realizzazione Cabinet", Ordinal = 6, Lock = true }, - new JobModel { JobID = 5, Description = "Realizzazione Parete", Ordinal = 7, Lock = true }, - new JobModel { JobID = 6, Description = "Serramento - ciclo base", Ordinal = 1, Lock = true }, - new JobModel { JobID = 7, Description = "Serramento - ciclo intermedio", Ordinal = 2, Lock = true } + modelBuilder.Entity().HasData( + new JobTaskModel { JobID = 1, Description = "Rivendita / servizi", Ordinal = 4, Lock = true }, + new JobTaskModel { JobID = 2, Description = "Serramento Legno - Ciclo Completo con installazione", Ordinal = 3, Lock = true }, + new JobTaskModel { JobID = 3, Description = "Realizzazione Trave", Ordinal = 5, Lock = true }, + new JobTaskModel { JobID = 4, Description = "Realizzazione Cabinet", Ordinal = 6, Lock = true }, + new JobTaskModel { JobID = 5, Description = "Realizzazione Parete", Ordinal = 7, Lock = true }, + new JobTaskModel { JobID = 6, Description = "Serramento - ciclo base", Ordinal = 1, Lock = true }, + new JobTaskModel { JobID = 7, Description = "Serramento - ciclo intermedio", Ordinal = 2, Lock = true } ); // init JobDriverConfig diff --git a/EgwCoreLib.Lux.Data/Services/DataLayerServices.cs b/EgwCoreLib.Lux.Data/Services/DataLayerServices.cs index e1a67c73..d31454f5 100644 --- a/EgwCoreLib.Lux.Data/Services/DataLayerServices.cs +++ b/EgwCoreLib.Lux.Data/Services/DataLayerServices.cs @@ -18,6 +18,7 @@ using static EgwCoreLib.Lux.Core.Enums; using static System.Runtime.InteropServices.JavaScript.JSType; using EgwCoreLib.Lux.Data.DbModel.Items; using EgwCoreLib.Lux.Data.DbModel.Config; +using EgwCoreLib.Lux.Data.DbModel.Task; namespace EgwCoreLib.Lux.Data.Services { @@ -688,6 +689,77 @@ namespace EgwCoreLib.Lux.Data.Services return result; } + /// + /// Esegue eliminazione + refresh cache + /// + /// + /// + public async Task JobTaskDeleteAsync(JobTaskModel selRec) + { + bool result = await dbController.JobTaskDeleteAsync(selRec); + await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:JobTaskList:*"); + return result; + } + + /// + /// Elenco completo Job gestiti + /// + /// + public async Task> JobTaskGetAllAsync() + { + string source = "DB"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + List? result = new List(); + // cerco in redis... + string currKey = $"{redisBaseKey}:JobTaskList:ALL"; + RedisValue rawData = await redisDb.StringGetAsync(currKey); + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject>($"{rawData}"); + source = "REDIS"; + } + else + { + result = await dbController.JobTaskGetAllAsync(); + // serializzo e salvo con config x evitare loop... + rawData = JsonConvert.SerializeObject(result, JSSettings); + await redisDb.StringSetAsync(currKey, rawData, LongCache); + } + if (result == null) + { + result = new List(); + } + sw.Stop(); + Log.Debug($"JobTaskGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + return result; + } + + /// + /// Esegue spostamento nell'ordinamento relativo alla classe + refresh cache + /// + /// + /// + /// + public async Task JobTaskMoveAsync(JobTaskModel selRec, bool moveUp) + { + bool result = await dbController.JobTaskMoveAsync(selRec, moveUp); + await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:JobTaskList:*"); + return result; + } + + /// + /// Esegue Upsert del record ricevuto + /// + /// + /// + public async Task JobTaskUpsertAsync(JobTaskModel currRec) + { + bool result = await dbController.JobTaskUpsertAsync(currRec); + await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:JobTaskList:*"); + return result; + } + /// /// Elenco completo offerte da DB /// @@ -775,6 +847,25 @@ namespace EgwCoreLib.Lux.Data.Services return answ; } + /// + /// Effettua eliminazione della riga offerta + /// + /// IRiga offerta coin dati FILE da aggiornare + /// + public async Task OffertRowDelete(OfferRowModel updRec) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + // calcolo + bool fatto = await dbController.OffertRowDelete(updRec); + // svuoto cache... + await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*"); + await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*"); + sw.Stop(); + Log.Debug($"OffertRowDelete in {sw.Elapsed.TotalMilliseconds} ms"); + return fatto; + } + /// /// Effettua fix UID righe child dell'offerta indicata e restituisce elenco UID da chiamare x refresh /// @@ -854,26 +945,6 @@ namespace EgwCoreLib.Lux.Data.Services return fatto; } - - /// - /// Effettua eliminazione della riga offerta - /// - /// IRiga offerta coin dati FILE da aggiornare - /// - public async Task OffertRowDelete(OfferRowModel updRec) - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - // calcolo - bool fatto = await dbController.OffertRowDelete(updRec); - // svuoto cache... - await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*"); - await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*"); - sw.Stop(); - Log.Debug($"OffertRowDelete in {sw.Elapsed.TotalMilliseconds} ms"); - return fatto; - } - /// /// Effettua Upsert della riga offerta /// @@ -1008,7 +1079,6 @@ namespace EgwCoreLib.Lux.Data.Services } } - /// /// Esegue salvataggio ProfileList sul DB /// @@ -1030,8 +1100,6 @@ namespace EgwCoreLib.Lux.Data.Services } } - - #endregion Public Methods #region Protected Fields diff --git a/Lux.API/Lux.API.csproj b/Lux.API/Lux.API.csproj index 9c86b155..64bf9bb5 100644 --- a/Lux.API/Lux.API.csproj +++ b/Lux.API/Lux.API.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 0.9.2510.2811 + 0.9.2510.2817 diff --git a/Lux.UI.Client/Lux.UI.Client.csproj b/Lux.UI.Client/Lux.UI.Client.csproj index 46fe6e3e..a81f17d9 100644 --- a/Lux.UI.Client/Lux.UI.Client.csproj +++ b/Lux.UI.Client/Lux.UI.Client.csproj @@ -9,7 +9,7 @@ - + diff --git a/Lux.UI/Components/Compo/EditJob.razor b/Lux.UI/Components/Compo/EditJob.razor new file mode 100644 index 00000000..018e6db5 --- /dev/null +++ b/Lux.UI/Components/Compo/EditJob.razor @@ -0,0 +1,5 @@ +

EditJob

+ +@code { + +} diff --git a/Lux.UI/Components/Compo/GenClassMan.razor.cs b/Lux.UI/Components/Compo/GenClassMan.razor.cs index 5d21d892..1555169b 100644 --- a/Lux.UI/Components/Compo/GenClassMan.razor.cs +++ b/Lux.UI/Components/Compo/GenClassMan.razor.cs @@ -54,7 +54,7 @@ namespace Lux.UI.Components.Compo if (NewRecord != null) { // verifico non sia duplicato... - var recExist = ListRecords.Count(x => x.ClassCod == NewRecord.ClassCod); + var recExist = AllRecords.Count(x => x.ClassCod == NewRecord.ClassCod); if (recExist > 0) { ErrorMsg = $"Errore: record già esistente con codice {NewRecord.ClassCod}"; diff --git a/Lux.UI/Components/Compo/JobTask/JobTaskListMan.razor b/Lux.UI/Components/Compo/JobTask/JobTaskListMan.razor new file mode 100644 index 00000000..75cb0bff --- /dev/null +++ b/Lux.UI/Components/Compo/JobTask/JobTaskListMan.razor @@ -0,0 +1,119 @@ +@if (addVisible) +{ + +} +
+
+ Elenco cicli attivi +
+
+ @if (isLoading || ListRecords == null) + { + + } + else if (totalCount == 0) + { +
Nessun record trovato
+ } + else + { + + + + + @if (selRecord == null) + { + + + + + } + else + { + + } + + + + @foreach (var item in ListRecords) + { + string cssBtnUp = editRecord == null && item.Ordinal > 1 ? "btn-outline-primary" : "btn-outline-secondary opacity-50 disabled"; + string cssBtnDown = editRecord == null && item.Ordinal < totalCount ? "btn-outline-primary" : "btn-outline-secondary opacity-50 disabled"; + + + + @if (selRecord == null) + { + + + + + } + else + { + + } + + } + +
+ + Ord.DescrizioneFasi + + Descrizione
+ + + + + + @item.Ordinal + + @item.Description@item.NumChild + @if (item.Lock || item.NumChild > 0) + { + + } + else + { + + } + @item.Description
+ } +
+
+ diff --git a/Lux.UI/Components/Compo/JobTask/JobTaskListMan.razor.cs b/Lux.UI/Components/Compo/JobTask/JobTaskListMan.razor.cs new file mode 100644 index 00000000..32749d18 --- /dev/null +++ b/Lux.UI/Components/Compo/JobTask/JobTaskListMan.razor.cs @@ -0,0 +1,239 @@ +using EgwCoreLib.Lux.Data.DbModel.Task; +using EgwCoreLib.Lux.Data.DbModel.Utils; +using EgwCoreLib.Lux.Data.Services; +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +namespace Lux.UI.Components.Compo.JobTask +{ + public partial class JobTaskListMan + { + #region Public Properties + + [Parameter] + public string CurrSearch { get; set; } = string.Empty; + + [Parameter] + public EventCallback EC_Selected { get; set; } + + [Parameter] + public EventCallback EC_Updated { get; set; } + + #endregion Public Properties + + #region Protected Fields + + protected List AllRecords = new List(); + protected List ListRecords = new List(); + + #endregion Protected Fields + + #region Protected Properties + + [Inject] + protected DataLayerServices DLService { get; set; } = null!; + + [Inject] + protected IJSRuntime JSRuntime { get; set; } = null!; + + #endregion Protected Properties + + #region Protected Methods + + /// + /// Genera nuovo record e lo salva + /// + protected async Task DoAdd() + { + if (newRecord != null) + { + // verifico non sia duplicato... + var recExist = AllRecords.Count(x => x.Description == newRecord.Description); + if (recExist > 0) + { + errorMsg = $"Errore: record già esistente | {newRecord.Description}"; + } + else + { + errorMsg = ""; + // faccio upsert record... + await DLService.JobTaskUpsertAsync(newRecord); + // segnalo update x reload + await EC_Updated.InvokeAsync(true); + newRecord = null; + addVisible = false; + // rileggo + await ReloadData(); + UpdateTable(); + } + } + } + + /// + /// Eliminazione record + /// + /// + protected async Task DoDelete(JobTaskModel rec2del) + { + // controlo che NON abbia child obj... altrimenti esco + if (rec2del.NumChild > 0) + return; + + if (!await JSRuntime.InvokeAsync("confirm", $"Sicuro di voler eliminare il record? {rec2del.Description} ({rec2del.JobID})")) + return; + + // esegue eliminazione del record... + await DLService.JobTaskDeleteAsync(rec2del); + + // segnalo update x reload + await EC_Updated.InvokeAsync(true); + // rileggo + await ReloadData(); + UpdateTable(); + } + + /// + /// Edit articolo selezionato + /// + /// + protected async void DoEdit(JobTaskModel curRec) + { + editRecord = curRec; + selRecord = curRec; +#if false + await EC_Selected.InvokeAsync(curRec); +#endif + await Task.Delay(1); + } + + /// + /// Reset selezione + /// + protected async void DoReset() + { + editRecord = null; + selRecord = null; + await EC_Selected.InvokeAsync(selRecord); + } + + /// + /// Selezione articolo x display info + /// + /// + protected async void DoSelect(JobTaskModel curRec) + { + selRecord = curRec; + await EC_Selected.InvokeAsync(curRec); + } + + protected override async Task OnParametersSetAsync() + { + await ReloadData(); + UpdateTable(); + } + + protected void ToggleAdd() + { + addVisible = !addVisible; + if (addVisible) + { + newRecord = new JobTaskModel() + { + Description = $"Nuovo Ciclo-{DateTime.Now:yyyy.MM.dd-HH.mm.ss}", + Ordinal = totalCount + 1 + }; + } + } + + #endregion Protected Methods + + #region Private Fields + + private bool addVisible = false; + + private int currPage = 1; + + private JobTaskModel? editRecord = null; + + private string errorMsg = ""; + + private bool isLoading = false; + + private JobTaskModel? newRecord = null; + + private int numRecord = 10; + + private JobTaskModel? selRecord = null; + + private int totalCount = 0; + + #endregion Private Fields + + #region Private Methods + + private string checkSel(JobTaskModel curRec) + { + string answ = ""; + if (selRecord != null) + { + answ = curRec.JobID == selRecord.JobID ? "table-info" : ""; + } + return answ; + } + + private async Task DoCancel() + { + await ResetEdit(); + UpdateTable(); + } + + /// + /// Esegue spostamento + /// + /// + /// + /// + private async Task MoveRec(JobTaskModel curRec, bool moveUp) + { + await DLService.JobTaskMoveAsync(curRec, moveUp); + await DoCancel(); + } + + private async Task ReloadData() + { + isLoading = true; + AllRecords = await DLService.JobTaskGetAllAsync(); + // se ho ricerca testuale faccio filtro ulteriore... + if (!string.IsNullOrEmpty(CurrSearch)) + { + AllRecords = AllRecords + .Where(x => x.Description.Contains(CurrSearch, StringComparison.InvariantCultureIgnoreCase)) + .ToList(); + } + totalCount = AllRecords.Count; + } + + private async Task ResetEdit() + { + // reset edit + editRecord = null; + await ReloadData(); + } + + /// + /// Filtro e paginazione + /// + private void UpdateTable() + { + // fix paginazione + ListRecords = AllRecords + .OrderBy(x => x.Ordinal) + .Skip(numRecord * (currPage - 1)) + .Take(numRecord) + .ToList(); + isLoading = false; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/Lux.UI/Components/Compo/OfferRowMan.razor b/Lux.UI/Components/Compo/OfferRowMan.razor index 3332d49d..0e127fa9 100644 --- a/Lux.UI/Components/Compo/OfferRowMan.razor +++ b/Lux.UI/Components/Compo/OfferRowMan.razor @@ -331,7 +331,7 @@ else diff --git a/Lux.UI/Components/Compo/OfferRowMan.razor.cs b/Lux.UI/Components/Compo/OfferRowMan.razor.cs index 1d452b20..273b6d9f 100644 --- a/Lux.UI/Components/Compo/OfferRowMan.razor.cs +++ b/Lux.UI/Components/Compo/OfferRowMan.razor.cs @@ -357,17 +357,6 @@ namespace Lux.UI.Components.Compo CurrEditMode = EditMode.None; } - /// - /// Imposta modalità ad edit BOM - /// - /// - protected void DoSwapMat(OfferRowModel currRow) - { - CurrEditMode = EditMode.BOM; - EditRecord = currRow; - CurrBomList = DLService.OffertGetBomList(EditRecord); - } - /// /// Imposta modalità edit ciclo di lavoro /// @@ -379,6 +368,17 @@ namespace Lux.UI.Components.Compo CurrBomList = DLService.OffertGetBomList(EditRecord); } + /// + /// Imposta modalità ad edit BOM + /// + /// + protected void DoSwapMat(OfferRowModel currRow) + { + CurrEditMode = EditMode.BOM; + EditRecord = currRow; + CurrBomList = DLService.OffertGetBomList(EditRecord); + } + /// /// Display fileSize scalato /// @@ -560,8 +560,6 @@ namespace Lux.UI.Components.Compo private List AllConfHardware = new(); - - private List AllConfWood = new(); private List AllRecords = new List(); @@ -589,11 +587,11 @@ namespace Lux.UI.Components.Compo /// private EditMode CurrEditMode = EditMode.None; + private Dictionary currGroupShape = new Dictionary(); private string currOptXml = ""; private int currPage = 1; private List currProfList = new List(); - private string currShape = ""; private string currSvg = ""; /// @@ -811,6 +809,7 @@ namespace Lux.UI.Components.Compo // vale SOLO SE sono in editing... if (EditRecord != null) { +#if false // aggiorno visualizzazione PubSubEventArgs currArgs = (PubSubEventArgs)e; // conversione on-the-fly SVG da mostrare @@ -818,9 +817,38 @@ namespace Lux.UI.Components.Compo { if (currArgs.msgUid.Equals($"{shapeChannel}:{EditRecord.OfferRowUID}")) { - currShape = currArgs.newMessage; + currGroupShape = currArgs.newMessage; // salvo in live data... - CurrData.Shape = currShape; + CurrData.DictShape = currGroupShape; + } + await InvokeAsync(StateHasChanged); + } +#endif + + // aggiorno visualizzazione + PubSubEventArgs currArgs = (PubSubEventArgs)e; + // conversione on-the-fly SVG da mostrare + if (!string.IsNullOrEmpty(currArgs.newMessage)) + { + if (currArgs.msgUid.StartsWith($"{shapeChannel}:{EditRecord.OfferRowUID}")) + { + // deserializzo il dizionario delle risposte... + var rawDict = JsonConvert.DeserializeObject>(currArgs.newMessage); +#if false + int groupId = 0; + // verifica del groupID... + int.TryParse(currArgs.msgUid.Replace($"{shapeChannel}:{windowUid}:", ""), out groupId); + if (currGroupShape.ContainsKey(groupId)) + { + currGroupShape[groupId] = currArgs.newMessage; + } + else + { + currGroupShape.Add(groupId, currArgs.newMessage); + } +#endif + currGroupShape = rawDict ?? new Dictionary(); + CurrData.DictShape = currGroupShape; } await InvokeAsync(StateHasChanged); } @@ -1022,7 +1050,7 @@ namespace Lux.UI.Components.Compo { string serStruct = args["Jwd"]; // controllo SE variato... - if (!prevJwd.Equals(serStruct) || !DictUtils.DictAreEqual(reqDict, args)) + if (!prevJwd.Equals(serStruct) || !EgwCoreLib.Lux.Core.DictUtils.DictAreEqual(reqDict, args)) { // aggiorno val prev reqDict = args; diff --git a/Lux.UI/Components/Pages/JobRoute.razor b/Lux.UI/Components/Pages/JobRoute.razor index d47897a3..b1349833 100644 --- a/Lux.UI/Components/Pages/JobRoute.razor +++ b/Lux.UI/Components/Pages/JobRoute.razor @@ -25,18 +25,19 @@ } else { -
- Elenco cicli attivi - - @* *@ +
+
-
- @* @if (!string.IsNullOrEmpty(CurrFilt.SelCodGroup)) + @if (selRecord != null) + { +
+ @* @if (!string.IsNullOrEmpty(CurrFilt.SelCodGroup)) { } *@ - Dettaglio ciclo selezionato -
+ Dettaglio ciclo selezionato +
+ } }
diff --git a/Lux.UI/Components/Pages/JobRoute.razor.cs b/Lux.UI/Components/Pages/JobRoute.razor.cs index f43e4d31..90b221e0 100644 --- a/Lux.UI/Components/Pages/JobRoute.razor.cs +++ b/Lux.UI/Components/Pages/JobRoute.razor.cs @@ -1,4 +1,5 @@ using EgwCoreLib.Lux.Data.DbModel.Items; +using EgwCoreLib.Lux.Data.DbModel.Task; using EgwCoreLib.Lux.Data.DbModel.Utils; using EgwCoreLib.Lux.Data.Services; using Lux.UI.Components.Compo; @@ -65,7 +66,8 @@ namespace Lux.UI.Components.Pages #region Private Fields - private ItemModel? editRecord = null; + private JobTaskModel? editRecord = null; + private JobTaskModel? selRecord = null; private bool isLoading = false; #endregion Private Fields @@ -90,5 +92,18 @@ namespace Lux.UI.Components.Pages } #endregion Private Methods + /// + /// Salva ID sel e mostra dettagli JobTask + /// + /// + private void ShowDetail(JobTaskModel? selRec) + { + selRecord = selRec; + } + + private string mainCss + { + get => selRecord == null ? "col-6" : "col-4"; + } } } \ No newline at end of file diff --git a/Lux.UI/Components/_Imports.razor b/Lux.UI/Components/_Imports.razor index b070bd7f..cc3d02c8 100644 --- a/Lux.UI/Components/_Imports.razor +++ b/Lux.UI/Components/_Imports.razor @@ -18,3 +18,4 @@ @using Lux.UI.Components @using Lux.UI.Components.Compo @using Lux.UI.Components.Compo.Config +@using Lux.UI.Components.Compo.JobTask diff --git a/Lux.UI/Lux.UI.csproj b/Lux.UI/Lux.UI.csproj index 31536d6c..418335bb 100644 --- a/Lux.UI/Lux.UI.csproj +++ b/Lux.UI/Lux.UI.csproj @@ -5,7 +5,7 @@ enable enable aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50 - 0.9.2510.2811 + 0.9.2510.2817 @@ -17,7 +17,7 @@ - + diff --git a/Resources/ChangeLog.html b/Resources/ChangeLog.html index 5323a040..910799a1 100644 --- a/Resources/ChangeLog.html +++ b/Resources/ChangeLog.html @@ -1,6 +1,6 @@ LUX - Web Windows MES -

Versione: 0.9.2510.2811

+

Versione: 0.9.2510.2817


Note di rilascio:
  • diff --git a/Resources/VersNum.txt b/Resources/VersNum.txt index c3ba9ffb..c58e16a5 100644 --- a/Resources/VersNum.txt +++ b/Resources/VersNum.txt @@ -1 +1 @@ -0.9.2510.2811 +0.9.2510.2817 diff --git a/Resources/manifest.xml b/Resources/manifest.xml index 9983c912..04631f39 100644 --- a/Resources/manifest.xml +++ b/Resources/manifest.xml @@ -1,6 +1,6 @@ - 0.9.2510.2811 + 0.9.2510.2817 http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html false