diff --git a/MP.Data/Controllers/MpStatsController.cs b/MP.Data/Controllers/MpStatsController.cs index d567fc7a..c0caef66 100644 --- a/MP.Data/Controllers/MpStatsController.cs +++ b/MP.Data/Controllers/MpStatsController.cs @@ -170,14 +170,13 @@ namespace MP.Data.Controllers /// Elenco da tabella Macchine con dati Energy /// /// - public List MacchineEnergy() + public List MacchineEnergy() { - List dbResult = new List(); + List dbResult = new List(); using (var dbCtx = new MoonPro_STATSContext(_configuration)) { dbResult = dbCtx - .DbSetMacchine - .FromSqlRaw("EXEC stp_MaccEnergy") + .DbSetMaccStat .ToList(); } return dbResult; diff --git a/MP.Data/DbModels/MacchineStatModel.cs b/MP.Data/DbModels/MacchineStatModel.cs new file mode 100644 index 00000000..dbaad00a --- /dev/null +++ b/MP.Data/DbModels/MacchineStatModel.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + + +#nullable disable +// +// This is here so CodeMaid doesn't reorganize this document +// +namespace MP.Data.DbModels +{ + public partial class MacchineStatModel + { + #region Public Properties + + [Key] + public string IdxMacchina { get; set; } + /// + /// Cod macchina + /// + public string CodMacchina { get; set; } = ""; + /// + /// Nome macchina + /// + public string Nome { get; set; } = ""; + /// + /// Descrizione macchina + /// + public string Descrizione { get; set; } = ""; + public bool Energy { get; set; } = false; + public bool Deleted { get; set; } = false; + + #endregion Public Properties + } +} \ No newline at end of file diff --git a/MP.Data/DbModels/TaskListModel.cs b/MP.Data/DbModels/TaskListModel.cs index 450eb255..d4d6e330 100644 --- a/MP.Data/DbModels/TaskListModel.cs +++ b/MP.Data/DbModels/TaskListModel.cs @@ -38,7 +38,7 @@ namespace MP.Data.DbModels /// /// Tipo Task /// - public Task2ExeType TType { get; set; } = Task2ExeType.ND; + public Task2ExeType TType { get; set; } = Task2ExeType.ALL; /// /// Comando da invocare diff --git a/MP.Data/MoonPro_STATSContext.cs b/MP.Data/MoonPro_STATSContext.cs index 0b4b9990..99a48f37 100644 --- a/MP.Data/MoonPro_STATSContext.cs +++ b/MP.Data/MoonPro_STATSContext.cs @@ -50,6 +50,7 @@ namespace MP.Data public virtual DbSet DbSetTurniOee { get; set; } public virtual DbSet DbSetUserLog { get; set; } public virtual DbSet DbSetVocabolario { get; set; } + public virtual DbSet DbSetMaccStat { get; set; } #endregion Public Properties @@ -176,55 +177,61 @@ namespace MP.Data entity.Property(e => e.Nome).HasMaxLength(50); }); + modelBuilder.Entity(entity => + { + //entity.HasNoKey(); + + entity.ToView("v_UI_MaccEnergy"); + }); modelBuilder.Entity(entity => - { - entity.HasNoKey(); + { + entity.HasNoKey(); - entity.ToView("v_UI_DDB_Turni"); + entity.ToView("v_UI_DDB_Turni"); - entity.Property(e => e.ClasseTempo).HasMaxLength(50); + entity.Property(e => e.ClasseTempo).HasMaxLength(50); - entity.Property(e => e.CodArticolo) - .IsRequired() - .HasMaxLength(50); + entity.Property(e => e.CodArticolo) + .IsRequired() + .HasMaxLength(50); - entity.Property(e => e.CodMacchina).HasMaxLength(50); + entity.Property(e => e.CodMacchina).HasMaxLength(50); - entity.Property(e => e.DataRif).HasColumnType("datetime"); + entity.Property(e => e.DataRif).HasColumnType("datetime"); - entity.Property(e => e.DataTurnoFine).HasColumnType("datetime"); + entity.Property(e => e.DataTurnoFine).HasColumnType("datetime"); - entity.Property(e => e.DataTurnoInizio).HasColumnType("datetime"); + entity.Property(e => e.DataTurnoInizio).HasColumnType("datetime"); - entity.Property(e => e.Descrizione).HasMaxLength(50); + entity.Property(e => e.Descrizione).HasMaxLength(50); - entity.Property(e => e.FinePeriodo).HasColumnType("datetime"); + entity.Property(e => e.FinePeriodo).HasColumnType("datetime"); - entity.Property(e => e.FineStato).HasColumnType("datetime"); + entity.Property(e => e.FineStato).HasColumnType("datetime"); - entity.Property(e => e.IdxMacchina) - .IsRequired() - .HasMaxLength(50); + entity.Property(e => e.IdxMacchina) + .IsRequired() + .HasMaxLength(50); - entity.Property(e => e.IdxOdl).HasColumnName("IdxODL"); + entity.Property(e => e.IdxOdl).HasColumnName("IdxODL"); - entity.Property(e => e.InizioPeriodo).HasColumnType("datetime"); + entity.Property(e => e.InizioPeriodo).HasColumnType("datetime"); - entity.Property(e => e.InizioStato).HasColumnType("datetime"); + entity.Property(e => e.InizioStato).HasColumnType("datetime"); - entity.Property(e => e.KeyRichiesta).HasMaxLength(50); + entity.Property(e => e.KeyRichiesta).HasMaxLength(50); - entity.Property(e => e.Pallet) - .HasMaxLength(20) - .HasColumnName("pallet"); + entity.Property(e => e.Pallet) + .HasMaxLength(20) + .HasColumnName("pallet"); - entity.Property(e => e.TempoCicloBase).HasColumnType("decimal(18, 8)"); + entity.Property(e => e.TempoCicloBase).HasColumnType("decimal(18, 8)"); - entity.Property(e => e.Turno) - .IsRequired() - .HasMaxLength(5); - }); + entity.Property(e => e.Turno) + .IsRequired() + .HasMaxLength(5); + }); modelBuilder.Entity(entity => { diff --git a/MP.Stats/Components/ChartTrends.razor b/MP.Stats/Components/ChartTrends.razor index b1156ef1..2108000c 100644 --- a/MP.Stats/Components/ChartTrends.razor +++ b/MP.Stats/Components/ChartTrends.razor @@ -39,7 +39,6 @@ } - @* selezione ITEM da mostrare, tra quelli POSSIBILI dato periodo... *@ diff --git a/MP.Stats/Components/ChartTrends.razor.cs b/MP.Stats/Components/ChartTrends.razor.cs index 099ee6c4..33b5902d 100644 --- a/MP.Stats/Components/ChartTrends.razor.cs +++ b/MP.Stats/Components/ChartTrends.razor.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Security.AccessControl; namespace MP.Stats.Components { diff --git a/MP.Stats/Controllers/TaskController.cs b/MP.Stats/Controllers/TaskController.cs index a89bdd59..c5d46c93 100644 --- a/MP.Stats/Controllers/TaskController.cs +++ b/MP.Stats/Controllers/TaskController.cs @@ -36,7 +36,7 @@ namespace MP.Stats.Controllers public async Task> ExecuteAndReturnGet() { List answ = new List(); - List listTask = await DService.TaskListAll(TaskMan.Objects.Enums.Task2ExeType.ND, ""); + List listTask = await DService.TaskListAll(TaskMan.Objects.Enums.Task2ExeType.ALL, ""); // verifico SE ci siano task in scadenza... DateTime adesso = DateTime.Now; var task2exe = listTask.Where(x => x.DtNextExec <= adesso).ToList(); @@ -56,7 +56,7 @@ namespace MP.Stats.Controllers [HttpGet("GetList")] public async Task> GetList() { - List answ = await DService.TaskListAll(TaskMan.Objects.Enums.Task2ExeType.ND, ""); + List answ = await DService.TaskListAll(TaskMan.Objects.Enums.Task2ExeType.ALL, ""); return answ; } diff --git a/MP.Stats/Data/MpStatsService.cs b/MP.Stats/Data/MpStatsService.cs index a2897632..b9f90a89 100644 --- a/MP.Stats/Data/MpStatsService.cs +++ b/MP.Stats/Data/MpStatsService.cs @@ -32,7 +32,7 @@ namespace MP.Stats.Data // setup compoenti REDIS redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis")); - redisDb = redisConn.GetDatabase(); + redisDb = redisConn.GetDatabase(); #endif // conf DB @@ -250,6 +250,113 @@ namespace MP.Stats.Data return answ; } + /// + /// Recupero dati FluxLog secondo filtro + richiesta raggruppamento + /// + /// + /// + /// + /// + public async Task> FluxLogRawData(SelectData CurrFilter, string fluxType, string searchVal = "") + { + // setup parametri costanti + string source = "DB"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + List result = new List(); + // cerco in redis... + DateTime adesso = DateTime.Now; + string currKey = getCacheKey($"{redisBaseKey}:FL_DATA:FT_{fluxType}", CurrFilter); + RedisValue rawData = await redisDb.StringGetAsync(currKey); + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject>($"{rawData}"); + source = "REDIS"; + } + else + { + result = dbController.FluxLogRawData(CurrFilter.IdxMacchina, CurrFilter.DateStart, CurrFilter.DateEnd, fluxType); + // serializzp e salvo... + rawData = JsonConvert.SerializeObject(result); + await redisDb.StringSetAsync(currKey, rawData, FastCache); + } + if (result == null) + { + result = new List(); + } + sw.Stop(); + Log.Debug($"FluxLogRawData | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + return result; + } + + /// + /// Elenco di tipi flusso disponibili + /// + /// + public async Task> FluxTypeList() + { + // setup parametri costanti + string source = "DB"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + List result = new List(); + // cerco in redis... + DateTime adesso = DateTime.Now; + string currKey = $"{redisBaseKey}:FTList"; + RedisValue rawData = await redisDb.StringGetAsync(currKey); + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject>($"{rawData}"); + source = "REDIS"; + } + else + { + result = dbController.FluxTypeList(); + // serializzp e salvo... + rawData = JsonConvert.SerializeObject(result); + await redisDb.StringSetAsync(currKey, rawData, UltraLongCache); + } + if (result == null) + { + result = new List(); + } + sw.Stop(); + Log.Debug($"FluxTypeList | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + return result; + } + + public List MacchineEnergy() + { + // setup parametri costanti + string source = "DB"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + List result = new List(); + // cerco in redis... + DateTime adesso = DateTime.Now; + string currKey = $"{redisBaseKey}:Cache:MacchineEnergy"; + RedisValue rawData = redisDb.StringGet(currKey); + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject>($"{rawData}"); + source = "REDIS"; + } + else + { + result = dbController.MacchineEnergy().ToList(); + // serializzp e salvo... + rawData = JsonConvert.SerializeObject(result); + redisDb.StringSet(currKey, rawData, FastCache); + } + if (result == null) + { + result = new List(); + } + sw.Stop(); + Log.Debug($"MacchineEnergy | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + return result; + } + public List MacchineGetAll() { // setup parametri costanti @@ -282,38 +389,6 @@ namespace MP.Stats.Data return result; } - public List MacchineEnergy() - { - // setup parametri costanti - string source = "DB"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - List result = new List(); - // cerco in redis... - DateTime adesso = DateTime.Now; - string currKey = $"{redisBaseKey}:Cache:MacchineEnergy"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.MacchineEnergy().ToList(); - // serializzp e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, FastCache); - } - if (result == null) - { - result = new List(); - } - sw.Stop(); - Log.Debug($"MacchineEnergy | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; - } - public Task> MachineList(bool onlyEnergy = false) { List answ = new List(); @@ -480,83 +555,6 @@ namespace MP.Stats.Data return numRec; } - - /// - /// Recupero dati FluxLog secondo filtro + richiesta raggruppamento - /// - /// - /// - /// - /// - public async Task> FluxLogRawData(SelectData CurrFilter, string fluxType, string searchVal = "") - { - // setup parametri costanti - string source = "DB"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - List result = new List(); - // cerco in redis... - DateTime adesso = DateTime.Now; - string currKey = getCacheKey($"{redisBaseKey}:FL_DATA:FT_{fluxType}", CurrFilter); - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.FluxLogRawData(CurrFilter.IdxMacchina, CurrFilter.DateStart, CurrFilter.DateEnd, fluxType); - // serializzp e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, FastCache); - } - if (result == null) - { - result = new List(); - } - sw.Stop(); - Log.Debug($"FluxLogRawData | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco di tipi flusso disponibili - /// - /// - public async Task> FluxTypeList() - { - // setup parametri costanti - string source = "DB"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - List result = new List(); - // cerco in redis... - DateTime adesso = DateTime.Now; - string currKey = $"{redisBaseKey}:FTList"; - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.FluxTypeList(); - // serializzp e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, UltraLongCache); - } - if (result == null) - { - result = new List(); - } - sw.Stop(); - Log.Debug($"FluxTypeList | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; - } - - /// /// Statistiche ODL /// @@ -787,6 +785,8 @@ namespace MP.Stats.Data /// protected static Dictionary DictFluxUm = new Dictionary(); + #endregion Protected Fields + #if false /// /// Oggetto per connessione a REDIS @@ -796,11 +796,9 @@ namespace MP.Stats.Data /// /// Oggetto DB redis da impiegare x chiamate R/W /// - protected IDatabase redisDb = null!; + protected IDatabase redisDb = null!; #endif - #endregion Protected Fields - #region Protected Methods protected string getCacheKey(string TableName, SelectData CurrFilter) diff --git a/MP.Stats/MP.Stats.csproj b/MP.Stats/MP.Stats.csproj index d0094905..0b0befa8 100644 --- a/MP.Stats/MP.Stats.csproj +++ b/MP.Stats/MP.Stats.csproj @@ -4,8 +4,8 @@ net6.0 MP.Stats 826e877c-ba70-4253-84cb-d0b1cafd4440 - 6.16.2507.0217 - 6.16.2507.0217 + 6.16.2507.0315 + 6.16.2507.0315 true $(NoWarn);1591 en diff --git a/MP.Stats/Pages/ForceReset.razor.cs b/MP.Stats/Pages/ForceReset.razor.cs index 22d95f89..80d5aad3 100644 --- a/MP.Stats/Pages/ForceReset.razor.cs +++ b/MP.Stats/Pages/ForceReset.razor.cs @@ -29,7 +29,7 @@ namespace MP.Stats.Pages protected override async Task OnInitializedAsync() { await StatService.FlushCache(); - await TServ.FlushCache(); + await TServ.FlushCacheAsync(); await TradServ.FlushCache(); await Task.Delay(500); NavManager.NavigateTo("", true); diff --git a/MP.Stats/Resources/ChangeLog.html b/MP.Stats/Resources/ChangeLog.html index 50fc96da..168f1c8c 100644 --- a/MP.Stats/Resources/ChangeLog.html +++ b/MP.Stats/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo statistiche MAPO -

Versione: 6.16.2507.0217

+

Versione: 6.16.2507.0315


Note di rilascio:
    diff --git a/MP.Stats/Resources/VersNum.txt b/MP.Stats/Resources/VersNum.txt index c0a31142..73d542ab 100644 --- a/MP.Stats/Resources/VersNum.txt +++ b/MP.Stats/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2507.0217 +6.16.2507.0315 diff --git a/MP.Stats/Resources/manifest.xml b/MP.Stats/Resources/manifest.xml index a8ea4ca5..d86e0fa7 100644 --- a/MP.Stats/Resources/manifest.xml +++ b/MP.Stats/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2507.0217 + 6.16.2507.0315 https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html false diff --git a/MP.TaskMan/Controllers/MpTaskController.cs b/MP.TaskMan/Controllers/MpTaskController.cs index bb0dd76d..3528da05 100644 --- a/MP.TaskMan/Controllers/MpTaskController.cs +++ b/MP.TaskMan/Controllers/MpTaskController.cs @@ -323,7 +323,7 @@ namespace MP.TaskMan.Controllers { dbResult = dbCtx .DbSetTaskList - .Where(x => (TType == Task2ExeType.ND || x.TType == TType)) + .Where(x => (TType == Task2ExeType.ALL || x.TType == TType)) .OrderBy(x => x.Ordinal) .ToList(); } @@ -388,6 +388,50 @@ namespace MP.TaskMan.Controllers return done; } + /// + /// Riordino record di un dato gruppo (da richiamare post cambio gruppo...) + /// + /// + /// + public bool TaskListReorder(int codGroup) + { + bool done = false; + using (var dbCtx = new TaskContext(_configuration)) + { + // in primis recupero i record del gruppo ordinati + var currList = dbCtx + .DbSetTaskList + .Where(x => x.Group == codGroup) + .OrderBy(x => x.Ordinal) + .ThenBy(x => x.TaskId) + .ToList(); + int newIdx = 0; + int numRec = currList.Count; + // li verifico in base al loro id attuale... + foreach (var item in currList) + { + newIdx++; + // se va cambiato lo riassegno + if (item.Ordinal != newIdx) + { + item.Ordinal = newIdx; + dbCtx.Entry(item).State = EntityState.Modified; + } + } + // salvo! + try + { + dbCtx.SaveChanges(); + done = true; + } + catch (Exception exc) + { + Log.Error($"Eccezione in TaskListReorder{Environment.NewLine}{exc}"); + } + } + return done; + } + /// /// Upsert record TaskList /// @@ -407,6 +451,7 @@ namespace MP.TaskMan.Controllers if (currData != null) { currData.Ordinal = rec2upd.Ordinal; + currData.Group = rec2upd.Group; currData.Enabled = rec2upd.Enabled; currData.Name = rec2upd.Name; currData.Descript = rec2upd.Descript; diff --git a/MP.TaskMan/Migrations/20250703101600_AddTaskGroup.Designer.cs b/MP.TaskMan/Migrations/20250703101600_AddTaskGroup.Designer.cs new file mode 100644 index 00000000..700f63bb --- /dev/null +++ b/MP.TaskMan/Migrations/20250703101600_AddTaskGroup.Designer.cs @@ -0,0 +1,145 @@ +// +using System; +using MP.TaskMan; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MP.TaskMan.Migrations +{ + [DbContext(typeof(TaskContext))] + [Migration("20250703101600_AddTaskGroup")] + partial class AddTaskGroup + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("SQL_Latin1_General_CP1_CI_AS") + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("MP.TaskMan.Models.TaskExecModel", b => + { + b.Property("TaskExecId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("TaskExecId"), 1L, 1); + + b.Property("DtEnd") + .HasColumnType("datetime2"); + + b.Property("DtStart") + .HasColumnType("datetime2"); + + b.Property("IsError") + .HasColumnType("bit"); + + b.Property("Result") + .HasColumnType("nvarchar(max)"); + + b.Property("TaskId") + .HasColumnType("int"); + + b.HasKey("TaskExecId"); + + b.HasIndex("TaskId"); + + b.ToTable("TaskExec"); + }); + + modelBuilder.Entity("MP.TaskMan.Models.TaskListModel", b => + { + b.Property("TaskId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("TaskId"), 1L, 1); + + b.Property("Args") + .HasColumnType("nvarchar(max)"); + + b.Property("Cad") + .HasColumnType("int"); + + b.Property("Command") + .HasColumnType("nvarchar(max)"); + + b.Property("Descript") + .HasColumnType("nvarchar(max)"); + + b.Property("DtLastExec") + .HasColumnType("datetime2"); + + b.Property("DtNextExec") + .HasColumnType("datetime2"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("Freq") + .HasColumnType("int"); + + b.Property("Group") + .HasColumnType("int"); + + b.Property("LastDuration") + .HasColumnType("float"); + + b.Property("LastIsError") + .HasColumnType("bit"); + + b.Property("LastResult") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("Ordinal") + .HasColumnType("int"); + + b.Property("TType") + .HasColumnType("int"); + + b.HasKey("TaskId"); + + b.ToTable("TaskList"); + }); + + modelBuilder.Entity("MP.TaskMan.Models.TaskResultModel", b => + { + b.Property("Task") + .HasColumnType("nvarchar(450)"); + + b.Property("ExecResult") + .HasColumnType("int"); + + b.Property("TextResult") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Task"); + + b.ToTable("DbSetTaskResult"); + }); + + modelBuilder.Entity("MP.TaskMan.Models.TaskExecModel", b => + { + b.HasOne("MP.TaskMan.Models.TaskListModel", "TaskListNav") + .WithMany() + .HasForeignKey("TaskId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TaskListNav"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MP.TaskMan/Migrations/20250703101600_AddTaskGroup.cs b/MP.TaskMan/Migrations/20250703101600_AddTaskGroup.cs new file mode 100644 index 00000000..a5f5c66f --- /dev/null +++ b/MP.TaskMan/Migrations/20250703101600_AddTaskGroup.cs @@ -0,0 +1,42 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MP.TaskMan.Migrations +{ + public partial class AddTaskGroup : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Group", + table: "TaskList", + type: "int", + nullable: false, + defaultValue: 1); + + migrationBuilder.CreateTable( + name: "DbSetTaskResult", + columns: table => new + { + Task = table.Column(type: "nvarchar(450)", nullable: false), + ExecResult = table.Column(type: "int", nullable: false), + TextResult = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_DbSetTaskResult", x => x.Task); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DbSetTaskResult"); + + migrationBuilder.DropColumn( + name: "Group", + table: "TaskList"); + } + } +} diff --git a/MP.TaskMan/Migrations/TaskContextModelSnapshot.cs b/MP.TaskMan/Migrations/TaskContextModelSnapshot.cs index e56f525d..5b460bc6 100644 --- a/MP.TaskMan/Migrations/TaskContextModelSnapshot.cs +++ b/MP.TaskMan/Migrations/TaskContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace MP.TaskMan.Migrations #pragma warning disable 612, 618 modelBuilder .UseCollation("SQL_Latin1_General_CP1_CI_AS") - .HasAnnotation("ProductVersion", "6.0.33") + .HasAnnotation("ProductVersion", "6.0.36") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); @@ -85,6 +85,9 @@ namespace MP.TaskMan.Migrations b.Property("Freq") .HasColumnType("int"); + b.Property("Group") + .HasColumnType("int"); + b.Property("LastDuration") .HasColumnType("float"); @@ -108,6 +111,22 @@ namespace MP.TaskMan.Migrations b.ToTable("TaskList"); }); + modelBuilder.Entity("MP.TaskMan.Models.TaskResultModel", b => + { + b.Property("Task") + .HasColumnType("nvarchar(450)"); + + b.Property("ExecResult") + .HasColumnType("int"); + + b.Property("TextResult") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Task"); + + b.ToTable("DbSetTaskResult"); + }); + modelBuilder.Entity("MP.TaskMan.Models.TaskExecModel", b => { b.HasOne("MP.TaskMan.Models.TaskListModel", "TaskListNav") diff --git a/MP.TaskMan/Models/TaskListModel.cs b/MP.TaskMan/Models/TaskListModel.cs index 292b5ea6..f27cfff4 100644 --- a/MP.TaskMan/Models/TaskListModel.cs +++ b/MP.TaskMan/Models/TaskListModel.cs @@ -19,6 +19,11 @@ namespace MP.TaskMan.Models [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int TaskId { get; set; } = 0; + /// + /// Gruppo task (per gestione precedenze e semaforo exec) + /// + public int Group { get; set; } = 1; + /// /// Ordinale x esecuzione /// @@ -42,7 +47,7 @@ namespace MP.TaskMan.Models /// /// Tipo Task /// - public Task2ExeType TType { get; set; } = Task2ExeType.ND; + public Task2ExeType TType { get; set; } = Task2ExeType.ALL; /// /// Comando da invocare diff --git a/MP.TaskMan/Objects/Enums.cs b/MP.TaskMan/Objects/Enums.cs index 6173e302..b26f093e 100644 --- a/MP.TaskMan/Objects/Enums.cs +++ b/MP.TaskMan/Objects/Enums.cs @@ -40,7 +40,7 @@ namespace MP.TaskMan.Objects /// /// Tipo indefinito / ALL /// - ND, + ALL, /// /// Chiamata exe esterno diff --git a/MP.TaskMan/Services/TaskService.cs b/MP.TaskMan/Services/TaskService.cs index e1ec23c6..2da2b596 100644 --- a/MP.TaskMan/Services/TaskService.cs +++ b/MP.TaskMan/Services/TaskService.cs @@ -126,6 +126,7 @@ namespace MP.TaskMan.Services case Task2ExeType.SqlStored: answ = MLController.ExecuteSqlTask(TaskRec.TaskId, SchedNext); break; + case Task2ExeType.RestCallGet: DateTime dtStart = DateTime.Now; // in primis testo la chiamata al servizio Health @@ -149,11 +150,12 @@ namespace MP.TaskMan.Services answ = MLController.TaskExecSaveExecuted(TaskRec.TaskId, SchedNext, tExeMod); } break; + default: break; } // svuoto cache! - await FlushCache(); + await FlushCacheAsync(); } return answ; } @@ -162,10 +164,10 @@ namespace MP.TaskMan.Services /// Pulizia cache Redis (tutta) /// /// - public async Task FlushCache() + public bool FlushCache() { RedisValue pattern = new RedisValue($"{RedisBaseKey}:*"); - bool answ = await ExecFlushRedisPattern(pattern); + bool answ = ExecFlushRedisPattern(pattern); return answ; } @@ -173,10 +175,32 @@ namespace MP.TaskMan.Services /// Pulizia cache Redis per chiave specifica (da RedisBaseKey...) /// /// - public async Task FlushCache(string KeyReq) + public bool FlushCache(string KeyReq) { RedisValue pattern = new RedisValue($"{RedisBaseKey}:{KeyReq}:*"); - bool answ = await ExecFlushRedisPattern(pattern); + bool answ = ExecFlushRedisPattern(pattern); + return answ; + } + + /// + /// Pulizia cache Redis (tutta) modalità Async + /// + /// + public async Task FlushCacheAsync() + { + RedisValue pattern = new RedisValue($"{RedisBaseKey}:*"); + bool answ = await ExecFlushRedisPatternAsync(pattern); + return answ; + } + + /// + /// Pulizia cache Redis per chiave specifica (da RedisBaseKey...) modalità Async + /// + /// + public async Task FlushCacheAsync(string KeyReq) + { + RedisValue pattern = new RedisValue($"{RedisBaseKey}:{KeyReq}:*"); + bool answ = await ExecFlushRedisPatternAsync(pattern); return answ; } @@ -292,7 +316,20 @@ namespace MP.TaskMan.Services bool dbResult = MLController.TaskListMove(rec2upd, moveUp); await Task.Delay(50); // svuoto cache! - await FlushCache(); + await FlushCacheAsync(); + return dbResult; + } + + /// + /// Riordino record di un dato gruppo (da richiamare post cambio gruppo...) + /// + /// + /// + public bool TaskListReorder(int codGroup) + { + bool dbResult = MLController.TaskListReorder(codGroup); + // svuoto cache! + FlushCache(); return dbResult; } @@ -306,7 +343,7 @@ namespace MP.TaskMan.Services bool dbResult = MLController.TaskListUpsert(rec2upd); await Task.Delay(50); // svuoto cache! - await FlushCache(); + await FlushCacheAsync(); return dbResult; } @@ -336,18 +373,17 @@ namespace MP.TaskMan.Services private Dictionary connStrParams = new Dictionary(); - private string DataBase { get; set; } = ""; - - private string DataSource { get; set; } = ""; - - private string RedisBaseKey { get; set; } = "MP:TASK"; - #endregion Private Fields #region Private Properties + private string DataBase { get; set; } = ""; + + private string DataSource { get; set; } = ""; + private MpTaskController MLController { get; set; } = null!; private RestCallService RCallService { get; set; } = null!; + private string RedisBaseKey { get; set; } = "MP:TASK"; #endregion Private Properties @@ -358,7 +394,35 @@ namespace MP.TaskMan.Services ///
/// /// - private async Task ExecFlushRedisPattern(RedisValue pattern) + private bool ExecFlushRedisPattern(RedisValue pattern) + { + bool answ = false; + var listEndpoints = redisConn.GetEndPoints(); + foreach (var endPoint in listEndpoints) + { + //var server = redisConnAdmin.GetServer(listEndpoints[0]); + var server = redisConn.GetServer(endPoint); + if (server != null) + { + var keyList = server.Keys(redisDb.Database, pattern); + foreach (var item in keyList) + { + redisDb.KeyDelete(item); + } + answ = true; + } + } + // notifico update ai client in ascolto x reset cache + NotifyReloadRequest($"FlushRedisCache | {pattern}"); + return answ; + } + + /// + /// Esegue flush memoria redis dato pattern modalità Async + /// + /// + /// + private async Task ExecFlushRedisPatternAsync(RedisValue pattern) { bool answ = false; var listEndpoints = redisConn.GetEndPoints(); diff --git a/MP.TaskMan/TaskEdit.razor b/MP.TaskMan/TaskEdit.razor index 59bd3a17..e13d4849 100644 --- a/MP.TaskMan/TaskEdit.razor +++ b/MP.TaskMan/TaskEdit.razor @@ -1,94 +1,100 @@ -@if (CurrRecord != null) +@if (isProcessing) { -
-
-
-
- - -
-
-
-
-
-
- -
-
- -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
- -
-
- - -
-
+ } +else +{ + if (CurrRecord != null) + { +
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+ +
+
+ } +} \ No newline at end of file diff --git a/MP.TaskMan/TaskEdit.razor.cs b/MP.TaskMan/TaskEdit.razor.cs index 6a250fee..ca8b68d3 100644 --- a/MP.TaskMan/TaskEdit.razor.cs +++ b/MP.TaskMan/TaskEdit.razor.cs @@ -16,6 +16,13 @@ namespace MP.TaskMan #endregion Public Properties + protected int oldGroup = 0; + + protected override void OnParametersSet() + { + oldGroup = CurrRecord != null ? CurrRecord.Group : 0; + } + #region Protected Properties [Inject] @@ -32,15 +39,26 @@ namespace MP.TaskMan protected async Task doSave() { + isProcessing = true; bool fatto = false; await Task.Delay(1); if (CurrRecord != null) { fatto = await TService.TaskListUpsert(CurrRecord); + // se cambiato gruppo chiamo reorg gruppo old/new... + if (CurrRecord.Group != oldGroup) + { + TService.TaskListReorder(oldGroup); + TService.TaskListReorder(CurrRecord.Group); + oldGroup = CurrRecord.Group; + } } + isProcessing = false; await EC_update.InvokeAsync(fatto); } #endregion Protected Methods + + private bool isProcessing= false; } } \ No newline at end of file diff --git a/MP.TaskMan/TaskList.razor b/MP.TaskMan/TaskList.razor index e269e020..ae310443 100644 --- a/MP.TaskMan/TaskList.razor +++ b/MP.TaskMan/TaskList.razor @@ -8,7 +8,7 @@
- @if (TypeSel != MP.TaskMan.Objects.Enums.Task2ExeType.ND) + @if (TypeSel != MP.TaskMan.Objects.Enums.Task2ExeType.ALL) { @if (currRecord == null) { @@ -21,7 +21,7 @@ } else { - + }