diff --git a/AGENTS.md b/AGENTS.md index 9c089229..1a45c898 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,94 +1,24 @@ -# CI to Local Workflow Guide +# MAPO-CORE Agent Instructions -This document describes how the GitLab CI pipeline in this repository translates to local commands that can be run on your machine. It also contains helper scripts and environment variables used by the CI. +## Core Context +- **Primary Goal**: Optimization and refactoring of the `MP-SPEC.sln` solution, focusing on migrating legacy Redis/DB caching to `FusionCache` (Memory + Redis + DB) in `MP.SPEC\Data\MpDataService.cs`. +- **Language**: C# (primary), PowerShell (scripts). +- **Documentation/Comments**: MUST be in **Italiano**. +- **Code Style**: Maintain existing region organization (`#region Public Methods`, etc.). +- **Reference Docs**: See `Refactor_Plan.md` for the current migration status and detailed strategy. -## Environment Variables -All variables listed below are interpolated in the CI templates. When running locally you can set them in a PowerShell profile or via `dotnet` arguments. +## Development Workflow +- **Build & Verification**: + - Use `./build_all_par.ps1 --agent` to build all solutions silently. + - Always verify that changes do not leave partial traces of old classes that break compilation. +- **Refactoring Strategy (`MpDataService.cs`)**: + - Use `GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tags)` as the standard for all data access. + - Target methods currently using manual `redisDb.StringGetAsync` / `StringSetAsync` patterns. +- **Testing**: + - Check the codebase for existing testing patterns before proposing new ones. -| Variable | Description | Typical value | -|----------|--------------|---------------| -| `SOL_NAME` | Solution name to restore | **MP-STATS.sln** | -| `PROJ_PATH` | Directory containing the main project | **MP.Stats** | -| `APP_NAME` | Main project file name (without `.csproj`) | **MP.Stats** | -| `NUGET_PATH` | NuGet credential file | **`C:\\Users\\samuele.steamw\AppData\Roaming\NuGet\Credentials.config`** | -| `NEXUS_PATH` | Nexus host URL | **https://nexus.steamware.net** | -| `DEST` | Artifacts output folder | **bin\publish** | -| `VERS_MAIN`, `VERS_MAIN_APP`, `VERSSUB` | Version strings used in packaging | **1.0.0** / -| `NEXUS_PASSWD` | Nexus password (secure via CI secret) | *Secret* | +## Architecture Notes +- **Multi-Layer Caching**: The system is transitioning from a dual-layer (Redis + DB) to a triple-layer approach via `IFusionCache`. +- **Service Responsibility**: `MpDataService` is the central hub for data access, interacting with `MpSpecController` (EFCore) and `MpMongoController` (MongoDB). +- **Key Management**: Cache keys are heavily managed via `Utils.redis...` constants. Use these to prevent key mismatches. -## Build Pipeline (`buildjob`) – Local Equivalent - -The CI first restores NuGet packages and then builds the solution for the selected `APP_NAME`. - -```powershell -# 1. Restore -#$env:SOL_NAME.sln is resolved by the .nuget-fix script -# In PowerShell: dotnet restore "MP-STATS.sln" - -# 2. Build -# $env:APP_NAME/$env:APP_NAME.csproj points to the project file -# In PowerShell: dotnet build "MP.Stats/MP.Stats.csproj" -``` - -### Helper: `.nuget-fix` -The `.nuget-fix` PowerShell script removes any stale NuGet sources that conflict with the Nexus proxy and re‑adds the latest proxy source with credentials. Ensure this script runs *before* `dotnet restore`. - -## Deploy Pipeline (`deployjob`) – Local Equivalent - -Deployment in CI rebuilds the project, publishes it, hashes the output, and uploads it to Nexus. The same steps can be executed locally. - -```powershell -# 1. Rebuild (same as Build) -# dotnet build "MP.Stats/MP.Stats.csproj" - -# 2. Publish to a local folder -# The `dotnet publish` command mimics the CI publish step. The `-c Release` ensures a Release build. -# In PowerShell: -# dotnet publish "MP.Stats/MP.Stats.csproj" -c Release -o publish - -# 3. Create hashes (MD5 & SHA1) -# The .hashBuild template generates .md5 and .sha1 files alongside the ZIP. A simple replacement can be -# 1. Zip the folder: `Compress-Archive -Path publish -DestinationPath $(APP_NAME).zip` -# 2. Generate hashes: -# (Get-FileHash -Algorithm MD5 "$(APP_NAME).zip").Hash | Out-File "$(APP_NAME).md5" -# (Get-FileHash -Algorithm SHA1 "$(APP_NAME).zip").Hash | Out-File "$(APP_NAME).sha1" - -# 4. Upload to Nexus (requires `curl`) -# Example curl command (CI uses `nexus-curl` script): -# $curl -u $(NUGET_USER):$(NEXUS_PASSWD) "$(NEXUS_PATH)/repository/$(APP_NAME)" -T "$(APP_NAME).zip" -``` - -## Installer & Release -The **installer** template copies the published artifacts to a staging folder and optionally creates installers. The **release** template bumps version numbers, updates the `nuspec`, generates a changelog, and pushes the packages to Nexus. - -Generally these steps are CI‑only, but you can repeat the same `dotnet pack` / `nuget push` commands locally if needed. - -## Common Issues & Fixes - -* _NuGet authentication errors_: Run `.nuget-fix` to reset the sources. -* _Missing SDK_: Verify `dotnet --list-sdks` includes at least one SDK. -* _Hashes not matching_: Ensure the ZIP file is identical to the one CI produced (same path, no hidden files). - -## Quick Start -```powershell -# Restore -.\.nuget-fix - -# Build - -dotnet restore "MP-STATS.sln" -dotnet build "MP.Stats/MP.Stats.csproj" - -# Publish & run - -dotnet publish "MP.Stats/MP.Stats.csproj" -c Release -o publish -dotnet run --project "MP.Stats/MP.Stats.csproj" - -# For hot‑reload during development - -dotnet watch run --project "MP.Stats/MP.Stats.csproj" -``` - ---- - -Feel free to adjust paths or environment variable names if your local setup differs. diff --git a/AGENTS.pdf b/AGENTS.pdf new file mode 100644 index 00000000..be4b911e Binary files /dev/null and b/AGENTS.pdf differ diff --git a/Directory.Packages.props b/Directory.Packages.props index 71c44dc1..aee39b65 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,7 +24,7 @@ - + diff --git a/Egw.Core/Utils.cs b/Egw.Core/Utils.cs index 91376768..49b26d0d 100644 --- a/Egw.Core/Utils.cs +++ b/Egw.Core/Utils.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Reflection; namespace Egw.Core { @@ -19,14 +14,24 @@ namespace Egw.Core /// public static async Task SaveToCsv(List reportData, string path, char separator) { + // 1. Recuperiamo le proprietà del tipo T una sola volta (Risolve i problemi di performance) + PropertyInfo[] properties = typeof(T).GetProperties(); + var lines = new List(); - IEnumerable props = TypeDescriptor.GetProperties(typeof(T)).OfType(); - var header = string.Join(";", props.ToList().Select(x => x.Name)); + + // 2. Creiamo l'header usando il separatore corretto (Risolve il bug del ";" fisso) + var header = string.Join(separator, properties.Select(p => p.Name)); lines.Add(header); - var valueLines = reportData.Select(row => string.Join(separator, header.Split(separator).Select(a => row.GetType().GetProperty(a).GetValue(row, null)))); - //var valueLines = reportData.Select(row => string.Join(";", header.Split(';').Select(a => row.GetType().GetProperty(a).GetValue(row, null)))); + + // 3. Estraiamo i valori gestendo i possibili null (Risolve il tuo warning) + var valueLines = reportData + .Where(row => row != null) + .Select(row => string.Join(separator, properties.Select(p => p.GetValue(row)?.ToString() ?? string.Empty))); + lines.AddRange(valueLines); - await Task.Run(() => File.WriteAllLines(path, lines.ToArray())); + + // 4. Utilizziamo il metodo di scrittura asincrono nativo di .NET + await File.WriteAllLinesAsync(path, lines); } } } diff --git a/MP-TAB.sln b/MP-TAB.sln deleted file mode 100644 index 339f020e..00000000 --- a/MP-TAB.sln +++ /dev/null @@ -1,37 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32126.317 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.Data", "MP.Data\MP.Data.csproj", "{10BA8450-301D-49C7-8E1E-21B7469C225C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP-TAB", "MP-TAB\MP-TAB\MP-TAB.csproj", "{9141D627-EE10-4BF6-9A2C-AAC6845E185F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP-TAB.Client", "MP-TAB\MP-TAB.Client\MP-TAB.Client.csproj", "{28559808-58F2-424B-B65C-062AA59839EC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Release|Any CPU.Build.0 = Release|Any CPU - {9141D627-EE10-4BF6-9A2C-AAC6845E185F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9141D627-EE10-4BF6-9A2C-AAC6845E185F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9141D627-EE10-4BF6-9A2C-AAC6845E185F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9141D627-EE10-4BF6-9A2C-AAC6845E185F}.Release|Any CPU.Build.0 = Release|Any CPU - {28559808-58F2-424B-B65C-062AA59839EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {28559808-58F2-424B-B65C-062AA59839EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {28559808-58F2-424B-B65C-062AA59839EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {28559808-58F2-424B-B65C-062AA59839EC}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {632D11D1-088B-4795-97E5-048534002558} - EndGlobalSection -EndGlobal diff --git a/MP-TAB3/Components/SelectCodArt.razor.cs b/MP-TAB3/Components/SelectCodArt.razor.cs index f1a0b850..4fb4dd3b 100644 --- a/MP-TAB3/Components/SelectCodArt.razor.cs +++ b/MP-TAB3/Components/SelectCodArt.razor.cs @@ -105,7 +105,7 @@ namespace MP_TAB3.Components if (!ListArtDisabled) { Log.Debug("START GetArticoli"); - var rawData = await MDataService.ArticoliGetSearch(10000, "*", searchVal); + var rawData = await MDataService.ArticoliGetSearch(10000,"*", "*", searchVal); // trasformo! if (rawData != null) { diff --git a/MP-TAB3/Components/TcHistoryFilter.razor.cs b/MP-TAB3/Components/TcHistoryFilter.razor.cs index 004c0bab..f9898a35 100644 --- a/MP-TAB3/Components/TcHistoryFilter.razor.cs +++ b/MP-TAB3/Components/TcHistoryFilter.razor.cs @@ -137,7 +137,7 @@ namespace MP_TAB3.Components if (!ListArtDisabled) { Log.Debug("START GetArticoli"); - var rawData = await MDataService.ArticoliGetSearch(10000, "*", searchVal); + var rawData = await MDataService.ArticoliGetSearch(10000,"*", "*", searchVal); // trasformo! if (rawData != null) { diff --git a/MP-TAB3/MP-TAB3.csproj b/MP-TAB3/MP-TAB3.csproj index a078167b..f073261a 100644 --- a/MP-TAB3/MP-TAB3.csproj +++ b/MP-TAB3/MP-TAB3.csproj @@ -3,7 +3,7 @@ net8.0 enable - 8.16.2604.2718 + 8.16.2606.408 enable MP_TAB3 diff --git a/MP-TAB3/Program.cs b/MP-TAB3/Program.cs index 178df0d6..f00f0736 100644 --- a/MP-TAB3/Program.cs +++ b/MP-TAB3/Program.cs @@ -2,16 +2,18 @@ using Blazored.LocalStorage; using Blazored.SessionStorage; #endif -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Web; -using Microsoft.AspNetCore.StaticFiles; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.FileProviders; using MP.Data; using MP.Data.Services; using NLog; using NLog.Web; using StackExchange.Redis; -using static Org.BouncyCastle.Math.EC.ECCurve; +using ZiggyCreatures.Caching.Fusion; +using ZiggyCreatures.Caching.Fusion.Backplane.StackExchangeRedis; +using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson; var builder = WebApplication.CreateBuilder(args); @@ -27,15 +29,45 @@ var cString = configuration.GetConnectionString("Redis"); string connStringRedis = cString ?? "localhost:6379, DefaultDatabase=5, connectTimeout=5000, syncTimeout=5000, asyncTimeout=5000, abortConnect=false, ssl=false"; //string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":")); // avvio oggetto shared x redis... -var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); +IConnectionMultiplexer redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); // Add services x accesso dati builder.Services.AddSingleton(redisMultiplexer); +// ✅ FusionCache +builder.Services.AddFusionCache() + .WithDistributedCache(sp => sp.GetRequiredService()) + .WithSerializer(new FusionCacheNewtonsoftJsonSerializer()) + .WithBackplane(new RedisBackplane(new RedisBackplaneOptions + { + ConnectionMultiplexerFactory = () => Task.FromResult(redisMultiplexer) + })); + +// Metodi principali x accesso dati +var connStr = builder.Configuration.GetConnectionString("MP.Data") + ?? throw new InvalidOperationException("ConnString 'MP.Data' mancante."); +// aggiungo il costruttore x i vari DbContextFactory +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStr) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + +var connStrFL = builder.Configuration.GetConnectionString("MP.Flux") + ?? throw new InvalidOperationException("ConnString 'MP.Flux' mancante."); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStrFL) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); + +// Init centralizzato Repository/Servizi da MP.Data Services +builder.Services.AddTabDataLayer(); + +#if false builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -43,13 +75,10 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddScoped(); -#if false -builder.Services.AddBlazoredLocalStorage(); -builder.Services.AddBlazoredSessionStorage(); -#endif // aggiunta helper local/session storage service builder.Services.AddScoped(); -builder.Services.AddScoped(); +builder.Services.AddScoped(); +#endif // gestione email builder.Services.Configure(builder.Configuration.GetSection(nameof(MailKitMailSettings))); @@ -62,7 +91,7 @@ logger.Info("Aggiunti services"); var app = builder.Build(); // aggiunt base URL x routing corretto -var pathBase= configuration.GetValue("SpecialConf:AppUrl") ?? (configuration.GetValue("OptConf:AppUrl") ?? ""); +var pathBase = configuration.GetValue("SpecialConf:AppUrl") ?? (configuration.GetValue("OptConf:AppUrl") ?? ""); app.UsePathBase(pathBase); // Configure the HTTP request pipeline. @@ -78,7 +107,7 @@ app.UseHttpsRedirection(); app.UseStaticFiles(); // gestione static files: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-8.0 -string BasePathDisegni = configuration.GetValue("ServerConf:BasePathDisegni") ?? configuration.GetValue("OptConf:BasePathDisegni")?? ""; +string BasePathDisegni = configuration.GetValue("ServerConf:BasePathDisegni") ?? configuration.GetValue("OptConf:BasePathDisegni") ?? ""; if (!string.IsNullOrEmpty(BasePathDisegni)) { // verifico esista folder disegni diff --git a/MP-TAB3/Resources/ChangeLog.html b/MP-TAB3/Resources/ChangeLog.html index 133a7fea..6e774415 100644 --- a/MP-TAB3/Resources/ChangeLog.html +++ b/MP-TAB3/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOSPEC -

Versione: 8.16.2604.2718

+

Versione: 8.16.2606.408


Note di rilascio:
  • diff --git a/MP-TAB3/Resources/VersNum.txt b/MP-TAB3/Resources/VersNum.txt index 87ec763e..988a0006 100644 --- a/MP-TAB3/Resources/VersNum.txt +++ b/MP-TAB3/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2604.2718 +8.16.2606.408 diff --git a/MP-TAB3/Resources/manifest.xml b/MP-TAB3/Resources/manifest.xml index 6613f4d9..1c9cc682 100644 --- a/MP-TAB3/Resources/manifest.xml +++ b/MP-TAB3/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2604.2718 + 8.16.2606.408 https://nexus.steamware.net/repository/SWS/MP-TAB3/stable/LAST/MP-TAB3.zip https://nexus.steamware.net/repository/SWS/MP-TAB3/stable/LAST/ChangeLog.html false diff --git a/MP-TAB3/appsettings.json b/MP-TAB3/appsettings.json index 6ef14f69..47c80c14 100644 --- a/MP-TAB3/appsettings.json +++ b/MP-TAB3/appsettings.json @@ -8,16 +8,10 @@ "AllowedHosts": "*", "CodApp": "MP.TAB", "ConnectionStrings": { - //"Redis": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=6,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true", - //"MP.All": "Server=SQL2022PROD;Database=Donati_LAV_MoonPro_prod; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", - //"MP.Mon": "Server=SQL2022PROD;Database=Donati_LAV_MoonPro_prod; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", - //"MP.IS": "Server=SQL2022PROD;Database=MoonPro_IS_EdilChim; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.INVE;", - //"MP.Tab": "Server=SQL2022PROD;Database=Donati_LAV_MoonPro_prod; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", - //"MP.Mag": "Server=SQL2022PROD;Database=MoonPro_MAG; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;" - "Redis": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=5,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true", "MP.All": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", "MP.Data": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", + "MP.Flux": "Server=SQL2016DEV;Database=MoonPro_FluxData; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", "MP.Mon": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", "MP.IS": "Server=SQL2016DEV;Database=MoonPro_IS_EdilChim; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.INVE;", "MP.Tab": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.TAB3;", diff --git a/MP-WAMON.sln b/MP-WAMON.sln deleted file mode 100644 index d0829635..00000000 --- a/MP-WAMON.sln +++ /dev/null @@ -1,43 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32126.317 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.Data", "MP.Data\MP.Data.csproj", "{10BA8450-301D-49C7-8E1E-21B7469C225C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.Mon", "MP.Mon\MP.Mon.csproj", "{7780FA7A-3597-4098-81C1-DC9AD6AE7A98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MP.WASM.Mon.Server", "MP.WASM.Mon\Server\MP.WASM.Mon.Server.csproj", "{4A98B7F4-4EC6-4284-9D6C-63203DB981B1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MP.WASM.Mon.Client", "MP.WASM.Mon\Client\MP.WASM.Mon.Client.csproj", "{9BF7BDE7-016A-458C-8791-494FD4204301}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10BA8450-301D-49C7-8E1E-21B7469C225C}.Release|Any CPU.Build.0 = Release|Any CPU - {7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Release|Any CPU.Build.0 = Release|Any CPU - {4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Release|Any CPU.Build.0 = Release|Any CPU - {9BF7BDE7-016A-458C-8791-494FD4204301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9BF7BDE7-016A-458C-8791-494FD4204301}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9BF7BDE7-016A-458C-8791-494FD4204301}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9BF7BDE7-016A-458C-8791-494FD4204301}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {632D11D1-088B-4795-97E5-048534002558} - EndGlobalSection -EndGlobal diff --git a/MP.AppAuth/Controllers/AppAuthController.cs b/MP.AppAuth/Controllers/AppAuthController.cs index bd6047d5..91407d3e 100644 --- a/MP.AppAuth/Controllers/AppAuthController.cs +++ b/MP.AppAuth/Controllers/AppAuthController.cs @@ -12,16 +12,23 @@ namespace MP.AppAuth.Controllers { public class AppAuthController { + #region Private Fields + + private readonly IConfiguration _configuration; + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + #endregion + #region Public Constructors public AppAuthController(IConfiguration configuration) { _configuration = configuration; - Log.Info("Avviata classe AppAuthController"); } - #endregion Public Constructors + #endregion #region Public Methods @@ -189,8 +196,6 @@ namespace MP.AppAuth.Controllers return dbResult; } - - /// /// Elenco Record x gestione Update /// @@ -225,12 +230,5 @@ namespace MP.AppAuth.Controllers } #endregion Public Methods - - #region Private Fields - - private static IConfiguration _configuration; - private static Logger Log = LogManager.GetCurrentClassLogger(); - - #endregion Private Fields } -} \ No newline at end of file +} diff --git a/MP.AppAuth/Controllers/AppUserController.cs b/MP.AppAuth/Controllers/AppUserController.cs index dde09586..f906fbb5 100644 --- a/MP.AppAuth/Controllers/AppUserController.cs +++ b/MP.AppAuth/Controllers/AppUserController.cs @@ -11,6 +11,16 @@ namespace MP.AppAuth.Controllers { public class AppUserController : IDisposable { + #region Private Fields + + private readonly IConfiguration _configuration; + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + private bool _disposed = false; + + #endregion + #region Public Constructors public AppUserController(IConfiguration configuration) @@ -19,7 +29,7 @@ namespace MP.AppAuth.Controllers Log.Info("Avviata classe AppUserController"); } - #endregion Public Constructors + #endregion #region Public Methods @@ -42,18 +52,28 @@ namespace MP.AppAuth.Controllers return dbResult; } - public void Dispose() - { - GC.Collect(); - } - #endregion Public Methods - #region Private Fields + #region Protected Methods - private static IConfiguration _configuration = null!; - private static Logger Log = LogManager.GetCurrentClassLogger(); + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + // Free managed resources here + } + _disposed = true; + } + } - #endregion Private Fields + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion } -} \ No newline at end of file +} diff --git a/MP.AppAuth/Controllers/MPController .cs b/MP.AppAuth/Controllers/MPController .cs index b3dee069..739b5150 100644 --- a/MP.AppAuth/Controllers/MPController .cs +++ b/MP.AppAuth/Controllers/MPController .cs @@ -10,19 +10,15 @@ namespace MP.AppAuth.Controllers { public class MPController : IDisposable { - #region Public Fields - - public static MPController dbController; - - #endregion Public Fields - #region Private Fields - private static IConfiguration _configuration; + private readonly IConfiguration _configuration; private static Logger Log = LogManager.GetCurrentClassLogger(); - #endregion Private Fields + private bool _disposed = false; + + #endregion #region Public Constructors @@ -32,7 +28,7 @@ namespace MP.AppAuth.Controllers Log.Info("Avviata classe MpController"); } - #endregion Public Constructors + #endregion #region Public Methods @@ -271,15 +267,6 @@ namespace MP.AppAuth.Controllers return fatto; } - public void Dispose() - { - if (dbController != null) - { - // Clear database controller - dbController.Dispose(); - } - } - /// /// Elenco Record x ListValues /// @@ -380,5 +367,27 @@ namespace MP.AppAuth.Controllers } #endregion Public Methods + + #region Protected Methods + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + // Free managed resources here + } + _disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion } -} \ No newline at end of file +} diff --git a/MP.AppAuth/DataServiceCollectionExtensions.cs b/MP.AppAuth/DataServiceCollectionExtensions.cs new file mode 100644 index 00000000..56841d9a --- /dev/null +++ b/MP.AppAuth/DataServiceCollectionExtensions.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MP.AppAuth +{ + public static class DataServiceCollectionExtensions + { + /// + /// Aggiunta repository/servizi specifici per IOC + /// + /// + /// + public static IServiceCollection AddAuthLandDataLayer(this IServiceCollection services) + { + + return services; + } + } +} diff --git a/MP.AppAuth/MoonProContext.cs b/MP.AppAuth/MoonProContext.cs index 6a1d615d..03219310 100644 --- a/MP.AppAuth/MoonProContext.cs +++ b/MP.AppAuth/MoonProContext.cs @@ -18,11 +18,12 @@ namespace MP.AppAuth #region Public Constructors - [Obsolete("This constructor should never be used directly, and is only needed to generate entityframework stuff. Connection string can be adapted as pleased.")] + [Obsolete("This constructor should never be used directly, and is only needed to generate entityframework stuff. DbContextOptions must be supplied.")] public MoonProContext() { } + [Obsolete("This constructor should never be used directly, and is only needed to generate entityframework stuff. DbContextOptions must be supplied.")] public MoonProContext(IConfiguration configuration) { _configuration = configuration; diff --git a/MP.AppAuth/Services/AppAuthService.cs b/MP.AppAuth/Services/AppAuthService.cs index 7ab866af..f4ec89f4 100644 --- a/MP.AppAuth/Services/AppAuthService.cs +++ b/MP.AppAuth/Services/AppAuthService.cs @@ -20,10 +20,6 @@ namespace MP.AppAuth.Services // diritti (cablato) public const string RoleSuperAdmin = "MoonPro_SuperAdmin"; - public static AppAuthController dbController; - public static MPController MpDbController; - public static AppUserController userController; - #endregion Public Fields #region Private Fields @@ -37,15 +33,15 @@ namespace MP.AppAuth.Services private const string rKeyPermUser = $"{redisBaseAddr}:PERM_USER"; - private static IConfiguration _configuration; + private readonly IConfiguration _configuration; - private static ILogger _logger; + private readonly ILogger _logger; - private static JsonSerializerSettings? JSSettings; + private readonly JsonSerializerSettings? JSSettings; private static Logger Log = LogManager.GetCurrentClassLogger(); - private static string Modulo = ""; + private string Modulo = ""; /// /// Durata cache lunga IN SECONDI @@ -60,23 +56,27 @@ namespace MP.AppAuth.Services /// /// Oggetto per connessione a REDIS /// - private IConnectionMultiplexer redisConn; + private readonly IConnectionMultiplexer redisConn; //ISubscriber sub = redis.GetSubscriber(); /// /// Oggetto DB redis da impiegare x chiamate R/W /// - private StackExchange.Redis.IDatabase redisDb = null!; + private readonly StackExchange.Redis.IDatabase redisDb; - private Random rnd = new Random(); + private readonly Random rnd = new Random(); private Dictionary Vocabolario = new Dictionary(); + private readonly AppAuthController _appAuthController; + private readonly MPController _mpController; + private readonly AppUserController _appUserController; + #endregion Private Fields #region Public Constructors - public AppAuthService(IConfiguration configuration, ILogger logger, IConnectionMultiplexer redisConnMult) + public AppAuthService(IConfiguration configuration, ILogger logger, IConnectionMultiplexer redisConnMult, AppAuthController appAuthController, MPController mpController, AppUserController appUserController) { _logger = logger; _configuration = configuration; @@ -103,9 +103,9 @@ namespace MP.AppAuth.Services } else { - dbController = new AppAuthController(configuration); - MpDbController = new MPController(configuration); - userController = new AppUserController(configuration); + _appAuthController = appAuthController; + _mpController = mpController; + _appUserController = appUserController; _logger.LogInformation("DbController OK"); } } @@ -114,7 +114,7 @@ namespace MP.AppAuth.Services #region Private Properties - private string CodApp { get; set; } = ""; + private string CodApp { get; } /// /// Durata cache lunga (+ perturbazione percentuale +/-10%) @@ -153,7 +153,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagCauSca(); + dbResult = _mpController.AnagCauSca(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagCauSca: {ts.TotalMilliseconds} ms"); @@ -169,7 +169,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagClassiTempo(); + dbResult = _mpController.AnagClassiTempo(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagClassiTempo: {ts.TotalMilliseconds} ms"); @@ -185,7 +185,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagEventi(); + dbResult = _mpController.AnagEventi(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagEventi: {ts.TotalMilliseconds} ms"); @@ -201,7 +201,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = dbController.AnagGruppiGetAll(); + dbResult = _appAuthController.AnagGruppiGetAll(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagGruppiAll: {ts.TotalMilliseconds} ms"); @@ -213,7 +213,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = dbController.AnagGruppiFilt(codTipo); + dbResult = _appAuthController.AnagGruppiFilt(codTipo); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagGruppiFilt: {ts.TotalMilliseconds} ms"); @@ -229,7 +229,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagIngressi(); + dbResult = _mpController.AnagIngressi(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagIngressi: {ts.TotalMilliseconds} ms"); @@ -241,7 +241,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.AnagKeyValuesUpsert(currRec); + answ = _mpController.AnagKeyValuesUpsert(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"AnagKeyValAdd | Aggiunto rec | NomeVar: {currRec.NomeVar} | durata: {ts.TotalMilliseconds} ms"); @@ -253,7 +253,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.AnagKeyValuesDelete(NomeVar); + answ = _mpController.AnagKeyValuesDelete(NomeVar); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"AnagKeyValDelete | Effettuata cancellazione | NomeVar: {NomeVar} | durata: {ts.TotalMilliseconds} ms"); @@ -265,7 +265,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagKeyValuesGetAll(); + dbResult = _mpController.AnagKeyValuesGetAll(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagKeyValList: {ts.TotalMilliseconds} ms"); @@ -277,7 +277,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.AnagKeyValuesUpsert(currRec); + answ = _mpController.AnagKeyValuesUpsert(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"AnagKeyValUpd | Effettuata modifica | NomeVar: {currRec.NomeVar} | durata: {ts.TotalMilliseconds} ms"); @@ -293,7 +293,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagMicroStati(); + dbResult = _mpController.AnagMicroStati(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagMicroStati: {ts.TotalMilliseconds} ms"); @@ -305,7 +305,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - var rawData = dbController + var rawData = _appAuthController .AnagOpByGruppoGetFilt(codGruppo, searchVal); dbResult = rawData .GroupBy(user => user.MatrOpr) @@ -322,7 +322,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = dbController.AnagOpGetAll(searchVal); + dbResult = _appAuthController.AnagOpGetAll(searchVal); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagOperList: {ts.TotalMilliseconds} ms"); @@ -338,7 +338,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.AnagStati(); + dbResult = _mpController.AnagStati(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per AnagStati: {ts.TotalMilliseconds} ms"); @@ -350,7 +350,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.ConfigUpsert(currRec); + answ = _mpController.ConfigUpsert(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"ConfigAdd | Aggiunto rec | Chiave: {currRec.Chiave} | durata: {ts.TotalMilliseconds} ms"); @@ -362,7 +362,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.ConfigDelete(Chiave); + answ = _mpController.ConfigDelete(Chiave); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"ConfigDelete | Effettuata cancellazione | Chiave: {Chiave} | durata: {ts.TotalMilliseconds} ms"); @@ -374,7 +374,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.ConfigGetAll(); + dbResult = _mpController.ConfigGetAll(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per ConfigList: {ts.TotalMilliseconds} ms"); @@ -386,7 +386,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.ConfigUpsert(currRec); + answ = _mpController.ConfigUpsert(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"ConfigUpd | Effettuata modifica | Chiave: {currRec.Chiave} | durata: {ts.TotalMilliseconds} ms"); @@ -415,7 +415,7 @@ namespace MP.AppAuth.Services else { // recupero diritti utente - dbResult = userController.DirittiUtente(UserName, Modulo); + dbResult = _appUserController.DirittiUtente(UserName, Modulo); rawData = JsonConvert.SerializeObject(dbResult, JSSettings); await redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } @@ -430,11 +430,8 @@ namespace MP.AppAuth.Services public void Dispose() { - // Clear database controller - if (MpDbController != null) - { - MpDbController.Dispose(); - } + // Clear database controllers + _mpController?.Dispose(); } public async Task FlushRedisCache() @@ -455,7 +452,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.ListValues(); + dbResult = _mpController.ListValues(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per ListValues: {ts.TotalMilliseconds} ms"); @@ -484,7 +481,7 @@ namespace MP.AppAuth.Services else { // recupero diritti utente - dbResult = MpDbController.MacchineGetAll(); + dbResult = _mpController.MacchineGetAll(); rawData = JsonConvert.SerializeObject(dbResult, JSSettings); redisDb.StringSet(currKey, rawData, UltraLongCache); } @@ -526,7 +523,7 @@ namespace MP.AppAuth.Services else { // recupero diritti utente - var userRightList = userController.DirittiUtente(UserName, Modulo); + var userRightList = _appUserController.DirittiUtente(UserName, Modulo); // proietto come funzioni... var ListFunc = userRightList.Select(x => x.Funzione).ToList(); // trasformo i permessi utente @@ -534,7 +531,7 @@ namespace MP.AppAuth.Services { ListFunc = new List(); } - dbResult = dbController.PermessiGetByFunc(ListFunc); + dbResult = _appAuthController.PermessiGetByFunc(ListFunc); rawData = JsonConvert.SerializeObject(dbResult, JSSettings); await redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } @@ -565,7 +562,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = dbController.UpdManGetAll(); + dbResult = _appAuthController.UpdManGetAll(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per UpdManList: {ts.TotalMilliseconds} ms"); @@ -577,7 +574,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.VocabolarioUpsert(currRec); + answ = _mpController.VocabolarioUpsert(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"VocabolarioAdd | Aggiunto rec | lingua: {currRec.Lingua} | lemma: {currRec.Lemma} | durata: {ts.TotalMilliseconds} ms"); @@ -589,7 +586,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.VocabolarioDelete(currRec); + answ = _mpController.VocabolarioDelete(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"VocabolarioDelete | Effettuata cancellazione | lingua: {currRec.Lingua} | lemma: {currRec.Lemma} | durata: {ts.TotalMilliseconds} ms"); @@ -601,7 +598,7 @@ namespace MP.AppAuth.Services List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = MpDbController.VocabolarioGetAll(); + dbResult = _mpController.VocabolarioGetAll(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per VocabolarioList: {ts.TotalMilliseconds} ms"); @@ -613,7 +610,7 @@ namespace MP.AppAuth.Services bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - answ = MpDbController.VocabolarioUpsert(currRec); + answ = _mpController.VocabolarioUpsert(currRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"VocabolarioUpd | Effettuata modifica | lingua: {currRec.Lingua} | lemma: {currRec.Lemma} | durata: {ts.TotalMilliseconds} ms"); @@ -641,7 +638,7 @@ namespace MP.AppAuth.Services } else { - Vocabolario = dbController + Vocabolario = _appAuthController .VocabolarioGetAll() .ToDictionary(x => $"{x.Lingua}#{x.Lemma}", x => x.Traduzione); rawData = JsonConvert.SerializeObject(Vocabolario); @@ -665,10 +662,10 @@ namespace MP.AppAuth.Services { bool answ = false; var masterEndpoint = redisConn.GetEndPoints() - .Where(ep => redisConn.GetServer(ep).IsConnected && !redisConn.GetServer(ep).IsReplica) - .FirstOrDefault(); + .Where(ep => redisConn.GetServer(ep).IsConnected && !redisConn.GetServer(ep).IsReplica) + .FirstOrDefault(); - // sepattern è "*" elimino intero DB... + // se pattern è "*" elimino intero DB... if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null)) { redisConn.GetServer(masterEndpoint).FlushDatabase(database: redisDb.Database); @@ -699,4 +696,4 @@ namespace MP.AppAuth.Services #endregion Private Methods } -} \ No newline at end of file +} diff --git a/MP.Core/DTO/CountResultDto.cs b/MP.Core/DTO/CountResultDto.cs new file mode 100644 index 00000000..c55a390b --- /dev/null +++ b/MP.Core/DTO/CountResultDto.cs @@ -0,0 +1,7 @@ +namespace MP.Core.DTO +{ + public class CountResultDto + { + public int NumCount { get; set; } + } +} diff --git a/MP.Core/DTO/FluxLogDTO.cs b/MP.Core/DTO/FluxLogDTO.cs index 3b28e2c1..fcc54437 100644 --- a/MP.Core/DTO/FluxLogDTO.cs +++ b/MP.Core/DTO/FluxLogDTO.cs @@ -1,17 +1,15 @@ -using System; - -namespace MP.Core.DTO +namespace MP.Core.DTO { public class FluxLogDTO { - public string IdxMacchina { get; set; } + public string IdxMacchina { get; set; } = string.Empty; public DateTime dtEvento { get; set; } - public string CodFlux { get; set; } + public string CodFlux { get; set; } = string.Empty; - public string Valore { get; set; } + public string Valore { get; set; } = string.Empty; - public string ValoreEdit { get; set; } + public string ValoreEdit { get; set; } = string.Empty; } } \ No newline at end of file diff --git a/MP.Core/DTO/MappaStatoExplDTO.cs b/MP.Core/DTO/MappaStatoExplDTO.cs index 12fe6b44..353f7975 100644 --- a/MP.Core/DTO/MappaStatoExplDTO.cs +++ b/MP.Core/DTO/MappaStatoExplDTO.cs @@ -9,20 +9,20 @@ namespace MP.Core.DTO { public int RowNum { get; set; } public DateTime? LastUpdate { get; set; } - public string IdxMacchina { get; set; } - public string CodMacchina { get; set; } - public string Nome { get; set; } - public string Url { get; set; } + public string IdxMacchina { get; set; } = string.Empty; + public string CodMacchina { get; set; } = string.Empty; + public string Nome { get; set; } = string.Empty; + public string Url { get; set; } = string.Empty; public int? IdxOdl { get; set; } = 0; public int? IdxPOdl { get; set; } = 0; - public string CodArticolo { get; set; } - public string Disegno { get; set; } + public string CodArticolo { get; set; } = string.Empty; + public string Disegno { get; set; } = string.Empty; public int NumPezzi { get; set; } = 0; public decimal TCAssegnato { get; set; } = 0; public DateTime? DataInizioOdl { get; set; } - public string Semaforo { get; set; } + public string Semaforo { get; set; } = string.Empty; public int? IdxStato { get; set; } - public string DescrizioneStato { get; set; } + public string DescrizioneStato { get; set; } = string.Empty; public double? Durata { get; set; } public int PezziProd { get; set; } = 0; public int PezziConf { get; set; } = 0; @@ -65,7 +65,7 @@ namespace MP.Core.DTO get { int answ = 0; - if(NumPezzi < PezziProd) + if (NumPezzi < PezziProd) { answ = Math.Abs(NumPezzi - PezziProd); } diff --git a/MP.Core/DTO/ParetoFluxLogDTO.cs b/MP.Core/DTO/ParetoFluxLogDTO.cs index 94aea2c1..6b5e7239 100644 --- a/MP.Core/DTO/ParetoFluxLogDTO.cs +++ b/MP.Core/DTO/ParetoFluxLogDTO.cs @@ -1,11 +1,9 @@ -using System; - -namespace MP.Core.DTO +namespace MP.Core.DTO { public class ParetoFluxLogDTO { - public string IdxMacchina { get; set; } - public string CodFlux { get; set; } + public string IdxMacchina { get; set; } = string.Empty; + public string CodFlux { get; set; } = string.Empty; public int Qty { get; set; } } } \ No newline at end of file diff --git a/MP.Core/DTO/ULogJsonPayloadDto.cs b/MP.Core/DTO/ULogJsonPayloadDto.cs index bdd43e75..c81acc86 100644 --- a/MP.Core/DTO/ULogJsonPayloadDto.cs +++ b/MP.Core/DTO/ULogJsonPayloadDto.cs @@ -7,7 +7,7 @@ { #region Public Properties - public List fluxData { get; set; } + public List fluxData { get; set; } = new(); #endregion Public Properties } diff --git a/MP.Core/Utils.cs b/MP.Core/Utils.cs index df5f8ec3..5af55b84 100644 --- a/MP.Core/Utils.cs +++ b/MP.Core/Utils.cs @@ -12,34 +12,29 @@ namespace MP.Core public const string redisAnagGruppi = redisBaseAddr + "Cache:AnagGruppi"; public const string redisAnagStati = redisBaseAddr + "Cache:AnagStati"; + public const string redisAnagGruppiOpr = redisBaseAddr + "Cache:GrpByOpr"; public const string redisArtByDossier = redisBaseAddr + "Cache:ArtByDossier"; - public const string redisArtList = redisBaseAddr + "Cache:ArtList"; - public const string redisBaseAddr = "MP:"; - public const string redisConfFlux = redisBaseAddr + "Cache:ConfFlux"; + public const string redisConfAll = redisBaseAddr + "Cache:ConfigAll"; public const string redisConfKey = redisBaseAddr + "Cache:Config"; - public const string redisDecNumArtKey = redisBaseAddr + "Cache:DecNumArt"; - public const string redisDossByMac = redisBaseAddr + "Cache:DossByMac"; public const string redisDossByMacLast = redisBaseAddr + "Cache:DossByMacLast"; - public const string redisEventList = redisBaseAddr + "Cache:EventList"; - public const string redisFluxByMac = redisBaseAddr + "Cache:FluxByMac"; public const string redisFluxByMacFirst = redisBaseAddr + "Cache:FluxByMacFirst"; public const string redisFluxLogFilt = redisBaseAddr + "Cache:FluxLogFilt"; - public const string redisGiacenzaList = redisBaseAddr + "Cache:GiacenzaList"; - public const string redisKit = redisBaseAddr + "Cache:Kit"; public const string redisKitInst = redisBaseAddr + "Cache:Kit:Inst"; public const string redisKitScore = redisBaseAddr + "Cache:Kit:Score"; public const string redisKitTempl = redisBaseAddr + "Cache:Kit:Templ"; public const string redisKitWip = redisBaseAddr + "Cache:Kit:Wip"; + public const string redisIobConf = redisBaseAddr + "Cache:IobConf"; + public const string redisLinkMenu = redisBaseAddr + "Cache:LinkMenu"; public const string redisMacByFlux = redisBaseAddr + "Cache:MacByFlux"; public const string redisMacList = redisBaseAddr + "Cache:MacList"; @@ -49,11 +44,13 @@ namespace MP.Core public const string redisMacRecipePath = redisBaseAddr + "Cache:RecipePath"; public const string redisOdlByBatch = redisXdlData + "OdlByBatch"; + public const string redisOdlByKey = redisXdlData + "OdlByKey"; public const string redisOdlCurrByMac = redisXdlData + "OdlByMac"; public const string redisOdlLastByMac = redisXdlData + "LastOdlByMac"; public const string redisOdlList = redisXdlData + "OdlList"; + public const string redisOdlStats = redisXdlData + "OdlStats"; public const string redisOprList = redisBaseAddr + "Cache:OprList"; @@ -88,12 +85,12 @@ namespace MP.Core public static string redKeyArtUsed { - get => RedHash($"SPEC:Cache:CheckArtUsed"); + get => RedHash($"SPEC:Cache:CheckArtUsed").ToString(); } public static string redKeyTabCheckArt { - get => RedHash($"CACHE:TabCheckArt"); + get => RedHash($"CACHE:TabCheckArt").ToString(); } #endregion Public Properties @@ -180,7 +177,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyCurrObjItems(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyCurrObjItems(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:CurrentParameters:{idxMacchina}"; @@ -192,7 +189,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyDatiMacc(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyDatiMacc(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:DtMac:{idxMacchina}"; @@ -212,7 +209,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyIobConfYaml(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyIobConfYaml(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:IOB:{idxMacchina}:ConfYaml"; @@ -224,7 +221,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyIobMemMap(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyIobMemMap(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:MemMap:{idxMacchina}"; @@ -237,7 +234,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyLastFLog(string idxMacchina, string flog, string baseAddr = null) + public static RedisKey RedKeyLastFLog(string idxMacchina, string flog, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:FLOG:{idxMacchina}:{flog}"; @@ -249,7 +246,7 @@ namespace MP.Core /// /// /// - public static RedisKey RedKeyMach2Iob(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyMach2Iob(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:hM2IOB:{idxMacchina}"; @@ -261,7 +258,7 @@ namespace MP.Core /// /// /// - public static RedisKey RedKeyMachIobConf(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyMachIobConf(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:IOB:{idxMacchina}:MachIobConf"; @@ -273,7 +270,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyMsmi(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyMsmi(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:hMSMI:{idxMacchina}"; @@ -285,7 +282,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyOptPar(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyOptPar(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:OptPar:{idxMacchina}"; @@ -297,7 +294,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyPzCount(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyPzCount(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:PzCount:{idxMacchina}"; @@ -309,7 +306,7 @@ namespace MP.Core /// /// /// - public static RedisKey RedKeySavedTask2ExeMacc(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeySavedTask2ExeMacc(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:SavedTask:{idxMacchina}"; @@ -321,7 +318,7 @@ namespace MP.Core /// /// Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy) /// - public static RedisKey RedKeyTask2ExeMacc(string idxMacchina, string baseAddr = null) + public static RedisKey RedKeyTask2ExeMacc(string idxMacchina, string? baseAddr = null) { var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':'); return (RedisKey)$"{prefix}:ExeTask:{idxMacchina}"; diff --git a/MP.Data/Controllers/MpIocController.cs b/MP.Data/Controllers/MpIocController.cs index 4c3cb3be..6502ccf6 100644 --- a/MP.Data/Controllers/MpIocController.cs +++ b/MP.Data/Controllers/MpIocController.cs @@ -15,15 +15,30 @@ namespace MP.Data.Controllers { public class MpIocController { + protected readonly IDbContextFactory _ctxFactory; + protected readonly IDbContextFactory _ctxFactoryFL; #region Public Constructors - public MpIocController(IConfiguration configuration) + public MpIocController( + IConfiguration configuration, + IDbContextFactory ctxFactory, + IDbContextFactory ctxFactoryFL) { - _configuration = configuration; - string connStr = _configuration.GetConnectionString("MP.Data"); +#if false + _configuration = configuration; +#endif + _ctxFactory = ctxFactory; + _ctxFactoryFL = ctxFactoryFL; +#if false + string connStr = configuration.GetConnectionString("MP.Data"); options = new DbContextOptionsBuilder() .UseSqlServer(connStr) + .Options; + string connStrFlux = configuration.GetConnectionString("MP.Flux"); + optionsFlux = new DbContextOptionsBuilder() + .UseSqlServer(connStrFlux) .Options; +#endif Log.Info("Avviata classe MpIocController"); } @@ -43,7 +58,7 @@ namespace MP.Data.Controllers /// public async Task AlarmLogInsertAsync(DateTime dtRif, string machineId, string memAddress, int memIndex, int statusVal, string valDecoded) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var DtRif = new SqlParameter("@DtRif", dtRif); var MachineId = new SqlParameter("@MachineId", machineId); @@ -63,7 +78,7 @@ namespace MP.Data.Controllers /// public async Task> AnagStatiGetAllAsync() { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetAnagStati @@ -81,7 +96,7 @@ namespace MP.Data.Controllers /// public async Task> ArticoliGetLastByMaccAsync(string idxMacc) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var dbResult = await dbCtx @@ -107,7 +122,7 @@ namespace MP.Data.Controllers /// public async Task AutoStartOdlAsync(int idxOdl, int MatrOpr, string idxMacchina, decimal tCRich, int pzPallet, string note, bool startNewOdl, int qtyRich, string keyRich) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxOdl = new SqlParameter("@idxOdl ", idxOdl); var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); @@ -138,7 +153,7 @@ namespace MP.Data.Controllers /// public async Task CheckCambiaStatoBatchAsync(tipoInputEvento tipoInput, string IdxMacchina, DateTime InizioStato, int IdxTipo, string CodArt, string Value, int MatrOpr, string pallet) { - await using var dbCtx = new MoonProContext(options); + await using var dbCtx = _ctxFactory.CreateDbContext(); //await using var tx = await dbCtx.Database.BeginTransactionAsync(); try @@ -224,7 +239,7 @@ namespace MP.Data.Controllers /// public async Task ConfermaProdMacchinaAsync(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzScarto, DateTime DataOraApp, int MatrOpr) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataOra = new SqlParameter("@DataOra ", DateTime.Now); @@ -267,7 +282,7 @@ namespace MP.Data.Controllers /// public async Task ConfermaProdMacchinaFullAsync(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzLasciati, int numPzScarto, DateTime DataOraApp, int MatrOpr) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataOra = new SqlParameter("@DataOra ", DateTime.Now); @@ -306,7 +321,7 @@ namespace MP.Data.Controllers /// public async Task> ConfFluxFiltAsync(string idxMacc) { - using var dbCtx = new MoonPro_FluxContext(_configuration); + using var dbCtx = _ctxFactoryFL.CreateDbContext(); var query = dbCtx.DbSetConfFlux .AsNoTracking() @@ -326,7 +341,7 @@ namespace MP.Data.Controllers /// public async Task> ConfigGetAllAsync() { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetConfig @@ -343,17 +358,17 @@ namespace MP.Data.Controllers /// public async Task ConfigUpdateAsync(ConfigModel updRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); bool fatto = false; - var dbResult = dbCtx - .DbSetConfig - .Where(x => x.Chiave == updRec.Chiave) - .FirstOrDefault(); + var dbResult = await dbCtx + .DbSetConfig + .Where(x => x.Chiave == updRec.Chiave) + .FirstOrDefaultAsync(); if (dbResult != null) { dbResult.Valore = updRec.Valore; - fatto = dbCtx.SaveChanges() > 0; + fatto = await dbCtx.SaveChangesAsync() > 0; } return fatto; @@ -365,7 +380,7 @@ namespace MP.Data.Controllers /// public async Task> DatiMacchineGetAllAsync() { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetDatiMacchine @@ -388,7 +403,7 @@ namespace MP.Data.Controllers /// public async Task DDB_InsStatoBatchAsync(string idxMacchina, DateTime inizioStato, int idxStato, string codArt, string value, int matrOpr, string pallet) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var InizioStato = new SqlParameter("@InizioStato", inizioStato); @@ -411,7 +426,7 @@ namespace MP.Data.Controllers /// public async Task> DecNumArtGetFiltAsync(string codArt = "") { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var query = dbCtx.DbSetDecNumArt .AsNoTracking() @@ -432,17 +447,13 @@ namespace MP.Data.Controllers /// public async Task> DossGetLastByMaccAsync(string idxMacc) { - List dbResult = new(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); - dbResult = await dbCtx - .DbSetDossiers - .FromSqlRaw("exec dbo.stp_DOSS_getLastByMacch @idxMacchina", IdxMacchina) - .AsNoTracking() - .ToListAsync(); - } - return dbResult; + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); + return await dbCtx + .DbSetDossiers + .FromSqlRaw("exec dbo.stp_DOSS_getLastByMacch @idxMacchina", IdxMacchina) + .AsNoTracking() + .ToListAsync(); } /// @@ -452,7 +463,7 @@ namespace MP.Data.Controllers /// public async Task EvListInsertAsync(EventListModel newRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); dbCtx.DbSetEvList.Add(newRec); return await dbCtx.SaveChangesAsync() > 0; @@ -467,7 +478,7 @@ namespace MP.Data.Controllers public async Task EvListMicroStatoInsertAsync(MicroStatoMacchinaModel newRecMsm, EventListModel newRecEv) { // eseguo in transazione... - await using var dbCtx = new MoonProContext(options); + await using var dbCtx = _ctxFactory.CreateDbContext(); await using var tx = await dbCtx.Database.BeginTransactionAsync(); try @@ -518,18 +529,15 @@ namespace MP.Data.Controllers /// public async Task> FluxLogFirstByMaccAsync(string idxMacc, int numMax) { - List dbResult = new(); - - using var dbCtx = new MoonPro_FluxContext(_configuration); + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var NumMax = new SqlParameter("@numMax", numMax); - dbResult = await dbCtx - .DbSetFluxLog - .FromSqlRaw("exec dbo.stp_FL_getFirstByMacc @IdxMacchina, @numMax", IdxMacchina, NumMax) - .AsNoTracking() - .ToListAsync(); - return dbResult; + return await dbCtx + .DbSetFluxLog + .FromSqlRaw("exec dbo.stp_FL_getFirstByMacc @IdxMacchina, @numMax", IdxMacchina, NumMax) + .AsNoTracking() + .ToListAsync(); } /// @@ -543,17 +551,15 @@ namespace MP.Data.Controllers /// public async Task> FluxLogGetLastFiltAsync(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec) { - List dbResult = new List(); - using var dbCtx = new MoonPro_FluxContext(_configuration); + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); - dbResult = await dbCtx - .DbSetFluxLog - .AsNoTracking() - .Where(x => (x.dtEvento >= DtMin && x.dtEvento <= DtMax) && (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodFlux == "*" || x.CodFlux == CodFlux)) - .OrderByDescending(x => x.dtEvento) - .Take(MaxRec) - .ToListAsync(); - return dbResult; + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => (x.dtEvento >= DtMin && x.dtEvento <= DtMax) && (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodFlux == "*" || x.CodFlux == CodFlux)) + .OrderByDescending(x => x.dtEvento) + .Take(MaxRec) + .ToListAsync(); } /// @@ -563,15 +569,13 @@ namespace MP.Data.Controllers /// public async Task FluxLogInsertAsync(FluxLogModel newRec) { - bool fatto = false; - using var dbCtx = new MoonPro_FluxContext(_configuration); + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); var currRec = dbCtx - .DbSetFluxLog - .Add(newRec); - await dbCtx.SaveChangesAsync(); + .DbSetFluxLog + .Add(newRec); + return await dbCtx.SaveChangesAsync()>0; - return fatto; } /// @@ -581,8 +585,7 @@ namespace MP.Data.Controllers /// public async Task FluxLogTakeSnapshotLastAsync(string idxMacc, DateTime dataInizio, DateTime dataFine) { - bool fatto = false; - using var dbCtx = new MoonPro_FluxContext(_configuration); + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var DataInizio = new SqlParameter("@DtMin", dataInizio); @@ -591,8 +594,7 @@ namespace MP.Data.Controllers var result = await dbCtx .Database .ExecuteSqlRawAsync("EXEC stp_FL_TakeSnapshotLast @IdxMacchina, @DtMin, @DtMax", IdxMacchina, DataInizio, DataFine); - fatto = result > 0; - return fatto; + return result > 0; } /// @@ -605,7 +607,7 @@ namespace MP.Data.Controllers public async Task KeepAliveUpsertAsync(string IdxMacc, DateTime OraServer, DateTime OraMacc) { bool fatto = false; - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var currRec = await dbCtx .DbSetKeepAlive @@ -638,7 +640,7 @@ namespace MP.Data.Controllers public async Task> ListLinkFiltAsync(string tipoLink) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); dbResult = await dbCtx .DbSetLinkMenu @@ -658,7 +660,7 @@ namespace MP.Data.Controllers public async Task> ListValuesFiltAsync(string tabName, string fieldName) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var query = dbCtx .DbSetListValues @@ -682,7 +684,7 @@ namespace MP.Data.Controllers public async Task> Macchine2SlaveAsync() { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); dbResult = await dbCtx .DbSetM2S @@ -700,7 +702,7 @@ namespace MP.Data.Controllers public async Task> MacchineGetAllAsync() { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); dbResult = await dbCtx .DbSetMacchine @@ -712,7 +714,7 @@ namespace MP.Data.Controllers public async Task MacchineGetByIdxAsync(string IdxMacchina) { MacchineModel dbResult = null; - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); dbResult = await dbCtx .DbSetMacchine @@ -729,7 +731,7 @@ namespace MP.Data.Controllers public async Task> MacchineGetFiltAsync(string codGruppo) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); if (codGruppo == "*") { @@ -763,7 +765,7 @@ namespace MP.Data.Controllers /// public async Task MacchineUpsertAsync(MacchineModel entity) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); // Recuperiamo l'entità tracciata dal context var trackedEntity = await dbCtx @@ -791,7 +793,7 @@ namespace MP.Data.Controllers public async Task> MicroStatoMacchinaGetByIdxMaccAsync(string IdxMacc) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); dbResult = await dbCtx .DbSetMicroStatoMacc @@ -809,7 +811,7 @@ namespace MP.Data.Controllers public async Task MicroStatoMacchinaUpsertAsync(MicroStatoMacchinaModel newRec) { bool fatto = false; - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var actRec = await dbCtx .DbSetMicroStatoMacc @@ -842,7 +844,7 @@ namespace MP.Data.Controllers public async Task> MseGetAllAsync(int maxAge = 2000) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); @@ -862,7 +864,7 @@ namespace MP.Data.Controllers /// public async Task OdlAutoDayGenAsync(string idxMacchina, DateTime dataInizio, DateTime dataFine, string codArticolo) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataInizio = new SqlParameter("@DataInizio", dataInizio); @@ -884,7 +886,7 @@ namespace MP.Data.Controllers /// public async Task OdlAutoDayGenFullAsync(string idxMacchina, DateTime dataInizio, DateTime dataFine, string codArticolo, int? pzPODL, int? pzPallet, string? keyRichiesta, int? tcAssegnato, string? codGruppo, bool flgCreaPODL, bool flgCheckTC) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataInizio = new SqlParameter("@DataInizio", dataInizio); @@ -913,7 +915,7 @@ namespace MP.Data.Controllers public async Task OdlCurrByMaccAsync(string idxMacchina) { ODLExpModel answ = new(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); // attenzione: se la stored resituisce una tabella, il primo elemento va recuperato in RAM!!! @@ -936,7 +938,7 @@ namespace MP.Data.Controllers /// public async Task OdlFixMachineSlave(string idxMacchina, int numDayPrev, int doInsert) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var idxMaccParam = new SqlParameter("@IdxMacchina", idxMacchina ?? ""); var numDayPrevParam = new SqlParameter("@NumDayPrev", numDayPrev); @@ -958,7 +960,7 @@ namespace MP.Data.Controllers /// public async Task OdlFixMachineSlaveAsync(string idxMacchina, int numDayPrev, int doInsert) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); var NumDayPrev = new SqlParameter("@NumDayPrev", numDayPrev); @@ -977,7 +979,7 @@ namespace MP.Data.Controllers public async Task OdlLastByMaccAsync(string idxMacchina) { ODLExpModel answ = new(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); // attenzione: se la stored resituisce una tabella, il primo elemento va recuperato in RAM!!! @@ -1001,7 +1003,7 @@ namespace MP.Data.Controllers public async Task> OdlListByMaccPeriodoAsync(string idxMacchina, DateTime dtStart, DateTime dtEnd) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataFrom = new SqlParameter("@dataFrom", dtStart); @@ -1023,7 +1025,7 @@ namespace MP.Data.Controllers public async Task PezziProdMacchinaAsync(string idxMacchina) { PzProdModel dbResult = new PzProdModel(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); dbResult = (await dbCtx @@ -1046,7 +1048,7 @@ namespace MP.Data.Controllers public async Task> POdlGetByMaccArtAsync(string idxMacchina, string codArticolo, string codGruppo, bool onlyFree) { List dbResult = new List(); - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var pCodArticolo = new SqlParameter("@CodArticolo", codArticolo); @@ -1069,7 +1071,7 @@ namespace MP.Data.Controllers /// public async Task RecalcMseAsync(string idxMacchina, int maxAgeSec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); var MaxAgeSec = new SqlParameter("@maxAgeSec ", maxAgeSec); @@ -1093,7 +1095,7 @@ namespace MP.Data.Controllers /// public async Task RegControlliInsertAsync(string idxMacchina, int matrOpr, bool esitoOk, string note, DateTime dataOra) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); var MatrOpr = new SqlParameter("@MatrOpr", matrOpr); @@ -1114,7 +1116,7 @@ namespace MP.Data.Controllers /// public async Task RegDichiarInsertAsync(RegistroDichiarazioniModel newRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var TagCode = new SqlParameter("@TagCode", newRec.TagCode); var IdxMacchina = new SqlParameter("@IdxMacchina", newRec.IdxMacchina); @@ -1136,7 +1138,7 @@ namespace MP.Data.Controllers /// public async Task RegDichiarUpdateAsync(RegistroDichiarazioniModel newRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var Original_IdxDich = new SqlParameter("@Original_IdxDich", newRec.IdxDich); var DtRec = new SqlParameter("@DtRec", newRec.DtRec); @@ -1157,7 +1159,7 @@ namespace MP.Data.Controllers /// public async Task RegScartiInsertAsync(RegistroScartiModel newRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@idxMacchina", newRec.IdxMacchina); var DataOra = new SqlParameter("@DataOra", newRec.DataOra); @@ -1184,7 +1186,7 @@ namespace MP.Data.Controllers public async Task RemRebootLogAddAndCleanAsync(RemoteRebootLogModel newRec, bool doClean, int num2keep) { bool fatto = false; - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); // 1. Transazione minima: SOLO INSERT + COMMIT await using var tx = await dbCtx.Database.BeginTransactionAsync(); @@ -1227,7 +1229,7 @@ namespace MP.Data.Controllers /// public async Task RemRebootLogAddAsync(RemoteRebootLogModel newRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = dbCtx .DbSetRemRebLog @@ -1242,7 +1244,7 @@ namespace MP.Data.Controllers /// public async Task> RemRebootLogGetAllAsync() { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetRemRebLog @@ -1258,7 +1260,7 @@ namespace MP.Data.Controllers /// public async Task> RemRebootLogGetLastAsync() { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetRemRebLog .FromSqlRaw("EXEC stp_RRL_getLast") @@ -1273,7 +1275,7 @@ namespace MP.Data.Controllers /// public async Task RemRebootLogKeepLastAsync(int num2keep) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var pNum2Keep = new SqlParameter("@num2keep", num2keep); // La SP gestisce già la logica di soglia (1.5x), ma la specifico x sicurezza @@ -1291,7 +1293,7 @@ namespace MP.Data.Controllers /// public async Task SignalLogInsertAsync(SignalLogModel newRec) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var currRec = dbCtx .DbSetSignalLog @@ -1307,7 +1309,7 @@ namespace MP.Data.Controllers /// public async Task> SMES_getHwTransitionsAsync(string idxMacchina, int idxTipo) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var IdxTipo = new SqlParameter("@IdxTipo", idxTipo); @@ -1327,7 +1329,7 @@ namespace MP.Data.Controllers /// public async Task> SMES_getUserForcedAsync(string idxMacchina, int idxTipo) { - await using var dbCtx = new MoonProContext(options); + await using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var IdxTipo = new SqlParameter("@IdxTipo", idxTipo); @@ -1346,18 +1348,14 @@ namespace MP.Data.Controllers /// public List StateMachineIngressi(int idxFam) { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var IdxFamIn = new SqlParameter("@IdxFamigliaIngresso", idxFam); - dbResult = dbCtx - .DbSetSMI - .FromSqlRaw("exec dbo.stp_TRI_getByIdxFamIng @IdxFamigliaIngresso", IdxFamIn) - .AsNoTracking() - .AsEnumerable() - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + var IdxFamIn = new SqlParameter("@IdxFamigliaIngresso", idxFam); + return dbCtx + .DbSetSMI + .FromSqlRaw("exec dbo.stp_TRI_getByIdxFamIng @IdxFamigliaIngresso", IdxFamIn) + .AsNoTracking() + .AsEnumerable() + .ToList(); } /// @@ -1366,7 +1364,7 @@ namespace MP.Data.Controllers /// public async Task> StateMachineIngressiAsync(int idxFam) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxFamIn = new SqlParameter("@IdxFamigliaIngresso", idxFam); var dbResult = await dbCtx @@ -1386,7 +1384,7 @@ namespace MP.Data.Controllers /// public async Task StatoProdMacchinaAsync(string idxMacchina, DateTime dtReq) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); var DataOra = new SqlParameter("@DataOra ", dtReq); @@ -1406,7 +1404,7 @@ namespace MP.Data.Controllers /// public async Task> VMSFDGetAllAsync() { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var dbResult = await dbCtx .DbSetMSFD @@ -1424,7 +1422,7 @@ namespace MP.Data.Controllers /// public async Task VMSFDGetByMaccAsync(string idxMacc) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); var dbResult = (await dbCtx @@ -1444,7 +1442,7 @@ namespace MP.Data.Controllers /// public async Task> VMSFDGetMultiByMaccAsync(string idxMacc) { - using var dbCtx = new MoonProContext(options); + using var dbCtx = _ctxFactory.CreateDbContext(); var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc); @@ -1461,9 +1459,14 @@ namespace MP.Data.Controllers #region Private Fields - private static IConfiguration _configuration; +#if false + private static IConfiguration _configuration; +#endif private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - private DbContextOptions options; +#if false + private DbContextOptions options; +#endif + private DbContextOptions optionsFlux; #endregion Private Fields diff --git a/MP.Data/Controllers/MpLandController.cs b/MP.Data/Controllers/MpLandController.cs index 9a77ad18..8ab7d25e 100644 --- a/MP.Data/Controllers/MpLandController.cs +++ b/MP.Data/Controllers/MpLandController.cs @@ -15,18 +15,30 @@ namespace MP.Data.Controllers public class MpLandController : IDisposable { #region Public Constructors + protected readonly IDbContextFactory _ctxFactory; + protected readonly IDbContextFactory _ctxFactoryFL; + protected readonly IDbContextFactory _ctxFactorySta; - public MpLandController(IConfiguration configuration) + public MpLandController( + IConfiguration configuration, + IDbContextFactory ctxFactory, + IDbContextFactory ctxFactoryFL, + IDbContextFactory ctxFactorySta) { _configuration = configuration; + _ctxFactory = ctxFactory; + _ctxFactoryFL = ctxFactoryFL; + _ctxFactorySta = ctxFactorySta; +#if false string connStr = _configuration.GetConnectionString("MP.Land"); - if(string.IsNullOrEmpty(connStr)) + if (string.IsNullOrEmpty(connStr)) { connStr = _configuration.GetConnectionString("MP.Data"); } options = new DbContextOptionsBuilder() .UseSqlServer(connStr) - .Options; + .Options; +#endif Log.Info("Avviato MpLandController"); } @@ -34,6 +46,7 @@ namespace MP.Data.Controllers #region Public Methods +#if false /// /// Restituisce info dimensione, tabelle e num righe DB gestiti /// @@ -70,58 +83,53 @@ namespace MP.Data.Controllers // leggo per DB principale if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.All"))) { - using (var dbCtx = new MoonProContext(options)) + using var dbCtx = _ctxFactory.CreateDbContext(); + var singleRes = dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsEnumerable() + .FirstOrDefault(); + if (singleRes != null) { - var singleRes = dbCtx - .DbSetDbSize - .FromSqlRaw(stp_DbInfo) - .AsEnumerable() - .FirstOrDefault(); - if (singleRes != null) - { - dbResult.Add(singleRes); - } + dbResult.Add(singleRes); } } // leggo per FluxLog if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.Flux"))) { - using (var dbCtx = new MoonPro_FluxContext(_configuration)) + using var dbCtx = _ctxFactoryFL.CreateDbContext(); + var singleRes = dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsEnumerable() + .FirstOrDefault(); + if (singleRes != null) { - var singleRes = dbCtx - .DbSetDbSize - .FromSqlRaw(stp_DbInfo) - .AsEnumerable() - .FirstOrDefault(); - if (singleRes != null) - { - dbResult.Add(singleRes); - } + dbResult.Add(singleRes); } } // leggo per Stats if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.Stats"))) { - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using var dbCtx = _ctxFactorySta.CreateDbContext(); + var singleRes = dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsEnumerable() + .FirstOrDefault(); + if (singleRes != null) { - var singleRes = dbCtx - .DbSetDbSize - .FromSqlRaw(stp_DbInfo) - .AsEnumerable() - .FirstOrDefault(); - if (singleRes != null) - { - dbResult.Add(singleRes); - } + dbResult.Add(singleRes); } } } catch (Exception exc) { - Log.Error($"Eccezione in AllDbInfo:{Environment.NewLine}{exc}"); + Log.Error($"Eccezione in AllDbInfoAsync:{Environment.NewLine}{exc}"); } return dbResult; - } + } +#endif /// /// Elenco da tabella Config @@ -130,20 +138,18 @@ namespace MP.Data.Controllers public List ConfigGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetConfig - .AsNoTracking() - .OrderBy(x => x.Chiave) - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + return dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToList(); } public void Dispose() { - _configuration = null; + Dispose(true); + GC.SuppressFinalize(this); } /// @@ -153,16 +159,13 @@ namespace MP.Data.Controllers public List ElencoOperatori() { List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbOperatori - .Where(s => s.MatrOpr > 0) - .AsNoTracking() - .OrderBy(x => x.MatrOpr) - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + return dbCtx + .DbOperatori + .Where(s => s.MatrOpr > 0) + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToList(); } /// @@ -172,13 +175,10 @@ namespace MP.Data.Controllers public List MacchineGetAll() { List dbResult = new List(); - using (MoonProContext localDbCtx = new MoonProContext(options)) - { - dbResult = localDbCtx - .DbSetMacchine - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + return dbCtx + .DbSetMacchine + .ToList(); } /// @@ -188,15 +188,12 @@ namespace MP.Data.Controllers public List RemRebootLogGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetRemRebLog - .AsNoTracking() - .OrderByDescending(x => x.IdxReboot) - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + return dbCtx + .DbSetRemRebLog + .AsNoTracking() + .OrderByDescending(x => x.IdxReboot) + .ToList(); } /// @@ -206,15 +203,12 @@ namespace MP.Data.Controllers public List RemRebootLogGetLast() { List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetRemRebLog - .FromSqlRaw("EXEC stp_RRL_getLast") - .AsNoTracking() - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + return dbCtx + .DbSetRemRebLog + .FromSqlRaw("EXEC stp_RRL_getLast") + .AsNoTracking() + .ToList(); } /// @@ -224,15 +218,12 @@ namespace MP.Data.Controllers public List RemRebootLogGetLastNoMacc() { List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetRemRebLog - .FromSqlRaw("EXEC stp_RRL_GetLastNoMachine") - .AsNoTracking() - .ToList(); - } - return dbResult; + using var dbCtx = _ctxFactory.CreateDbContext(); + return dbCtx + .DbSetRemRebLog + .FromSqlRaw("EXEC stp_RRL_GetLastNoMachine") + .AsNoTracking() + .ToList(); } /// @@ -243,7 +234,7 @@ namespace MP.Data.Controllers public bool RollBackEntity(object item) { bool answ = false; - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using var dbCtx = _ctxFactory.CreateDbContext(); { try { @@ -262,11 +253,30 @@ namespace MP.Data.Controllers #endregion Public Methods + #region Protected Methods + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + // Free managed resources here + } + _disposed = true; + } + } + + #endregion Protected Methods + #region Private Fields - private static IConfiguration _configuration; private static Logger Log = LogManager.GetCurrentClassLogger(); - private DbContextOptions options; + private readonly IConfiguration _configuration; +#if false + private readonly DbContextOptions options; +#endif + private bool _disposed = false; #endregion Private Fields } diff --git a/MP.Data/Controllers/MpSpecController.cs b/MP.Data/Controllers/MpSpecController.cs deleted file mode 100644 index efa33086..00000000 --- a/MP.Data/Controllers/MpSpecController.cs +++ /dev/null @@ -1,2549 +0,0 @@ -using Microsoft.Data.SqlClient; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using MP.Core.DTO; -using MP.Core.Objects; -using MP.Data.DbModels; -using NLog; -using System; -using System.Collections.Generic; -using System.Data; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using static EgwCoreLib.Utils.DtUtils; - -namespace MP.Data.Controllers -{ - public class MpSpecController : IDisposable - { - #region Public Constructors - - public MpSpecController(IConfiguration configuration) - { - _configuration = configuration; - string connStr = _configuration.GetConnectionString("MP.Data"); - options = new DbContextOptionsBuilder() - .UseSqlServer(connStr) - .Options; - Log.Info("Avviata classe MpSpecController"); - } - - #endregion Public Constructors - - #region Public Methods - - /// - /// Elenco di tutti i counter coi valori correnti - /// - /// - public List AnagCounters() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetAnagCount - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Stacca un nuovo counter x il tipo richiesto - /// - /// - public AnagCountersModel AnagCountersGetNext(string cntType) - { - AnagCountersModel answ = new AnagCountersModel(); - bool outTable = true; - if (outTable) - { - using (var dbCtx = new MoonProContext(options)) - { - var pCntType = new SqlParameter("@CntType", cntType); - var pLastNum = new SqlParameter - { - ParameterName = "@LastNum", - SqlDbType = SqlDbType.Int, - Direction = ParameterDirection.Output - }; - - var dbResult = dbCtx - .DbSetAnagCount - .FromSqlRaw("EXEC dbo.stp_getNextNumb @CntType, @LastNum OUTPUT", pCntType, pLastNum) - .AsNoTracking() - .AsEnumerable() - .FirstOrDefault(); - if (dbResult != null) - { - answ = dbResult; - } - } - } - else - { - // se si volessero impiegare parametri OUTPUT (qui ne mancherebbe 1 nella stored x CntCode...) - using (var dbCtx = new MoonProContext(options)) - { - var pCntType = new SqlParameter("@CntType", cntType); - var pLastNum = new SqlParameter - { - ParameterName = "@LastNum", - SqlDbType = SqlDbType.Int, - Direction = ParameterDirection.Output - }; - var pCntCode = new SqlParameter - { - ParameterName = "@CntCode", - SqlDbType = SqlDbType.NVarChar, - Direction = ParameterDirection.Output - }; - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC dbo.stp_getNextNumb @CntType, @LastNum OUTPUT, @CntCode OUTPUT", pCntType, pLastNum, pCntCode); - if (dbResult != 0) - { - answ.CntType = cntType; - answ.CntCode = $"{pCntCode.Value}"; - int lNum = 0; - int.TryParse($"{pLastNum.Value}", out lNum); - answ.LastNum = lNum; - } - } - } - return answ; - } - - /// - /// Restituisce l'anagrafica EVENTI generalmente disponibile per OGNI macchina - /// - /// Nome Table x filtro (std: EvList) - /// Nome Field x filtro (std: Common) - /// - public List AnagEventiGeneral(string TableName = "EvList", string FieldName = "Common") - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var pTableName = new SqlParameter("@TableName", TableName); - var pFieldName = new SqlParameter("@FieldName", FieldName); - dbResult = dbCtx - .DbSetVSEB - .FromSqlRaw("exec dbo.stp_vseb_getGenerallyAvailable @TableName, @FieldName", pTableName, pFieldName) - .AsNoTracking() - .AsEnumerable() - .ToList(); - } - return dbResult; - } - - /// - /// Restituisce l'anagrafica EVENTI per macchina - /// - /// - public List AnagEventiGetByMacc(string IdxMac) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var IdxMacch = new SqlParameter("@idxMacchina", IdxMac); - - dbResult = dbCtx - .DbSetVSEB - .FromSqlRaw("exec dbo.stp_vseb_getByIdxMacchinaFull @idxMacchina", IdxMacch) - .AsNoTracking() - .AsEnumerable() - .ToList(); - } - return dbResult; - } - - /// - /// Elenco Gruppi tipo Azienda - /// - /// - public List AnagGruppiAziende() - { - return AnagGruppiGetTipo("AZIENDA"); - } - - /// - /// Delete record AnagraficaGruppi - /// - /// - public bool AnagGruppiDelete(AnagGruppiModel updRec) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var dbRec = dbCtx - .DbSetAnagGruppi - .AsNoTracking() - .Where(x => x.CodGruppo == updRec.CodGruppo) - .FirstOrDefault(); - // se trovato aggiorno descrizione (resto immutato x sicurezza!) - if (dbRec != null) - { - dbCtx.DbSetAnagGruppi.Remove(dbRec); - } - var numRes = dbCtx.SaveChanges(); - answ = numRes != 0; - } - return answ; - } - - /// - /// Elenco Gruppi tipo Fasi - /// - /// - public List AnagGruppiFase() - { - return AnagGruppiGetTipo("FASE"); - } - - /// - /// Elenco Gruppi - /// - /// - public List AnagGruppiGetAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetAnagGruppi - .AsNoTracking() - .OrderBy(x => x.CodGruppo) - .ToList(); - } - return dbResult; - } - - /// - /// Gruppi x tipo - /// - /// - /// - public List AnagGruppiGetTipo(string tipoGruppo) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetAnagGruppi - .Where(x => x.TipoGruppo == tipoGruppo) - .AsNoTracking() - .OrderBy(x => x.CodGruppo) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco Gruppi tipo REPARTO (x associazione Macchine-Operatori) - /// - /// - public List AnagGruppiReparto() - { - return AnagGruppiGetTipo("REPARTO"); - } - - /// - /// Elenco Gruppi tipo REPARTO (x associazione Macchine-Operatori) in formato DTO con conteggi del numero record trovati - /// - /// - public List AnagGruppiRepartoDTO() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - // in primis recupero i reparti... - var listReparti = AnagGruppiGetTipo("REPARTO"); - - // recupero TUTTE le macchine da DbSetGrp2Macc - var listMacc = dbCtx - .DbSetGrp2Macc - .AsNoTracking() - .ToList(); - // recupero TUTTI gli operatori da DbSetGrp2Oper - var listOpr = dbCtx - .DbSetGrp2Oper - .AsNoTracking() - .ToList(); - - dbResult = listReparti - .Select(x => new RepartiDTO() - { - CodGruppo = x.CodGruppo, - TipoGruppo = x.TipoGruppo, - DescrGruppo = x.DescrGruppo, - SelEnabled = x.SelEnabled, - CountMacc = listMacc.Where(y => y.CodGruppo == x.CodGruppo).Select(x => x.IdxMacchina).Distinct().Count(), - CountOpr = listOpr.Where(y => y.CodGruppo == x.CodGruppo).Select(x => x.MatrOpr).Distinct().Count() - }) - .ToList(); - } - return dbResult; - } - - /// - /// Upsert record AnagraficaGruppi (solo codice/descrizione) - /// - /// - /// - public bool AnagGruppiUpsert(AnagGruppiModel updRec) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var dbRec = dbCtx - .DbSetAnagGruppi - .AsNoTracking() - .Where(x => x.CodGruppo == updRec.CodGruppo) - .FirstOrDefault(); - // se trovato aggiorno descrizione (resto immutato x sicurezza!) - if (dbRec != null) - { - dbRec.DescrGruppo = updRec.DescrGruppo; - dbCtx.Entry(dbRec).State = EntityState.Modified; - } - // altrimenti aggiungo - else - { - dbCtx.DbSetAnagGruppi.Add(updRec); - } - var numRes = dbCtx.SaveChanges(); - answ = numRes != 0; - } - return answ; - } - - /// - /// Elenco Gruppi - /// - /// - public List AnagKeyValGetAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetAKV - .AsNoTracking() - .OrderBy(x => x.nomeVar) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco valori ammessi x Stati commessa (es Yacht Baglietto) - /// - /// - public List AnagStatiComm() - { - return ListValuesFilt("PODL", "StatoComm"); - } - - /// - /// Elenco valori ammessi x Tipo articoli - /// - /// - public List AnagTipoArtLV() - { - return ListValuesFilt("AnagArticoli", "Tipo"); - } - - /// - /// Elenco codice articoli che abbiano dati Dossier - /// - /// - public List ArticleWithDossier() - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = dbCtx - .DbSetDossiers - .AsNoTracking() - .Select(i => i.CodArticolo) - .Distinct() - .ToList(); - } - return dbResult; - } - - /// - /// Eliminazione Record - /// - /// - /// - public async Task ArticoliDeleteRecord(AnagArticoliModel currRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currVal = dbCtx - .DbSetArticoli - .Where(x => x.CodArticolo == currRec.CodArticolo) - .FirstOrDefault(); - dbCtx - .DbSetArticoli - .Remove(currVal); - await dbCtx.SaveChangesAsync(); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante ArticoliDeleteRecord{Environment.NewLine}{exc}"); - } - } - return fatto; - } - - /// - /// Restitusice elenco articoli dato tipo (es KIT) - /// - /// - /// - /// - /// - public List ArticoliGetByTipo(string tipo, string azienda = "*") - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetArticoli - .AsNoTracking() - .Where(x => x.Tipo.ToUpper() == tipo.ToUpper() && (azienda == "*" || x.Azienda.ToUpper() == azienda.ToUpper())) - .OrderBy(x => x.CodArticolo) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco tabella Articoli da filtro - /// - /// - /// - /// - public List ArticoliGetSearch(int numRecord, string searchVal = "") - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetArticoli - .AsNoTracking() - .Where(x => x.CodArticolo.Contains(searchVal) || x.DescArticolo.Contains(searchVal) || x.Disegno.Contains(searchVal) || string.IsNullOrEmpty(searchVal)) - .OrderBy(x => x.CodArticolo) - .Take(numRecord) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco tabella Articoli da filtro - /// - /// - /// - /// - /// - public List ArticoliGetSearch(int numRecord, string azienda = "*", string searchVal = "") - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetArticoli - .AsNoTracking() - .Where(x => (azienda == "*" || x.Azienda.ToUpper() == azienda.ToUpper()) && (string.IsNullOrEmpty(searchVal) || x.CodArticolo.Contains(searchVal) || x.DescArticolo.Contains(searchVal) || x.Disegno.Contains(searchVal))) - .OrderBy(x => x.CodArticolo) - .Take(numRecord) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco tabella Articoli IMPIEGATI (da stored stp_ART_getUsed) - /// - /// - public List ArticoliGetUsed() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetArticoli - .FromSqlRaw("EXEC stp_ART_getUsed") - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Update Record - /// - /// - /// - public async Task ArticoliUpdateRecord(AnagArticoliModel editRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currRec = dbCtx - .DbSetArticoli - .Where(x => x.CodArticolo == editRec.CodArticolo) - .FirstOrDefault(); - if (currRec != null) - { - currRec.Disegno = editRec.Disegno; - currRec.DescArticolo = editRec.DescArticolo; - currRec.Tipo = editRec.Tipo; - currRec.Azienda = editRec.Azienda; - dbCtx.Entry(currRec).State = EntityState.Modified; - } - else - { - dbCtx - .DbSetArticoli - .Add(editRec); - } - await dbCtx.SaveChangesAsync(); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante ArticoliUpdateRecord{Environment.NewLine}{exc}"); - } - } - return fatto; - } - - /// - /// Elenco da tabella Config - /// - /// - public List ConfigGetAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetConfig - .AsNoTracking() - .OrderBy(x => x.Chiave) - .ToList(); - } - return dbResult; - } - - /// - /// Update record config - /// - /// - public bool ConfigUpdate(ConfigModel updRec) - { - bool fatto = false; - ConfigModel dbResult = new ConfigModel(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetConfig - .Where(x => x.Chiave == updRec.Chiave) - .FirstOrDefault(); - if (dbResult != null) - { - dbResult.Valore = updRec.Valore; - dbCtx.SaveChanges(); - fatto = true; - } - } - return fatto; - } - - /// - /// Intera tab dati macchina - /// - /// - public List DatiMacchineGetAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetDatiMacchine - .AsNoTracking() - .OrderBy(x => x.IdxMacchina) - .ToList(); - } - return dbResult; - } - - public void Dispose() - { - _configuration = null; - } - - /// - /// Eliminazione di un dossier - /// - /// record dossier da eliminare - /// - public async Task DossiersDeleteRecord(DossierModel currRec) - { - bool answ = false; - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - try - { - var currVal = dbCtx - .DbSetDossiers - .Where(x => x.IdxDossier == currRec.IdxDossier) - .FirstOrDefault(); - dbCtx - .DbSetDossiers - .Remove(currVal); - await dbCtx.SaveChangesAsync(); - answ = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante DossiersDeleteRecord{Environment.NewLine}{exc}"); - } - } - return answ; - } - - /// - /// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato - /// macchina (ordinato x data registrazione) - /// - /// * = tutte, altrimenti solo x una data macchina - /// * = tutti, altrimenti solo x un dato articolo - /// Data minima per estrazione records - /// Data Massima per estrazione records - /// Num max record recuperati - /// - public async Task> DossiersGetLastFiltAsync(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = await dbCtx - .DbSetDossiers - .AsNoTracking() - .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodArticolo == "*" || x.CodArticolo == CodArticolo) && (x.DtRif >= DtStart && x.DtRif <= DtEnd)) - .Include(m => m.MachineNav) - .Include(a => a.ArticoloNav) - .OrderByDescending(x => x.DtRif) - .Take(MaxRec) - .ToListAsync(); - } - return dbResult; - } - - /// - /// insert di un record Dossier - /// - /// record dossier da modificare - /// - public async Task DossiersInsert(DossierModel newRec) - { - bool fatto = false; - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - try - { - dbCtx - .DbSetDossiers - .Add(newRec); - await dbCtx.SaveChangesAsync(); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante DossiersInsert{Environment.NewLine}{exc}"); - } - } - return fatto; - } - - /// - /// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache _redisConn - /// - /// macchina - /// Num massimo secondi per recuperare dati correnti - /// DataOra riferimento x cui prendere valori antecedenti - public bool DossiersTakeParamsSnapshot(string idxMacchina, int maxSec, DateTime dtRif) - { - bool answ = false; - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); - var pMaxSec = new SqlParameter("@MaxSec", maxSec); - var pDtRif = new SqlParameter("@DtRif", dtRif); - - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC stp_FL_TakeSnapshot @IdxMacchina,@MaxSec,@DtRif", pIdxMacchina, pMaxSec, pDtRif); - answ = true; - } - return answ; - } - - /// - /// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache _redisConn - /// - /// macchina - /// Data min x selezione - /// Data MAX x selezione - public bool DossiersTakeParamsSnapshotLast(string idxMacchina, DateTime dtMin, DateTime dtMax) - { - bool answ = false; - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); - var pDtMin = new SqlParameter("@DtMin", dtMin); - var pDtMax = new SqlParameter("@DtMax", dtMax); - - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC stp_FL_TakeSnapshotLast @IdxMacchina,@DtMin,@DtMax", pIdxMacchina, pDtMin, pDtMax); - answ = true; - } - return answ; - } - - /// - /// Update del campo VALORE di un dossier (che contiene json flux log serializzati) - /// - /// record dossier da modificare - /// - public async Task DossiersUpdateValore(DossierModel editRec) - { - bool fatto = false; - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - try - { - var currRec = dbCtx - .DbSetDossiers - .Where(x => x.IdxDossier == editRec.IdxDossier) - .FirstOrDefault(); - if (currRec != null) - { - currRec.Valore = editRec.Valore; - dbCtx.Entry(currRec).State = EntityState.Modified; - } - else - { - dbCtx - .DbSetDossiers - .Add(editRec); - } - await dbCtx.SaveChangesAsync(); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante DossiersUpdateRecord{Environment.NewLine}{exc}"); - } - } - return fatto; - } - - /// - /// Elenco valori link (x home e navMenu laterale) - /// - /// - public List ElencoLink() - { - return ListLinkFilt("SpecLink"); - } - - /// - /// Elenco operatori - /// - /// - public List ElencoOperatori() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbOperatori - .Where(s => s.MatrOpr > 0) - .AsNoTracking() - .OrderBy(x => x.MatrOpr) - .ToList(); - } - return dbResult; - } - - /// - /// Aggiunta record EventList - /// - /// - /// - public async Task EvListInsert(EventListModel newRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currRec = dbCtx - .DbSetEvList - .Add(newRec); - await dbCtx.SaveChangesAsync(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante EvListInsert{Environment.NewLine}{exc}"); - } - } - await Task.Delay(1); - return fatto; - } - - /// - /// Funzione di Data Reduction x FluxLog - /// - /// - /// - /// - /// - /// - /// - /// Restitusice list dei record statistiche raccolti (da integrare a quelli rpesenti in Redis...) - /// - public async Task> FluxLogDataRedux(string idxMaccSel, List fluxList, Periodo currPeriodo, Enums.ValSelection valMode, Enums.DataInterval intReq, int maxItem) - { - List procStats = new List(); - Log.Info($"Inizio FluxLogDataRedux | idxMaccSel: {idxMaccSel} | periodo: {currPeriodo.Inizio:yyyy-MM-dd} --> {currPeriodo.Fine:yyyy-MM-dd}"); - TimeSpan step = TimeSpan.FromHours(1); - switch (intReq) - { - case Enums.DataInterval.minute: - step = TimeSpan.FromMinutes(1.00 / maxItem); - break; - - case Enums.DataInterval.hour: - step = TimeSpan.FromHours(1.00 / maxItem); - break; - - case Enums.DataInterval.day: - step = TimeSpan.FromDays(1.00 / maxItem); - break; - - default: - break; - } - - // setup parametri costanti x stored - var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMaccSel); - var pOnlyTest = new SqlParameter("@OnlyTest", false); - - // processo 1:1 ogni flusso - foreach (var item in fluxList) - { - Log.Info($"FluxLogDataRedux | Flux: {item}"); - int numRecProc = 0; - Stopwatch sw = new Stopwatch(); - sw.Start(); - // parametri x flusso - var pCodFlux = new SqlParameter("@CodFlux", item); - // inizializzo cursore timer - DateTime dtCursStart = currPeriodo.Inizio; - DateTime dtCursEnd = dtCursStart.Add(step); - bool setCompleted = false; - // dbContext x ogni singolo flusso - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - // opzionalmente timeout comandi a 2 minuti... NON usato x ora e da testare - //dbCtx.Database.SetCommandTimeout(TimeSpan.FromMinutes(2)); - // li processo per intervallo richiesto, cercando dati nel periodo e - // selezionando VC - while (!setCompleted) - { - // ora recupero TUTTI i dati della macchina - var currFlux = await dbCtx - .DbSetFluxLog - .Where(x => (x.CodFlux == item) && (x.dtEvento >= dtCursStart && x.dtEvento < dtCursEnd) && (x.IdxMacchina == idxMaccSel)) - .ToListAsync(); - - int numRec = currFlux.Count; - numRecProc += numRec; - if (numRec > maxItem) - { - List listPeriodi = new List(); - - switch (valMode) - { - case Enums.ValSelection.First: - // recupero 2° item - var recStart = currFlux.Skip(1).FirstOrDefault(); - // salvo periodo! - listPeriodi.Add(new Periodo(recStart.dtEvento, dtCursEnd)); - break; - - case Enums.ValSelection.Last: - // recupero ultimo item - var recEnd = currFlux.LastOrDefault(); - // salvo periodo! - listPeriodi.Add(new Periodo(dtCursStart, recEnd.dtEvento)); - break; - - case Enums.ValSelection.Center: - int idx = 1; - // per iniziare mi metto a 1/(n+1) rec come step - var recCent = currFlux.Skip(idx / (maxItem + 1)).FirstOrDefault(); - listPeriodi.Add(new Periodo(dtCursStart, recCent.dtEvento)); - // salvo restanti periodi (se > 1)! - if (maxItem > 1) - { - for (int i = 2; i < maxItem; i++) - { - DateTime dtInizio = recCent.dtEvento; - recCent = currFlux.Skip(i / (maxItem + 1)).FirstOrDefault(); - listPeriodi.Add(new Periodo(dtInizio, recCent.dtEvento)); - } - } - // aggiungo ultimo... - listPeriodi.Add(new Periodo(recCent.dtEvento.AddSeconds(1), dtCursEnd)); - break; - - default: - break; - } - - // ciclo x tutti i periodi e chiamo stored... - foreach (var slot in listPeriodi) - { - // parametri x periodo (base) - var pDtStart = new SqlParameter("@DtStart", slot.Inizio); - var pDtEnd = new SqlParameter("@DtEnd", slot.Fine); - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC man.stp_ReduceFluxLog @IdxMacchina, @CodFlux, @DtStart, @DtEnd, @OnlyTest", pIdxMacchina, pCodFlux, pDtStart, pDtEnd, pOnlyTest); - } - } - - // incremento dt fine periodo - dtCursStart = dtCursEnd; - dtCursEnd = dtCursStart.Add(step); - setCompleted = dtCursStart >= currPeriodo.Fine; - } - } - // fermo cronometro e salvo su DB... - sw.Stop(); - StatDedupDTO currStat = new StatDedupDTO() - { - IdxMacchina = idxMaccSel, - CodFlux = item, - Interval = intReq, - Num4Int = maxItem, - NumRec = numRecProc, - ProcTime = sw.Elapsed.TotalSeconds - }; - procStats.Add(currStat); - } - Log.Info($"FINE FluxLogDataRedux | idxMaccSel: {idxMaccSel} | periodo: {currPeriodo.Inizio:yyyy-MM-dd} --> {currPeriodo.Fine:yyyy-MM-dd}"); - return procStats; - } - - /// - /// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione) - /// - /// Data massima x eventi - /// Data minima x eventi - /// * = tutte, altrimenti solo x una data macchina - /// *=tutti, altrimenti solo selezionato - /// numero massimo record da restituire - /// - public List FluxLogGetLastFilt(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = dbCtx - .DbSetFluxLog - .AsNoTracking() - .Where(x => (x.dtEvento >= DtMin && x.dtEvento <= DtMax) && (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodFlux == "*" || x.CodFlux == CodFlux)) - .OrderByDescending(x => x.dtEvento) - .Take(MaxRec) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco Gruppi - /// - /// - public List FluxLogPareto(string idxMacchina, DateTime dtFrom, DateTime dtTo) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = dbCtx - .DbSetFluxLog - .Where(x => (string.IsNullOrEmpty(idxMacchina) || x.IdxMacchina == idxMacchina) && (dtFrom <= x.dtEvento && x.dtEvento <= dtTo)) - .AsNoTracking() - .GroupBy(x => x.CodFlux) - .Select(g => new ParetoFluxLogDTO() { IdxMacchina = idxMacchina, CodFlux = g.Key, Qty = g.Count() }) - .OrderByDescending(x => x.Qty) - .ToList(); - } - return dbResult; - } - - /// - /// Stored manutenzione del DB - /// - /// Esegue realmente il task - /// Aggiornamento statistiche - /// Salvataggio - /// def: 1000 - /// def: 10 - /// def: 50 - /// - public async Task ForceDbMaint(bool doExec, bool doUpdStat, bool doSave, int minPgCnt, int minAvgFrag, int maxAvgFragReb) - { - Log.Info($"Inizio ForceDbMaint on MoonProAdminContext"); - bool fatto = false; - // uso context admin x query lunghe - using (var dbCtx = new MoonProAdminContext(_configuration)) - { - var pFlgExec = new SqlParameter("@FlgExec", doExec ? "Y" : "N"); - var pFlgUpdStat = new SqlParameter("@FlgUpdStat", doUpdStat ? "Y" : "N"); - var pFlgSave = new SqlParameter("@FlgSave", doSave ? "Y" : "N"); - var pMinPgCnt = new SqlParameter("@min_page_count", minPgCnt); - var pMinAvgFrag = new SqlParameter("@min_avg_fragmentation_in_percent", minAvgFrag); - var pMaxAvgFrag = new SqlParameter("@max_avg_fragmentation_per_rebuild", maxAvgFragReb); - - var dbResult = await dbCtx - .Database - .ExecuteSqlRawAsync("EXEC man.stp_Utility_Maintanance"); - //.ExecuteSqlRaw("EXEC man.stp_Utility_Maintanance @FlgExec, @FlgUpdStat, @FlgSave, @min_page_count, @min_avg_fragmentation_in_percent, @max_avg_fragmentation_per_rebuild", pFlgExec, pFlgUpdStat, pFlgSave, pMinPgCnt, pMinAvgFrag, pMaxAvgFrag); - fatto = true; - } - Log.Info($"FINE ForceDbMaint on MoonProAdminContext"); - return fatto; - } - - /// - /// Eliminazione di un record macchina dal gruppo - /// - /// - /// - public bool Grp2MaccDelete(Gruppi2MaccModel rec2del) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var dbRec = dbCtx - .DbSetGrp2Macc - .Where(x => x.CodGruppo == rec2del.CodGruppo && x.IdxMacchina == rec2del.IdxMacchina) - .FirstOrDefault(); - if (dbRec != null) - { - dbCtx.DbSetGrp2Macc.Remove(dbRec); - int numDone = dbCtx.SaveChanges(); - answ = numDone != 0; - } - } - return answ; - } - - /// - /// Insert di un record macchina - /// - /// - /// - public bool Grp2MaccInsert(Gruppi2MaccModel upsRec) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var dbRec = dbCtx - .DbSetGrp2Macc - .Where(x => x.CodGruppo == upsRec.CodGruppo && x.IdxMacchina == upsRec.IdxMacchina) - .FirstOrDefault(); - if (dbRec == null) - { - dbCtx.DbSetGrp2Macc.Add(upsRec); - // salvo - int numDone = dbCtx.SaveChanges(); - answ = numDone != 0; - } - } - return answ; - } - - /// - /// Eliminazione di un record operatore dal gruppo - /// - /// - /// - public bool Grp2OperDelete(Gruppi2OperModel rec2del) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var dbRec = dbCtx - .DbSetGrp2Oper - .Where(x => x.CodGruppo == rec2del.CodGruppo && x.MatrOpr == rec2del.MatrOpr) - .FirstOrDefault(); - if (dbRec != null) - { - dbCtx.DbSetGrp2Oper.Remove(dbRec); - int numDone = dbCtx.SaveChanges(); - answ = numDone != 0; - } - } - return answ; - } - - /// - /// Insert di un record operatore - /// - /// - /// - public bool Grp2OperInsert(Gruppi2OperModel upsRec) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var dbRec = dbCtx - .DbSetGrp2Oper - .Where(x => x.CodGruppo == upsRec.CodGruppo && x.MatrOpr == upsRec.MatrOpr) - .FirstOrDefault(); - if (dbRec == null) - { - dbCtx.DbSetGrp2Oper.Add(upsRec); - // salvo - int numDone = dbCtx.SaveChanges(); - answ = numDone != 0; - } - } - return answ; - } - - /// - /// Elimina record - /// - /// - public bool IstKitDelete(IstanzeKitModel rec2del) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetInstKit - .Where(x => x.KeyKit == rec2del.KeyKit && x.KeyExtOrd == rec2del.KeyExtOrd) - .FirstOrDefault(); - // se ci fosse aggiorno... - if (actRec != null) - { - dbCtx - .DbSetInstKit - .Remove(actRec); - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Elenco istanze KIT da ricerca - /// - /// - /// - /// - public List IstKitFilt(string keyKit, string keyExtOrd) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetInstKit - .Where(x => (string.IsNullOrEmpty(keyKit) && string.IsNullOrEmpty(keyExtOrd)) || (x.KeyKit.Contains(keyKit) && !string.IsNullOrEmpty(keyKit)) || (x.KeyExtOrd.Contains(keyExtOrd) && !string.IsNullOrEmpty(keyExtOrd))) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Effettua creazione istanza KIT - /// - /// Articolo KIT (fittizio) - /// Chiave x filtro conf su tab WKS - public bool IstKitInsertByWKS(string CodArtParent, string KeyFilt) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var pCodArtParent = new SqlParameter("@CodArtParent", CodArtParent); - var pKeyFilt = new SqlParameter("@KeyFilt", KeyFilt); - - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC dbo.stp_IstKit_insertByWKS @CodArtParent,@KeyFilt", pCodArtParent, pKeyFilt); - answ = true; - } - return answ; - } - - /// - /// Esegue upsert record - /// - /// - public bool IstKitUpsert(IstanzeKitModel editRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetInstKit - .Where(x => x.KeyKit == editRec.KeyKit && x.KeyExtOrd == editRec.KeyExtOrd) - .FirstOrDefault(); - - // se ci fosse aggiorno... - if (actRec == null) - { - dbCtx - .DbSetInstKit - .Add(editRec); - } - else - { - actRec.CodArtParent = editRec.CodArtParent; - actRec.CodArtChild = editRec.CodArtChild; - actRec.QtyART = editRec.QtyART; - actRec.QtyKIT = editRec.QtyKIT; - dbCtx.Entry(actRec).State = EntityState.Modified; - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Elenco giacenze - /// - /// id odl da cercare - /// - public List ListGiacenze(int IdxOdl) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_InveContext(_configuration)) - { - try - { - dbResult = dbCtx - .DbGiacenzeData - .AsNoTracking() - .Where(x => x.IdxOdl == IdxOdl) - .ToList(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante ListGiacenze{Environment.NewLine}{exc}"); - } - } - return dbResult; - } - - /// - /// Elenco link JQM completo - /// - /// - /// - public List ListLinkAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetLinkMenu - .AsNoTracking() - .OrderBy(x => x.Ordine) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco link JQM dato filtro tipo - /// - /// - /// - public List ListLinkFilt(string tipoLink) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetLinkMenu - .Where(x => x.TipoLink == tipoLink) - .AsNoTracking() - .OrderBy(x => x.Ordine) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato) - /// - /// Stato ODL: true=in corso/completato - /// Cod articolo - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Reparto selezionato - /// Macchina selezionata - /// Data inizio - /// Data fine - /// - public List ListODLFilt(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var InCorso = new SqlParameter("@InCorso", inCorso); - var CodArt = new SqlParameter("@CodArt", codArt); - var KeyRich = new SqlParameter("@KeyRich", keyRichPart); - var CodGruppo = new SqlParameter("@CodGruppo", Reparto); - var IdxMacc = new SqlParameter("@IdxMacchina", IdxMacchina); - var DataFrom = new SqlParameter("@DataFrom", startDate); - var DataTo = new SqlParameter("@DataTo", endDate); - - dbResult = dbCtx - .DbSetODLExp - .FromSqlRaw("EXEC stp_ODL_getByFiltSpec @InCorso, @CodArt, @KeyRich, @CodGruppo, @IdxMacchina, @DataFrom, @DataTo", InCorso, CodArt, KeyRich, CodGruppo, IdxMacc, DataFrom, DataTo) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Recupero elenco PODL EXPL filtrati - /// - /// - /// True = aperti (=senza ODL) - /// - public List ListPODL_ByCodArt(string CodArticolo, bool OnlyAvail) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var pCodArticolo = new SqlParameter("@CodArticolo", CodArticolo); - var pOnlyAvail = new SqlParameter("@onlyAvail", OnlyAvail); - - dbResult = dbCtx - .DbSetPODLExp - .FromSqlRaw("EXEC stp_PODL_getByCodArt @CodArticolo, @onlyAvail", pCodArticolo, pOnlyAvail) - .AsNoTracking() - .ToList(); - } - - return dbResult; - } - - /// - /// Elenco PODL in un istanza KIT dall'ID del parent - /// - /// IDX PODL parent - /// - public List ListPODL_ByKitParent(int IdxPodlParent) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var pIdxPodlParent = new SqlParameter("@IdxPodlParent", IdxPodlParent); - - dbResult = dbCtx - .DbSetPODLExp - .FromSqlRaw("EXEC stp_PODL_getByParentKitIdx @IdxPodlParent", pIdxPodlParent) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Elenco PODL per composizione KIT non avviati filtrati x articolo, KeyRich (che contiene stato) - /// - /// Solo lanciati (1) o ancora disponibili (0) - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Macchina - /// Gruppo - /// - public List ListPODL_KitFilt(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var Lanc = new SqlParameter("@Lanciato", lanciato); - var KeyRich = new SqlParameter("@KeyRich", keyRichPart); - var CodGrp = new SqlParameter("@CodGruppo", codGruppo); - var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); - var DateFrom = new SqlParameter("@DtInizio", startDate); - var DateTo = new SqlParameter("@DtFine", endDate); - - dbResult = dbCtx - .DbSetPODLExp - .FromSqlRaw("EXEC stp_PODL_getByFiltSpecKit @Lanciato, @KeyRich, @CodGruppo, @IdxMacchina, @DtInizio, @DtFine", Lanc, KeyRich, CodGrp, IdxMacc, DateFrom, DateTo) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato) - /// - /// Solo lanciati (1) o ancora disponibili (0) - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Macchina - /// Gruppo - /// - public List ListPODLFilt(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var Lanc = new SqlParameter("@Lanciato", lanciato); - var KeyRich = new SqlParameter("@KeyRich", keyRichPart); - var CodGrp = new SqlParameter("@CodGruppo", codGruppo); - var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); - var DateFrom = new SqlParameter("@DtInizio", startDate); - var DateTo = new SqlParameter("@DtFine", endDate); - - dbResult = dbCtx - .DbSetPODLExp - .FromSqlRaw("EXEC stp_PODL_getByFiltSpec @Lanciato, @KeyRich, @CodGruppo, @IdxMacchina, @DtInizio, @DtFine", Lanc, KeyRich, CodGrp, IdxMacc, DateFrom, DateTo) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Elenco valori ammessi x tabella/colonna - /// - /// - /// - /// - public List ListValuesFilt(string tabName, string fieldName) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetListValues - .Where(x => x.TableName == tabName && x.FieldName == fieldName) - .AsNoTracking() - .OrderBy(x => x.ordinal) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco Macchine dato operatore secondo gruppi (macchine/operatore) - /// - /// - /// - public List MacchineByMatrOper(int MatrOpr) - { - List dbResult = new List(); - try - { - using (var dbCtx = new MoonProContext(options)) - { - if (MatrOpr == 0) - { - dbResult = dbCtx - .DbSetMacchine - .AsNoTracking() - .OrderBy(x => x.IdxMacchina) - .ToList(); - } - else - { - dbResult = dbCtx - .DbSetGrp2Oper - .Where(g => g.MatrOpr == MatrOpr) - .Join(dbCtx.DbSetGrp2Macc, - g => g.CodGruppo, - m => m.CodGruppo, - (g, m) => m - ) - .Distinct() - .Join(dbCtx.DbSetMacchine, - g => g.IdxMacchina, - m => m.IdxMacchina, - (g, m) => m - ) - .Distinct() - .AsNoTracking() - .OrderBy(x => x.IdxMacchina) - .ToList(); - } - } - } - catch (Exception exc) - { - Log.Error($"Eccezione in MacchineByMatrOper{Environment.NewLine}{exc}"); - } - return dbResult; - } - - /// - /// Elenco da tabella Macchine filtro x gruppo - /// - /// - /// - public List MacchineGetFilt(string codGruppo) - { - List dbResult = new List(); - try - { - using (var dbCtx = new MoonProContext(options)) - { - if (codGruppo == "*") - { - dbResult = dbCtx - .DbSetMacchine - .AsNoTracking() - .OrderBy(x => x.IdxMacchina) - .ToList(); - } - else - { - dbResult = dbCtx - .DbSetGrp2Macc - .Where(g => g.CodGruppo == codGruppo) - .Join(dbCtx.DbSetMacchine, - g => g.IdxMacchina, - m => m.IdxMacchina, - (g, m) => m - ) - .AsNoTracking() - .OrderBy(x => x.IdxMacchina) - .ToList(); - } - } - } - catch (Exception exc) - { - Log.Error($"Eccezione in MacchineGetFilt{Environment.NewLine}{exc}"); - } - return dbResult; - } - - /// - /// Elenco id MacchineModel che abbiano dati FLuxLog, nel periodo indicato - /// - /// - /// - /// - public async Task> MacchineWithFlux(DateTime dtStart, DateTime dtEnd) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = await dbCtx - .DbSetFluxLog - .AsNoTracking() - .Where(x => x.dtEvento >= dtStart && x.dtEvento <= dtEnd) - .Select(i => i.IdxMacchina) - .Distinct() - .ToListAsync(); - } - return dbResult; - } - - /// - /// Aggiornamento record Microstato macchina - /// - /// - /// - public async Task MicroStatoMacchinaUpsert(MicroStatoMacchinaModel newRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = await dbCtx - .DbSetMicroStatoMacc - .Where(x => x.IdxMacchina == newRec.IdxMacchina) - .AsNoTracking() - .FirstOrDefaultAsync(); - if (actRec == null) - { - dbCtx - .DbSetMicroStatoMacc - .Add(newRec); - } - else - { - actRec.IdxMicroStato = newRec.IdxMicroStato; - actRec.InizioStato = newRec.InizioStato; - actRec.Value = newRec.Value; - - dbCtx.Entry(actRec).State = EntityState.Modified; - } - await dbCtx.SaveChangesAsync(); - fatto = true; - } - return fatto; - } - - /// - /// Elenco da tabella MappaStatoExplModel - /// - /// - public List MseGetAll(int maxAge = 2000) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); - - dbResult = dbCtx - .DbSetMSE - .FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Elenco ODL dato batch selezionato - /// - /// Batch richiesto - /// - public List OdlByBatch(string batchSel) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_InveContext(_configuration)) - { - try - { - dbResult = dbCtx - .DbGiacenzeData - .AsNoTracking() - .Where(x => x.IdentRG == batchSel) - .Select(x => x.IdxOdl) - .ToList(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante OdlByBatch{Environment.NewLine}{exc}"); - } - } - return dbResult; - } - - /// - /// ODL da chiave - /// - /// - public ODLExpModel OdlByKey(int IdxOdl) - { - ODLExpModel dbResult = new ODLExpModel(); - using (var dbCtx = new MoonProContext(options)) - { - try - { - dbResult = dbCtx - .DbSetODLExp - .AsNoTracking() - .Where(x => x.IdxOdl == IdxOdl) - .FirstOrDefault(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante OdlByKey{Environment.NewLine}{exc}"); - } - } - return dbResult; - } - - /// - /// Chiusura ODL con eventuale conferma pezzi - /// - /// idx odl da chiudere - /// idx macchina - /// matricola operatore - /// indica se confermare i pezzi prima di chiudere ODL - /// Conferma con rettifica (ev 121) x pezzi lasciati in macchina - /// Modo conferma produzione (0=periodo, 1=giorno, 2=turno) - /// - public async Task ODLClose(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi, bool confRett, int modoConfProd) - { - bool fatto = false; - await Task.Delay(1); - if (idxOdl > 0) - { - using (var dbCtx = new MoonProContext(options)) - { - DateTime adesso = DateTime.Now; - // preparo i parametri - var IdxODL = new SqlParameter("@IdxODL", idxOdl); - var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); - - // FARE FIXME TODO !!! da valutare casi setup/autoconferma... -#if false - // controllo se HO pezzi da confermare... - var statoProd = StatoProdMacchina(idxMacchina); - if (statoProd.pezziNonConfermati < 1) - { } -#endif - - // se richiesto confermo produzione - if (confPezzi) - { - var MatrApp = new SqlParameter("@MatrApp", idxMacchina); - - /* ---------------------------------- - * CONFERMA PEZZI - * - * condizioni da verificare: - * - gestione rettifica (ev121) / pezzi da LASCIARE in macchina - * - conferma a zero pezzi (setup) oppure con i pezzi fatti e non ancora confermati - * - * - * - * */ - - // recupero i dati dei pezzi da confermare... con DbSetPzProd + exec - // stp_PzProd_getByMacchina 'SIMUL_01' - - // stp_ConfermaProduzCompletaFull - /* - * @idxMacchina NVARCHAR(50), - @MatrApp INT, - @dataFrom DATETIME, - @dataTo DATETIME, - @pezziConf INT, - @pezziLasciati INT, -- pezzi lasciati = evento 121 (-) pre conferma e (+) dopo --> da lasciare in macchina post conferma - @pezziScar INT = 0, -- pezzi scartati (registrati da 2016.11.20) DA INDICARE COME VALORE > 0!!! sennò faccio ABS... - @TipoConf INT = 0, -- Tipo intervallo conferma: 0 = periodo intero, 1 = per giorni, 2 = per turni - @DataOraApp DATETIME = NULL, -- di norma GETDATE() nel programma - serve per ricalcolo - @TestConferma BIT = 1 -- TestConferma : 1 = verifica conf. duplicata e inserisci in ElencoConfermeProd, 0 = nessuna verifica e inserimento ( per ricalcolo ) - */ - } - - // ora chiudo ODL con stored SENZA ritorno... - try - { - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC stp_ODL_fineProd @IdxODL, @IdxMacchina", IdxODL, IdxMacchina); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante ODLClose{Environment.NewLine}{exc}"); - } - } - } - return fatto; - } - - /// - /// Recupero odl data chiave - /// - /// - /// - /// - public async Task OdlGetByKey(int idxOdl) - { - ODLModel dbResult = new ODLModel(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = await dbCtx - .DbSetODL - .FirstOrDefaultAsync(x => x.IdxOdl == idxOdl); - } - return dbResult; - } - - /// - /// Recupero Odl CORRENTI - /// - /// - public List OdlGetCurrent() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetODL - .Where(x => x.DataInizio != null && x.DataFine == null) - .ToList(); - } - return dbResult; - } - - /// - /// Elenco TUTTI GLI ODL - /// - /// - public List OdlListAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - try - { - dbResult = dbCtx - .DbSetODL - .AsNoTracking() - .ToList(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante ListOdlAll{Environment.NewLine}{exc}"); - } - } - return dbResult; - } - - /// - /// Statistiche ODL calcolate (da stored stp_STAT_ODL) - /// - /// - public async Task> OdlStart(int IdxOdl) - { - List dbResult = new List(); - if (IdxOdl > 0) - { - using (var dbCtx = new MoonProContext(options)) - { - var IdxODL = new SqlParameter("@IdxODL", IdxOdl); - - dbResult = await dbCtx - .DbSetStatOdl - .FromSqlRaw("EXEC stp_STAT_ODL @IdxODL", IdxODL) - .AsNoTracking() - .ToListAsync(); - } - } - return dbResult; - } - - /// - /// Elenco da tabella Operatori filtro x gruppo - /// - /// - /// - public List OperatoriGetFilt(string codGruppo) - { - List dbResult = new List(); - try - { - using (var dbCtx = new MoonProContext(options)) - { - if (codGruppo == "*") - { - dbResult = dbCtx - .DbOperatori - .AsNoTracking() - .OrderBy(x => x.MatrOpr) - .ToList(); - } - else - { - dbResult = dbCtx - .DbSetGrp2Oper - .Where(g => g.CodGruppo == codGruppo) - .Join(dbCtx.DbOperatori, - g => g.MatrOpr, - m => m.MatrOpr, - (g, m) => m - ) - .AsNoTracking() - .OrderBy(x => x.MatrOpr) - .ToList(); - } - } - } - catch (Exception exc) - { - Log.Error($"Eccezione in OperatoriGetFilt{Environment.NewLine}{exc}"); - } - return dbResult; - } - - /// - /// Elenco parametri validi x una data macchina - /// - /// - /// - public List ParametriGetFilt(string IdxMacchina) - { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = dbCtx - .DbSetFluxLog - .AsNoTracking() - .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina)) - .Take(1000) - .Select(i => i.CodFlux) - .Distinct() - .OrderBy(x => x) - .ToList(); - } - return dbResult; - } - - /// - /// Stato prod macchina - /// - /// - /// - public PzProdModel PezziProdMacchina(string idxMacchina) - { - PzProdModel dbResult = new PzProdModel(); - using (var dbCtx = new MoonProContext(options)) - { - var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); - dbResult = dbCtx - .DbSetPzProd - .FromSqlRaw("EXEC stp_PzProd_getByMacchina @IdxMacchina", IdxMacchina) - .AsNoTracking() - .FirstOrDefault(); - } - return dbResult; - } - - /// - /// Recupero PODL da chiave - /// - /// - /// - public async Task PODL_getByKey(int idxPODL) - { - PODLModel dbResult = new PODLModel(); - using (var dbCtx = new MoonProContext(options)) - { - try - { - dbResult = dbCtx - .DbSetPODL - .AsNoTracking() - .Where(x => x.IdxPromessa == idxPODL) - .Include(a => a.ArticoloNav) - .FirstOrDefault(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante PODL_getByKey{Environment.NewLine}{exc}"); - } - } - await Task.Delay(1); - return dbResult; - } - - /// - /// Recupero PODL da IdxOdl - /// - /// - /// - public PODLModel PODL_getByOdl(int idxODL) - { - PODLModel dbResult = new PODLModel(); - using (var dbCtx = new MoonProContext(options)) - { - try - { - dbResult = dbCtx - .DbSetPODL - .AsNoTracking() - .Where(x => x.IdxOdl == idxODL) - .FirstOrDefault(); - } - catch (Exception exc) - { - Log.Error($"Eccezione durante PODL_getByOdl{Environment.NewLine}{exc}"); - } - } - return dbResult; - } - - /// - /// Avvio setup ODL da PODL - /// - /// - /// - /// - /// - /// - /// - public async Task PODL_startSetup(PODLExpModel editRec, int matrOpr, double tcRich, int pzPallet, string note, DateTime dtEvent) - { - bool answ = false; - - PODLModel recPODL = new PODLModel() - { - IdxPromessa = editRec.IdxPromessa, - KeyRichiesta = editRec.KeyRichiesta, - KeyBCode = editRec.KeyBCode, - IdxOdl = editRec.IdxOdl, - CodArticolo = editRec.CodArticolo, - CodGruppo = editRec.CodGruppo, - IdxMacchina = editRec.IdxMacchina, - NumPezzi = editRec.NumPezzi, - Tcassegnato = editRec.Tcassegnato, - DueDate = editRec.DueDate, - Priorita = editRec.Priorita, - PzPallet = editRec.PzPallet, - Note = editRec.Note, - CodCli = editRec.CodCli, - InsertDate = editRec.InsertDate - }; - - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currRec = dbCtx - .DbSetPODL - .AsNoTracking() - .Where(x => x.IdxPromessa == recPODL.IdxPromessa) - .FirstOrDefault(); - - if (currRec != null) - { - // eseguo stored attrezzaggio - var IdxPromessa = new SqlParameter("@idxPromessa", recPODL.IdxPromessa); - var MatrOpr = new SqlParameter("@MatrOpr", matrOpr); - var IdxMacchina = new SqlParameter("@IdxMacchina", recPODL.IdxMacchina); - var TCRichAttr = new SqlParameter("@TCRichAttr", tcRich); - var PzPallet = new SqlParameter("@PzPallet", pzPallet); - var Note = new SqlParameter("@Note", note); - var DtEvento = new SqlParameter("@dtEvento", dtEvent); - var callResult = await dbCtx - .Database - .ExecuteSqlRawAsync("EXEC stp_ODL_inizioSetupPromessa @idxPromessa, @MatrOpr, @IdxMacchina, @TCRichAttr, @PzPallet, @Note, @dtEvento", IdxPromessa, MatrOpr, IdxMacchina, TCRichAttr, PzPallet, Note, DtEvento); - - answ = true; - } - } - catch (Exception exc) - { - Log.Error($"Eccezione durante PODL_doSetup{Environment.NewLine}{exc}"); - } - } - await Task.Delay(1); - return answ; - } - - /// - /// Chiamata salvataggio ricetta su DB - /// - /// - /// - /// - public async Task PODL_updateRecipe(int idxPODL, string recipeName) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currRec = dbCtx - .DbSetPODL - .Where(x => x.IdxPromessa == idxPODL) - .FirstOrDefault(); - - if (currRec != null) - { - currRec.Recipe = recipeName; - dbCtx.Entry(currRec).State = EntityState.Modified; - await dbCtx.SaveChangesAsync(); - answ = true; - } - } - catch (Exception exc) - { - Log.Error($"Eccezione durante PODL_updateRecipe{Environment.NewLine}{exc}"); - } - } - await Task.Delay(1); - return answ; - } - - /// - /// Eliminazione Record - /// - /// - /// - public async Task PODLDeleteRecord(PODLExpModel currRec) - { - PODLModel recPODL = new PODLModel() - { - IdxPromessa = currRec.IdxPromessa, - KeyRichiesta = currRec.KeyRichiesta, - KeyBCode = currRec.KeyBCode, - IdxOdl = currRec.IdxOdl, - CodArticolo = currRec.CodArticolo, - CodGruppo = currRec.CodGruppo, - IdxMacchina = currRec.IdxMacchina, - NumPezzi = currRec.NumPezzi, - Tcassegnato = currRec.Tcassegnato, - DueDate = currRec.DueDate, - Priorita = currRec.Priorita, - PzPallet = currRec.PzPallet, - Note = currRec.Note, - CodCli = currRec.CodCli, - InsertDate = currRec.InsertDate - }; - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currVal = dbCtx - .DbSetPODL - .Where(x => x.IdxPromessa == recPODL.IdxPromessa) - .FirstOrDefault(); - dbCtx - .DbSetPODL - .Remove(currVal); - await dbCtx.SaveChangesAsync(); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante PODLDeleteRecord{Environment.NewLine}{exc}"); - } - } - return fatto; - } - - /// - /// Effettua il task di eliminazione PODL KIT + istanze + riattivazione PODL originali disattivate tramite stored - /// - /// IdxPODL parent - public bool PodlIstKitDelete(int IdxPODL) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - var pIdxPODL = new SqlParameter("@IdxPODL", IdxPODL); - - var dbResult = dbCtx - .Database - .ExecuteSqlRaw("EXEC dbo.stp_PodlIstKit_delete @IdxPODL", pIdxPODL); - answ = dbResult != 0; - } - return answ; - } - - /// - /// Update Record - /// - /// - /// - public async Task PODLUpdateRecord(PODLModel editRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - var currRec = dbCtx - .DbSetPODL - .Where(x => x.IdxPromessa == editRec.IdxPromessa) - .FirstOrDefault(); - if (currRec != null) - { - currRec.CodGruppo = editRec.CodGruppo; - currRec.CodArticolo = editRec.CodArticolo; - currRec.IdxMacchina = editRec.IdxMacchina; - currRec.KeyBCode = editRec.KeyBCode; - currRec.KeyRichiesta = editRec.KeyRichiesta; - currRec.NumPezzi = editRec.NumPezzi; - currRec.Tcassegnato = editRec.Tcassegnato; - currRec.Attivabile = editRec.Attivabile; - currRec.Note = editRec.Note; - dbCtx.Entry(currRec).State = EntityState.Modified; - } - else - { - dbCtx - .DbSetPODL - .Add(editRec); - } - await dbCtx.SaveChangesAsync(); - fatto = true; - } - catch (Exception exc) - { - Log.Error($"Eccezione durante PODLUpdateRecord{Environment.NewLine}{exc}"); - } - } - return fatto; - } - - /// - /// Annulla modifiche su una specifica entity (cancel update) - /// - /// - /// - public bool RollBackEntity(object item) - { - bool answ = false; - using (var dbCtx = new MoonProContext(options)) - { - try - { - if (dbCtx.Entry(item).State == Microsoft.EntityFrameworkCore.EntityState.Deleted || dbCtx.Entry(item).State == Microsoft.EntityFrameworkCore.EntityState.Modified) - { - dbCtx.Entry(item).Reload(); - } - } - catch (Exception exc) - { - Log.Error($"Eccezione in rollBackEntity{Environment.NewLine}{exc}"); - } - } - return answ; - } - - /// - /// Stato macchina (da key) - /// - /// - /// - public StatoMacchineModel StatoMacchina(string idxMacchina) - { - StatoMacchineModel dbResult = new StatoMacchineModel(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetStatoMacc - .Where(x => x.IdxMacchina == idxMacchina) - .AsNoTracking() - .FirstOrDefault(); - } - return dbResult; - } - - /// - /// Elimina record - /// - /// - public bool TemplateKitDelete(TemplateKitModel rec2del) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetTempKit - .Where(x => x.CodArtParent == rec2del.CodArtParent && x.CodArtChild == rec2del.CodArtChild) - .FirstOrDefault(); - // se ci fosse aggiorno... - if (actRec != null) - { - dbCtx - .DbSetTempKit - .Remove(actRec); - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Elenco template KIT da ricerca - /// - /// - /// - /// - public List TemplateKitFilt(string KitCode, string codChild) - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetTempKit - .Where(x => (string.IsNullOrEmpty(KitCode) && string.IsNullOrEmpty(codChild)) || (x.CodArtParent.Contains(KitCode) && !string.IsNullOrEmpty(KitCode)) || (x.CodArtChild.Contains(codChild) && !string.IsNullOrEmpty(codChild))) - .AsNoTracking() - .ToList(); - } - return dbResult; - } - - /// - /// Esegue upsert record - /// - /// - /// - public bool TemplateKitUpsert(TemplateKitModel editRec, string codAzienda) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - // verifico preliminarmente articolo... - var recArt = dbCtx - .DbSetArticoli - .FirstOrDefault(x => x.CodArticolo == editRec.CodArtParent); - // se mancasse... - if (recArt == null) - { - // aggiungo! - AnagArticoliModel newRecArt = new AnagArticoliModel() - { - CodArticolo = editRec.CodArtParent, - Tipo = "KIT", - DescArticolo = $"Articolo KIT - {DateTime.Now:yyyy-MM-dd HH:mm:ss}", - Disegno = "", - Azienda = codAzienda, - CurrRev = "", - ProdRev = "" - }; - dbCtx - .DbSetArticoli - .Add(newRecArt); - } - - // proseguo col KIT - var actRec = dbCtx - .DbSetTempKit - .Where(x => x.CodArtParent == editRec.CodArtParent && x.CodArtChild == editRec.CodArtChild) - .FirstOrDefault(); - - // se NON ci fosse aggiungo... - if (actRec == null) - { - dbCtx - .DbSetTempKit - .Add(editRec); - } - else - { - actRec.Qty = editRec.Qty; - dbCtx.Entry(actRec).State = EntityState.Modified; - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Punteggio compatibilità KIT per KeyFilt indicato - /// - /// - /// - /// - public List TksScore(string KeyFilt, int MaxResult) - { - List dbResult = new List(); - if (!string.IsNullOrEmpty(KeyFilt)) - { - using (var dbCtx = new MoonProContext(options)) - { - var pKeyFilt = new SqlParameter("@KeyFilt", KeyFilt); - var pMaxRes = new SqlParameter("@maxResult", MaxResult); - - dbResult = dbCtx - .DbSetTksScore - .FromSqlRaw("EXEC stp_TKS_Search @KeyFilt, @maxResult", pKeyFilt, pMaxRes) - .AsNoTracking() - .ToList(); - } - } - return dbResult; - } - - /// - /// Elenco Vocabolario (completo) - /// - /// - public List VocabolarioGetAll() - { - List dbResult = new List(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetVocabolario - .AsNoTracking() - .OrderBy(x => x.Lemma) - .ToList(); - } - return dbResult; - } - - /// - /// Elimina record - /// - /// - public bool WipKitDelete(WipSetupKitModel rec2del) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetWipKit - .Where(x => x.KeyFilt == rec2del.KeyFilt && x.CodOrd == rec2del.CodOrd) - .FirstOrDefault(); - // se ci fosse aggiorno... - if (actRec != null) - { - dbCtx - .DbSetWipKit - .Remove(actRec); - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Elimina i record associati al KeyFilt indicato - /// - /// - public bool WipKitDeleteGroup(string KeyFilt) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetWipKit - .Where(x => x.KeyFilt == KeyFilt) - .ToList(); - // se ci fosse aggiorno... - if (actRec != null) - { - dbCtx - .DbSetWipKit - .RemoveRange(actRec); - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Elimina record + vecchi della data-ora indicata - /// - /// - /// - public bool WipKitDeleteOlder(DateTime dateLimit) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetWipKit - .Where(x => x.DataIns < dateLimit) - .ToList(); - // se ci fosse aggiorno... - if (actRec != null) - { - dbCtx - .DbSetWipKit - .RemoveRange(actRec); - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - /// - /// Elenco record WipSetupKit da KeyFilt - /// - /// - /// - public List WipKitFilt(string KeyFilt) - { - List dbResult = new List(); - // solo se filtro valido... - if (!string.IsNullOrEmpty(KeyFilt)) - { - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetWipKit - .Where(x => x.KeyFilt.Contains(KeyFilt)) - .AsNoTracking() - .ToList(); - } - } - return dbResult; - } - - /// - /// Esegue upsert record - /// - /// - public bool WipKitUpsert(WipSetupKitModel editRec) - { - bool fatto = false; - using (var dbCtx = new MoonProContext(options)) - { - var actRec = dbCtx - .DbSetWipKit - .Where(x => x.KeyFilt == editRec.KeyFilt && x.CodOrd == editRec.CodOrd) - .FirstOrDefault(); - - // se ci fosse aggiorno... - if (actRec == null) - { - dbCtx - .DbSetWipKit - .Add(editRec); - } - else - { - actRec.CodArt = editRec.CodArt; - actRec.DescArt = editRec.DescArt; - actRec.Qta = editRec.Qta; - actRec.DataIns = editRec.DataIns; - dbCtx.Entry(actRec).State = EntityState.Modified; - } - var res = dbCtx.SaveChanges(); - fatto = res != 0; - } - return fatto; - } - - #endregion Public Methods - - #region Private Fields - - private static IConfiguration _configuration; - private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - private DbContextOptions options; - - #endregion Private Fields - } -} \ No newline at end of file diff --git a/MP.Data/Controllers/MpSpecRepository.cs b/MP.Data/Controllers/MpSpecRepository.cs new file mode 100644 index 00000000..27b70da3 --- /dev/null +++ b/MP.Data/Controllers/MpSpecRepository.cs @@ -0,0 +1,2029 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using NLog; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Controllers +{ + public class MpSpecController + { + protected readonly IDbContextFactory _ctxFactory; + protected readonly IDbContextFactory _ctxFactoryFL; + #region Public Constructors + + public MpSpecController( + IConfiguration configuration, + IDbContextFactory ctxFactory, + IDbContextFactory ctxFactoryFL) + { + _configuration = configuration; + _ctxFactory = ctxFactory; + _ctxFactoryFL = ctxFactoryFL; +#if false + string connStr = _configuration.GetConnectionString("MP.Data"); + options = new DbContextOptionsBuilder() + .UseSqlServer(connStr) + .Options; +#endif + Log.Info("Avviata classe MpSpecController"); + } + + #endregion Public Constructors + + #region Public Methods + +#if false + /// + /// Stacca un nuovo counter x il tipo richiesto + /// + /// + public async Task AnagCountersGetNextAsync(string cntType) + { + AnagCountersModel answ = new AnagCountersModel(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + bool outTable = true; + if (outTable) + { + var pCntType = new SqlParameter("@CntType", cntType); + var pLastNum = new SqlParameter + { + ParameterName = "@LastNum", + SqlDbType = SqlDbType.Int, + Direction = ParameterDirection.Output + }; + + var dbResult = await dbCtx + .DbSetAnagCount + .FromSqlRaw("EXEC dbo.stp_getNextNumb @CntType, @LastNum OUTPUT", pCntType, pLastNum) + .AsNoTracking() + .FirstOrDefaultAsync(); + if (dbResult != null) + { + answ = dbResult; + } + } + else + { + // se si volessero impiegare parametri OUTPUT (qui ne mancherebbe 1 nella stored x CntCode...) + var pCntType = new SqlParameter("@CntType", cntType); + var pLastNum = new SqlParameter + { + ParameterName = "@LastNum", + SqlDbType = SqlDbType.Int, + Direction = ParameterDirection.Output + }; + var pCntCode = new SqlParameter + { + ParameterName = "@CntCode", + SqlDbType = SqlDbType.NVarChar, + Direction = ParameterDirection.Output + }; + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC dbo.stp_getNextNumb @CntType, @LastNum OUTPUT, @CntCode OUTPUT", pCntType, pLastNum, pCntCode); + if (dbResult != 0) + { + answ.CntType = cntType; + answ.CntCode = $"{pCntCode.Value}"; + int lNum = 0; + int.TryParse($"{pLastNum.Value}", out lNum); + answ.LastNum = lNum; + } + } + return answ; + } + + /// + /// Restituisce l'anagrafica EVENTI generalmente disponibile per OGNI macchina + /// + /// Nome Table x filtro (std: EvList) + /// Nome Field x filtro (std: Common) + /// + public async Task> AnagEventiGeneralAsync(string TableName = "EvList", string FieldName = "Common") + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var pTableName = new SqlParameter("@TableName", TableName); + var pFieldName = new SqlParameter("@FieldName", FieldName); + var dbResult = await dbCtx + .DbSetVSEB + .FromSqlRaw("exec dbo.stp_vseb_getGenerallyAvailable @TableName, @FieldName", pTableName, pFieldName) + .AsNoTracking() + .ToListAsync(); + return dbResult ?? new(); + } + + + /// + /// Elenco Gruppi tipo Azienda + /// + /// + public Task> AnagGruppiAziendeAsync() + { + return AnagGruppiGetTipoAsync("AZIENDA"); + } + + /// + /// Delete record AnagraficaGruppi + /// + /// + public async Task AnagGruppiDeleteAsync(AnagGruppiModel updRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var dbRec = await dbCtx + .DbSetAnagGruppi + .AsNoTracking() + .Where(x => x.CodGruppo == updRec.CodGruppo) + .FirstOrDefaultAsync(); + // se trovato aggiorno descrizione (resto immutato x sicurezza!) + if (dbRec != null) + { + dbCtx.DbSetAnagGruppi.Remove(dbRec); + } + var numRes = await dbCtx.SaveChangesAsync(); + return numRes != 0; + } + + /// + /// Elenco Gruppi tipo Fasi + /// + /// + public Task> AnagGruppiFaseAsync() + { + return AnagGruppiGetTipoAsync("FASE"); + } + + + /// + /// Gruppi x tipo modalità Async + /// + /// + /// + public async Task> AnagGruppiGetTipoAsync(string tipoGruppo) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetAnagGruppi + .Where(x => x.TipoGruppo == tipoGruppo) + .AsNoTracking() + .OrderBy(x => x.CodGruppo) + .ToListAsync(); + } + + /// + /// Elenco Gruppi tipo REPARTO (x associazione Macchine-Operatori) in formato DTO con conteggi del numero record trovati + /// + /// + public async Task> AnagGruppiRepartoDtoAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + // in primis recupero i reparti... + var listReparti = await AnagGruppiGetTipoAsync("REPARTO"); + + // recupero TUTTE le macchine da DbSetGrp2Macc + var listMacc = await dbCtx + .DbSetGrp2Macc + .AsNoTracking() + .ToListAsync(); + // recupero TUTTI gli operatori da DbSetGrp2Oper + var listOpr = await dbCtx + .DbSetGrp2Oper + .AsNoTracking() + .ToListAsync(); + + return listReparti + .Select(x => new RepartiDTO() + { + CodGruppo = x.CodGruppo, + TipoGruppo = x.TipoGruppo, + DescrGruppo = x.DescrGruppo, + SelEnabled = x.SelEnabled, + CountMacc = listMacc.Where(y => y.CodGruppo == x.CodGruppo).Select(x => x.IdxMacchina).Distinct().Count(), + CountOpr = listOpr.Where(y => y.CodGruppo == x.CodGruppo).Select(x => x.MatrOpr).Distinct().Count() + }) + .ToList(); + } + + /// + /// Upsert record AnagraficaGruppi (solo codice/descrizione) + /// + /// + /// + public async Task AnagGruppiUpsertAsync(AnagGruppiModel updRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var dbRec = await dbCtx + .DbSetAnagGruppi + .AsNoTracking() + .Where(x => x.CodGruppo == updRec.CodGruppo) + .FirstOrDefaultAsync(); + // se trovato aggiorno descrizione (resto immutato x sicurezza!) + if (dbRec != null) + { + dbRec.DescrGruppo = updRec.DescrGruppo; + dbCtx.Entry(dbRec).State = EntityState.Modified; + } + // altrimenti aggiungo + else + { + await dbCtx.DbSetAnagGruppi.AddAsync(updRec); + } + var numRes = await dbCtx.SaveChangesAsync(); + + return numRes != 0; + } + + + /// + /// Elenco valori ammessi x Stati commessa (es Yacht Baglietto) + /// + /// + public Task> AnagStatiCommAsync() + { + return ListValuesFiltAsync("PODL", "StatoComm"); + } + + /// + /// Elenco valori ammessi x Tipo articoli + /// + /// + public Task> AnagTipoArtLvAsync() + { + return ListValuesFiltAsync("AnagArticoli", "Tipo"); + } + +#endif + +#if false + /// + /// Elenco codice articoli che abbiano dati Dossier + /// + /// + public async Task> ArticleWithDossierAsync() + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + return await dbCtx + .DbSetDossiers + .AsNoTracking() + .Select(i => i.CodArticolo) + .Distinct() + .ToListAsync(); + } + +#endif + +#if false + /// + /// Conteggio num articoli Async + /// + /// + public async Task ArticoliCountAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var result = await dbCtx + .DbSetArticoli + .CountAsync(); + return result; + } + + /// + /// Conteggio articoli data condizione ricerca + /// + /// + /// + /// + /// + public async Task ArticoliCountSearchAsync(string tipoArt = "*", string azienda = "*", string searchVal = "") + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + IQueryable query = dbCtx.DbSetArticoli.AsNoTracking(); + + // filtro tipo articolo + if (tipoArt != "*") + { + //query = query.Where(x => x.Tipo.ToLower() == tipoArt.ToLower()); + query = query.Where(x => EF.Functions.Like(x.Tipo, tipoArt)); + } + // filtro azienda + if (azienda != "*") + { + //query = query.Where(x => x.Azienda.ToLower() == azienda.ToLower()); + query = query.Where(x => EF.Functions.Like(x.Azienda, azienda)); + } + // filtro ricerca + if (!string.IsNullOrWhiteSpace(searchVal)) + { + string pattern = $"%{searchVal}%"; + query = query.Where(x => + EF.Functions.Like(x.CodArticolo, pattern) || + EF.Functions.Like(x.DescArticolo, pattern) || + EF.Functions.Like(x.Disegno, pattern)); + } + + return await query + .OrderBy(x => x.CodArticolo) + .CountAsync(); + } + + /// + /// Elenco tabella Articoli IMPIEGATI (da stored stp_ART_getUsed) Async + /// + /// + public async Task ArticoliCountUsedAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var result = await dbCtx + .DbSetCounter + .FromSqlRaw("EXEC stp_ART_CountUsed") + .AsNoTracking() + .ToListAsync(); + + return result.FirstOrDefault()?.NumCount ?? 0; + } + + /// + /// Eliminazione Record + /// + /// + /// + public async Task ArticoliDeleteRecordAsync(AnagArticoliModel currRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currVal = dbCtx + .DbSetArticoli + .Where(x => x.CodArticolo == currRec.CodArticolo) + .FirstOrDefault(); + dbCtx + .DbSetArticoli + .Remove(currVal); + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Restitusice elenco articoli dato tipo (es KIT) + /// + /// + /// + /// + /// + public async Task> ArticoliGetByTipoAsync(string tipo, string azienda = "*") + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetArticoli + .AsNoTracking() + .Where(x => x.Tipo.ToUpper() == tipo.ToUpper() && (azienda == "*" || x.Azienda.ToUpper() == azienda.ToUpper())) + .OrderBy(x => x.CodArticolo) + .ToListAsync(); + } + + /// + /// Elenco tabella Articoli da filtro + /// + /// + /// + /// + /// + /// + public async Task> ArticoliGetSearchAsync(int numRecord, string tipoArt = "*", string azienda = "*", string searchVal = "") + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + IQueryable query = dbCtx.DbSetArticoli + .AsNoTracking(); + + // filtro tipo articolo + if (tipoArt != "*") + { + //query = query.Where(x => x.Tipo.ToLower() == tipoArt.ToLower()); + query = query.Where(x => EF.Functions.Like(x.Tipo, tipoArt)); + } + // filtro azienda + if (azienda != "*") + { + //query = query.Where(x => x.Azienda.ToLower() == azienda.ToLower()); + query = query.Where(x => EF.Functions.Like(x.Azienda, azienda)); + } + // filtro ricerca + if (!string.IsNullOrWhiteSpace(searchVal)) + { + string pattern = $"%{searchVal}%"; + query = query.Where(x => + EF.Functions.Like(x.CodArticolo, pattern) || + EF.Functions.Like(x.DescArticolo, pattern) || + EF.Functions.Like(x.Disegno, pattern)); + } + + return await query + .OrderBy(x => x.CodArticolo) + .Take(numRecord) + .ToListAsync(); + } + + /// + /// Elenco tabella Articoli NON IMPIEGATI (da stored stp_ART_getUsed) Async + /// + /// + public async Task> ArticoliGetUnusedAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetArticoli + .FromSqlRaw("EXEC stp_ART_getNotUsed") + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Elenco tabella Articoli IMPIEGATI (da stored stp_ART_getUsed) Async + /// + /// + public async Task> ArticoliGetUsedAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetArticoli + .FromSqlRaw("EXEC stp_ART_getUsed") + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Elenco Articoli che sono in KIT Child + /// + /// + public async Task> ArticoliInKitAsync() + { + List dbResult = new List(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + dbResult = await dbCtx + .DbSetArticoli + .FromSqlRaw("EXEC stp_TempKIT_getArtChild") + .AsNoTracking() + .ToListAsync(); + return dbResult; + } + + /// + /// Update Record + /// + /// + /// + public async Task ArticoliUpdateRecord(AnagArticoliModel editRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currRec = dbCtx + .DbSetArticoli + .Where(x => x.CodArticolo == editRec.CodArticolo) + .FirstOrDefault(); + if (currRec != null) + { + currRec.Disegno = editRec.Disegno; + currRec.DescArticolo = editRec.DescArticolo; + currRec.Tipo = editRec.Tipo; + currRec.Azienda = editRec.Azienda; + dbCtx.Entry(currRec).State = EntityState.Modified; + } + else + { + dbCtx + .DbSetArticoli + .Add(editRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } +#endif +#if false + + /// + /// Elenco da tabella Config Async + /// + /// + public async Task> ConfigGetAllAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + /// Update record config + /// + /// + public async Task ConfigUpdateAsync(ConfigModel updRec) + { + bool fatto = false; + ConfigModel dbResult = new ConfigModel(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + dbResult = await dbCtx + .DbSetConfig + .Where(x => x.Chiave == updRec.Chiave) + .FirstOrDefaultAsync(); + if (dbResult != null) + { + dbResult.Valore = updRec.Valore; + fatto = await dbCtx.SaveChangesAsync() > 0; + } + return fatto; + } + + /// + /// Eliminazione di un dossier + /// + /// record dossier da eliminare + /// + public async Task DossiersDeleteRecordAsync(DossierModel currRec) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + var currVal = await dbCtx + .DbSetDossiers + .Where(x => x.IdxDossier == currRec.IdxDossier) + .FirstOrDefaultAsync(); + dbCtx + .DbSetDossiers + .Remove(currVal); + + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato + /// macchina (ordinato x data registrazione) + /// + /// * = tutte, altrimenti solo x una data macchina + /// * = tutti, altrimenti solo x un dato articolo + /// Data minima per estrazione records + /// Data Massima per estrazione records + /// Num max record recuperati + /// + public async Task> DossiersGetLastFiltAsync(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + return await dbCtx + .DbSetDossiers + .AsNoTracking() + .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodArticolo == "*" || x.CodArticolo == CodArticolo) && (x.DtRif >= DtStart && x.DtRif <= DtEnd)) + .Include(m => m.MachineNav) + .Include(a => a.ArticoloNav) + .OrderByDescending(x => x.DtRif) + .Take(MaxRec) + .ToListAsync(); + } + + /// + /// insert di un record Dossier + /// + /// record dossier da modificare + /// + public async Task DossiersInsertAsync(DossierModel newRec) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + dbCtx + .DbSetDossiers + .AddAsync(newRec); + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache _redisConn + /// + /// macchina + /// Data min x selezione + /// Data MAX x selezione + public async Task DossiersTakeParamsSnapshotLastAsync(string idxMacchina, DateTime dtMin, DateTime dtMax) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); + var pDtMin = new SqlParameter("@DtMin", dtMin); + var pDtMax = new SqlParameter("@DtMax", dtMax); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_FL_TakeSnapshotLast @IdxMacchina,@DtMin,@DtMax", pIdxMacchina, pDtMin, pDtMax); + return dbResult != 0; + } + + /// + /// Update del campo VALORE di un dossier (che contiene json flux log serializzati) + /// + /// record dossier da modificare + /// + public async Task DossiersUpdateValoreAsync(DossierModel editRec) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + var currRec = await dbCtx + .DbSetDossiers + .Where(x => x.IdxDossier == editRec.IdxDossier) + .FirstOrDefaultAsync(); + if (currRec != null) + { + currRec.Valore = editRec.Valore; + dbCtx.Entry(currRec).State = EntityState.Modified; + } + else + { + await dbCtx + .DbSetDossiers + .AddAsync(editRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elenco valori link (x home e navMenu laterale) + /// + /// + public Task> ElencoLinkAsync() + { + return ListLinkFiltAsync("SpecLink"); + } + + /// + /// Aggiunta record EventList + /// + /// + /// + public async Task EvListInsertAsync(EventListModel newRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currRec = await dbCtx + .DbSetEvList + .AddAsync(newRec); + + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Funzione di Data Reduction x FluxLog + /// + /// + /// + /// + /// + /// + /// + /// Restitusice list dei record statistiche raccolti (da integrare a quelli rpesenti in Redis...) + /// + public async Task> FluxLogDataReduxAsync(string idxMaccSel, List fluxList, Periodo currPeriodo, Enums.ValSelection valMode, Enums.DataInterval intReq, int maxItem) + { + List procStats = new List(); + Log.Info($"Inizio FluxLogDataReduxAsync | idxMaccSel: {idxMaccSel} | periodo: {currPeriodo.Inizio:yyyy-MM-dd} --> {currPeriodo.Fine:yyyy-MM-dd}"); + TimeSpan step = TimeSpan.FromHours(1); + switch (intReq) + { + case Enums.DataInterval.minute: + step = TimeSpan.FromMinutes(1.00 / maxItem); + break; + + case Enums.DataInterval.hour: + step = TimeSpan.FromHours(1.00 / maxItem); + break; + + case Enums.DataInterval.day: + step = TimeSpan.FromDays(1.00 / maxItem); + break; + + default: + break; + } + + // setup parametri costanti x stored + var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMaccSel); + var pOnlyTest = new SqlParameter("@OnlyTest", false); + + // dbContext condiviso + using var dbCtx = new MoonPro_FluxContext(_configuration); + // opzionalmente timeout comandi a 2 minuti... NON usato x ora e da testare + //dbCtx.Database.SetCommandTimeout(TimeSpan.FromMinutes(2)); + // processo 1:1 ogni flusso + foreach (var item in fluxList) + { + Log.Info($"FluxLogDataReduxAsync | Flux: {item}"); + int numRecProc = 0; + Stopwatch sw = new Stopwatch(); + sw.Start(); + // parametri x flusso + var pCodFlux = new SqlParameter("@CodFlux", item); + // inizializzo cursore timer + DateTime dtCursStart = currPeriodo.Inizio; + DateTime dtCursEnd = dtCursStart.Add(step); + bool setCompleted = false; + // li processo per intervallo richiesto, cercando dati nel periodo eselezionando VC + while (!setCompleted) + { + // ora recupero TUTTI i dati della macchina + var currFlux = await dbCtx + .DbSetFluxLog + .Where(x => (x.CodFlux == item) && (x.dtEvento >= dtCursStart && x.dtEvento < dtCursEnd) && (x.IdxMacchina == idxMaccSel)) + .ToListAsync(); + + int numRec = currFlux.Count; + numRecProc += numRec; + if (numRec > maxItem) + { + List listPeriodi = new List(); + + switch (valMode) + { + case Enums.ValSelection.First: + // recupero 2° item + var recStart = currFlux.Skip(1).FirstOrDefault(); + // salvo periodo! + listPeriodi.Add(new Periodo(recStart.dtEvento, dtCursEnd)); + break; + + case Enums.ValSelection.Last: + // recupero ultimo item + var recEnd = currFlux.LastOrDefault(); + // salvo periodo! + listPeriodi.Add(new Periodo(dtCursStart, recEnd.dtEvento)); + break; + + case Enums.ValSelection.Center: + int idx = 1; + // per iniziare mi metto a 1/(n+1) rec come step + var recCent = currFlux.Skip(idx / (maxItem + 1)).FirstOrDefault(); + listPeriodi.Add(new Periodo(dtCursStart, recCent.dtEvento)); + // salvo restanti periodi (se > 1)! + if (maxItem > 1) + { + for (int i = 2; i < maxItem; i++) + { + DateTime dtInizio = recCent.dtEvento; + recCent = currFlux.Skip(i / (maxItem + 1)).FirstOrDefault(); + listPeriodi.Add(new Periodo(dtInizio, recCent.dtEvento)); + } + } + // aggiungo ultimo... + listPeriodi.Add(new Periodo(recCent.dtEvento.AddSeconds(1), dtCursEnd)); + break; + + default: + break; + } + + // ciclo x tutti i periodi e chiamo stored... + foreach (var slot in listPeriodi) + { + // parametri x periodo (base) + var pDtStart = new SqlParameter("@DtStart", slot.Inizio); + var pDtEnd = new SqlParameter("@DtEnd", slot.Fine); + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC man.stp_ReduceFluxLog @IdxMacchina, @CodFlux, @DtStart, @DtEnd, @OnlyTest", pIdxMacchina, pCodFlux, pDtStart, pDtEnd, pOnlyTest); + } + } + + // incremento dt fine periodo + dtCursStart = dtCursEnd; + dtCursEnd = dtCursStart.Add(step); + setCompleted = dtCursStart >= currPeriodo.Fine; + } + // fermo cronometro e salvo su DB... + sw.Stop(); + StatDedupDTO currStat = new StatDedupDTO() + { + IdxMacchina = idxMaccSel, + CodFlux = item, + Interval = intReq, + Num4Int = maxItem, + NumRec = numRecProc, + ProcTime = sw.Elapsed.TotalSeconds + }; + procStats.Add(currStat); + } + Log.Info($"FINE FluxLogDataReduxAsync | idxMaccSel: {idxMaccSel} | periodo: {currPeriodo.Inizio:yyyy-MM-dd} --> {currPeriodo.Fine:yyyy-MM-dd}"); + return procStats; + } + + /// + /// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione) + /// + /// Data massima x eventi + /// Data minima x eventi + /// * = tutte, altrimenti solo x una data macchina + /// *=tutti, altrimenti solo selezionato + /// numero massimo record da restituire + /// + public async Task> FluxLogGetLastFiltAsync(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => (x.dtEvento >= DtMin && x.dtEvento <= DtMax) && (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodFlux == "*" || x.CodFlux == CodFlux)) + .OrderByDescending(x => x.dtEvento) + .Take(MaxRec) + .ToListAsync() ?? new(); + } + + /// + /// Elenco Gruppi + /// + /// + public async Task> FluxLogParetoAsync(string idxMacchina, DateTime dtFrom, DateTime dtTo) + { + using var dbCtx = new MoonPro_FluxContext(_configuration); + return await dbCtx + .DbSetFluxLog + .Where(x => (string.IsNullOrEmpty(idxMacchina) || x.IdxMacchina == idxMacchina) && (dtFrom <= x.dtEvento && x.dtEvento <= dtTo)) + .AsNoTracking() + .GroupBy(x => x.CodFlux) + .Select(g => new ParetoFluxLogDTO() { IdxMacchina = idxMacchina, CodFlux = g.Key, Qty = g.Count() }) + .OrderByDescending(x => x.Qty) + .ToListAsync() ?? new(); + } + + /// + /// Stored manutenzione del DB + /// + /// Esegue realmente il task + /// Aggiornamento statistiche + /// Salvataggio + /// def: 1000 + /// def: 10 + /// def: 50 + /// + public async Task ForceDbMaintAsync(bool doExec, bool doUpdStat, bool doSave, int minPgCnt, int minAvgFrag, int maxAvgFragReb) + { + Log.Info($"Inizio ForceDbMaintAsync on MoonProAdminContext"); + // uso context admin x query lunghe + using var dbCtx = new MoonProAdminContext(_configuration); + var pFlgExec = new SqlParameter("@FlgExec", doExec ? "Y" : "N"); + var pFlgUpdStat = new SqlParameter("@FlgUpdStat", doUpdStat ? "Y" : "N"); + var pFlgSave = new SqlParameter("@FlgSave", doSave ? "Y" : "N"); + var pMinPgCnt = new SqlParameter("@min_page_count", minPgCnt); + var pMinAvgFrag = new SqlParameter("@min_avg_fragmentation_in_percent", minAvgFrag); + var pMaxAvgFrag = new SqlParameter("@max_avg_fragmentation_per_rebuild", maxAvgFragReb); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC man.stp_Utility_Maintanance"); + //.ExecuteSqlRaw("EXEC man.stp_Utility_Maintanance @FlgExec, @FlgUpdStat, @FlgSave, @min_page_count, @min_avg_fragmentation_in_percent, @max_avg_fragmentation_per_rebuild", pFlgExec, pFlgUpdStat, pFlgSave, pMinPgCnt, pMinAvgFrag, pMaxAvgFrag); + Log.Info($"FINE ForceDbMaintAsync on MoonProAdminContext"); + return dbResult != 0; + } + + /// + /// Eliminazione di un record macchina dal gruppo + /// + /// + /// + public async Task Grp2MaccDeleteAsync(Gruppi2MaccModel rec2del) + { + bool answ = false; + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Macc + .Where(x => x.CodGruppo == rec2del.CodGruppo && x.IdxMacchina == rec2del.IdxMacchina) + .FirstOrDefaultAsync(); + if (dbRec != null) + { + dbCtx.DbSetGrp2Macc.Remove(dbRec); + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + /// Insert di un record macchina + /// + /// + /// + public async Task Grp2MaccInsertAsync(Gruppi2MaccModel upsRec) + { + bool answ = false; + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Macc + .Where(x => x.CodGruppo == upsRec.CodGruppo && x.IdxMacchina == upsRec.IdxMacchina) + .FirstOrDefaultAsync(); + if (dbRec == null) + { + await dbCtx.DbSetGrp2Macc.AddAsync(upsRec); + // salvo + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + /// Eliminazione di un record operatore dal gruppo + /// + /// + /// + public async Task Grp2OperDeleteAsync(Gruppi2OperModel rec2del) + { + bool answ = false; + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Oper + .Where(x => x.CodGruppo == rec2del.CodGruppo && x.MatrOpr == rec2del.MatrOpr) + .FirstOrDefaultAsync(); + if (dbRec != null) + { + dbCtx.DbSetGrp2Oper.Remove(dbRec); + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + /// Insert di un record operatore + /// + /// + /// + public async Task Grp2OperInsertAsync(Gruppi2OperModel upsRec) + { + bool answ = false; + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Oper + .Where(x => x.CodGruppo == upsRec.CodGruppo && x.MatrOpr == upsRec.MatrOpr) + .FirstOrDefaultAsync(); + if (dbRec == null) + { + await dbCtx.DbSetGrp2Oper.AddAsync(upsRec); + // salvo + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + /// Elimina record + /// + /// + public async Task IstKitDeleteAsync(IstanzeKitModel rec2del) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetInstKit + .Where(x => x.KeyKit == rec2del.KeyKit && x.KeyExtOrd == rec2del.KeyExtOrd) + .FirstOrDefaultAsync(); + // se ci fosse aggiorno... + if (actRec != null) + { + dbCtx + .DbSetInstKit + .Remove(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elenco istanze KIT da ricerca + /// + /// + /// + /// + public async Task> IstKitFiltAsync(string keyKit, string keyExtOrd) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetInstKit + .Where(x => (string.IsNullOrEmpty(keyKit) && string.IsNullOrEmpty(keyExtOrd)) || (x.KeyKit.Contains(keyKit) && !string.IsNullOrEmpty(keyKit)) || (x.KeyExtOrd.Contains(keyExtOrd) && !string.IsNullOrEmpty(keyExtOrd))) + .AsNoTracking() + .ToListAsync() ?? new(); + } + + /// + /// Effettua creazione istanza KIT + /// + /// Articolo KIT (fittizio) + /// Chiave x filtro conf su tab WKS + public async Task IstKitInsertByWKSAsync(string CodArtParent, string KeyFilt) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + + var pCodArtParent = new SqlParameter("@CodArtParent", CodArtParent); + var pKeyFilt = new SqlParameter("@KeyFilt", KeyFilt); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC dbo.stp_IstKit_insertByWKS @CodArtParent,@KeyFilt", pCodArtParent, pKeyFilt); + return dbResult != 0; + } + + /// + /// Esegue upsert record + /// + /// + public async Task IstKitUpsertAsync(IstanzeKitModel editRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetInstKit + .Where(x => x.KeyKit == editRec.KeyKit && x.KeyExtOrd == editRec.KeyExtOrd) + .FirstOrDefaultAsync(); + + // se ci fosse aggiorno... + if (actRec == null) + { + await dbCtx + .DbSetInstKit + .AddAsync(editRec); + } + else + { + actRec.CodArtParent = editRec.CodArtParent; + actRec.CodArtChild = editRec.CodArtChild; + actRec.QtyART = editRec.QtyART; + actRec.QtyKIT = editRec.QtyKIT; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elenco giacenze + /// + /// id odl da cercare + /// + public async Task> ListGiacenzeAsync(int IdxOdl) + { + List dbResult = new List(); + using var dbCtx = new MoonPro_InveContext(_configuration); + dbResult = await dbCtx + .DbGiacenzeData + .Where(x => x.IdxOdl == IdxOdl) + .AsNoTracking() + .ToListAsync(); + return dbResult; + } + + /// + /// Elenco link JQM completo + /// + /// + /// + public async Task> ListLinkAllAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetLinkMenu + .AsNoTracking() + .OrderBy(x => x.Ordine) + .ToListAsync(); + } + + /// + /// Elenco link JQM dato filtro tipo, Async + /// + /// + /// + public async Task> ListLinkFiltAsync(string tipoLink) + { + List dbResult = new List(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetLinkMenu + .Where(x => x.TipoLink == tipoLink) + .AsNoTracking() + .OrderBy(x => x.Ordine) + .ToListAsync(); + } + +#endif + + /// + /// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato) + /// + /// Stato ODL: true=in corso/completato + /// Cod articolo + /// KeyRich (parziale) da cercare (es cod stato x yacht) + /// Reparto selezionato + /// Macchina selezionata + /// Data inizio + /// Data fine + /// + public async Task> ListODLFiltAsync(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) + { + List dbResult = new List(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + + var InCorso = new SqlParameter("@InCorso", inCorso); + var CodArt = new SqlParameter("@CodArt", codArt); + var KeyRich = new SqlParameter("@KeyRich", keyRichPart); + var CodGruppo = new SqlParameter("@CodGruppo", Reparto); + var IdxMacc = new SqlParameter("@IdxMacchina", IdxMacchina); + var DataFrom = new SqlParameter("@DataFrom", startDate); + var DataTo = new SqlParameter("@DataTo", endDate); + + return await dbCtx + .DbSetODLExp + .FromSqlRaw("EXEC stp_ODL_getByFiltSpec @InCorso, @CodArt, @KeyRich, @CodGruppo, @IdxMacchina, @DataFrom, @DataTo", InCorso, CodArt, KeyRich, CodGruppo, IdxMacc, DataFrom, DataTo) + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Recupero elenco PODL EXPL filtrati + /// + /// + /// True = aperti (=senza ODL) + /// + public async Task> ListPODL_ByCodArtAsync(string CodArticolo, bool OnlyAvail) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var pCodArticolo = new SqlParameter("@CodArticolo", CodArticolo); + var pOnlyAvail = new SqlParameter("@onlyAvail", OnlyAvail); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByCodArt @CodArticolo, @onlyAvail", pCodArticolo, pOnlyAvail) + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Elenco PODL in un istanza KIT dall'ID del parent + /// + /// IDX PODL parent + /// + public async Task> ListPODL_ByKitParentAsync(int IdxPodlParent) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var pIdxPodlParent = new SqlParameter("@IdxPodlParent", IdxPodlParent); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByParentKitIdx @IdxPodlParent", pIdxPodlParent) + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Elenco PODL per composizione KIT non avviati filtrati x articolo, KeyRich (che contiene stato) + /// + /// Solo lanciati (1) o ancora disponibili (0) + /// KeyRich (parziale) da cercare (es cod stato x yacht) + /// Macchina + /// Gruppo + /// + public async Task> ListPODL_KitFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var Lanc = new SqlParameter("@Lanciato", lanciato); + var KeyRich = new SqlParameter("@KeyRich", keyRichPart); + var CodGrp = new SqlParameter("@CodGruppo", codGruppo); + var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); + var DateFrom = new SqlParameter("@DtInizio", startDate); + var DateTo = new SqlParameter("@DtFine", endDate); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByFiltSpecKit @Lanciato, @KeyRich, @CodGruppo, @IdxMacchina, @DtInizio, @DtFine", Lanc, KeyRich, CodGrp, IdxMacc, DateFrom, DateTo) + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato) - ASYNC + /// + /// Solo lanciati (1) o ancora disponibili (0) + /// KeyRich (parziale) da cercare (es cod stato x yacht) + /// Macchina + /// Gruppo + /// + public async Task> ListPODLFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var Lanc = new SqlParameter("@Lanciato", lanciato); + var KeyRich = new SqlParameter("@KeyRich", keyRichPart); + var CodGrp = new SqlParameter("@CodGruppo", codGruppo); + var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); + var DateFrom = new SqlParameter("@DtInizio", startDate); + var DateTo = new SqlParameter("@DtFine", endDate); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByFiltSpec @Lanciato, @KeyRich, @CodGruppo, @IdxMacchina, @DtInizio, @DtFine", Lanc, KeyRich, CodGrp, IdxMacc, DateFrom, DateTo) + .AsNoTracking() + .ToListAsync(); + } + + /// + /// Elenco valori ammessi x tabella/colonna Async + /// + /// + /// + /// + public async Task> ListValuesFiltAsync(string tabName, string fieldName) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetListValues + .Where(x => x.TableName == tabName && x.FieldName == fieldName) + .AsNoTracking() + .OrderBy(x => x.ordinal) + .ToListAsync(); + } + + /// + /// Elenco Macchine dato operatore secondo gruppi (macchine/operatore) + /// + /// + /// + public async Task> MacchineByMatrOperAsync(int MatrOpr) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + if (MatrOpr == 0) + { + return await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + else + { + return await dbCtx + .DbSetGrp2Oper + .Where(g => g.MatrOpr == MatrOpr) + .Join(dbCtx.DbSetGrp2Macc, + g => g.CodGruppo, + m => m.CodGruppo, + (g, m) => m + ) + .Distinct() + .Join(dbCtx.DbSetMacchine, + g => g.IdxMacchina, + m => m.IdxMacchina, + (g, m) => m + ) + .Distinct() + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + } + + /// + /// Elenco da tabella Macchine filtro x gruppo + /// + /// + /// + public async Task> MacchineGetFiltAsync(string codGruppo) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + if (codGruppo == "*") + { + return await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + else + { + return await dbCtx + .DbSetGrp2Macc + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbSetMacchine, + g => g.IdxMacchina, + m => m.IdxMacchina, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + } + + /// + /// Elenco id MacchineModel che abbiano dati FLuxLog, nel periodo indicato + /// + /// + /// + /// + public async Task> MacchineWithFluxAsync(DateTime dtStart, DateTime dtEnd) + { + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => x.dtEvento >= dtStart && x.dtEvento <= dtEnd) + .Select(i => i.IdxMacchina) + .Distinct() + .ToListAsync() ?? new(); + } + + /// + /// Elenco da tabella MappaStatoExplModel + /// + /// + public async Task> MseGetAllAsync(int maxAge = 2000) + { + List dbResult = new List(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + + var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); + + dbResult = await dbCtx + .DbSetMSE + .FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec) + .AsNoTracking() + .ToListAsync(); + + return dbResult; + } + + /// + /// Elenco ODL dato batch selezionato + /// + /// Batch richiesto + /// + public async Task> OdlByBatchAsync(string batchSel) + { + using var dbCtx = new MoonPro_InveContext(_configuration); + return await dbCtx + .DbGiacenzeData + .AsNoTracking() + .Where(x => x.IdentRG == batchSel) + .Select(x => x.IdxOdl) + .ToListAsync(); + } + + /// + /// ODL da chiave + /// + /// + public async Task OdlByKeyAsync(int IdxOdl) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetODLExp + .AsNoTracking() + .FirstOrDefaultAsync(x => x.IdxOdl == IdxOdl); + } + + /// + /// Chiusura ODL con eventuale conferma pezzi + /// + /// idx odl da chiudere + /// idx macchina + /// matricola operatore + /// indica se confermare i pezzi prima di chiudere ODL + /// Conferma con rettifica (ev 121) x pezzi lasciati in macchina + /// Modo conferma produzione (0=periodo, 1=giorno, 2=turno) + /// + public async Task ODLCloseAsync(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi, bool confRett, int modoConfProd) + { + bool fatto = false; + if (idxOdl > 0) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + DateTime adesso = DateTime.Now; + // preparo i parametri + var IdxODL = new SqlParameter("@IdxODL", idxOdl); + var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); + + // se richiesto confermo produzione + if (confPezzi) + { + var MatrApp = new SqlParameter("@MatrApp", idxMacchina); + + /* ---------------------------------- + * CONFERMA PEZZI + * + * condizioni da verificare: + * - gestione rettifica (ev121) / pezzi da LASCIARE in macchina + * - conferma a zero pezzi (setup) oppure con i pezzi fatti e non ancora confermati + * + * + * + * */ + + // recupero i dati dei pezzi da confermare... con DbSetPzProd + exec + // stp_PzProd_getByMacchina 'SIMUL_01' + + // stp_ConfermaProduzCompletaFull + /* + * @idxMacchina NVARCHAR(50), + @MatrApp INT, + @dataFrom DATETIME, + @dataTo DATETIME, + @pezziConf INT, + @pezziLasciati INT, -- pezzi lasciati = evento 121 (-) pre conferma e (+) dopo --> da lasciare in macchina post conferma + @pezziScar INT = 0, -- pezzi scartati (registrati da 2016.11.20) DA INDICARE COME VALORE > 0!!! sennò faccio ABS... + @TipoConf INT = 0, -- Tipo intervallo conferma: 0 = periodo intero, 1 = per giorni, 2 = per turni + @DataOraApp DATETIME = NULL, -- di norma GETDATE() nel programma - serve per ricalcolo + @TestConferma BIT = 1 -- TestConferma : 1 = verifica conf. duplicata e inserisci in ElencoConfermeProd, 0 = nessuna verifica e inserimento ( per ricalcolo ) + */ + } + + // ora chiudo ODL con stored SENZA ritorno... + try + { + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ODL_fineProd @IdxODL, @IdxMacchina", IdxODL, IdxMacchina); + fatto = dbResult != 0; + } + catch (Exception exc) + { + Log.Error($"Eccezione durante ODLCloseAsync{Environment.NewLine}{exc}"); + } + } + return fatto; + } + + /// + /// Recupero Odl CORRENTI + /// + /// + public async Task> OdlGetCurrentAsync() + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetODL + .Where(x => x.DataInizio != null && x.DataFine == null) + .ToListAsync(); + } + + /// + /// Statistiche ODL calcolate (da stored stp_STAT_ODL) + /// + /// + public async Task> OdlGetStatAsync(int IdxOdl) + { + List dbResult = new List(); + if (IdxOdl > 0) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var IdxODL = new SqlParameter("@IdxODL", IdxOdl); + + dbResult = await dbCtx + .DbSetStatOdl + .FromSqlRaw("EXEC stp_STAT_ODL @IdxODL", IdxODL) + .AsNoTracking() + .ToListAsync(); + } + return dbResult; + } + + /// + /// Elenco da tabella Operatori filtro x gruppo + /// + /// + /// + public async Task> OperatoriGetFiltAsync(string codGruppo) + { + List dbResult = new List(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + if (codGruppo == "*") + { + dbResult = await dbCtx + .DbOperatori + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToListAsync(); + } + else + { + dbResult = await dbCtx + .DbSetGrp2Oper + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbOperatori, + g => g.MatrOpr, + m => m.MatrOpr, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToListAsync(); + } + return dbResult; + } + + /// + /// Elenco parametri validi x una data macchina + /// + /// + /// + public async Task> ParametriGetFiltAsync(string IdxMacchina) + { + using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina)) + .Take(1000) + .Select(i => i.CodFlux) + .Distinct() + .OrderBy(x => x) + .ToListAsync(); + } + + /// + /// Recupero PODL da chiave + /// + /// + /// + public async Task PODL_getByKeyAsync(int idxPODL) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => x.IdxPromessa == idxPODL) + .Include(a => a.ArticoloNav) + .FirstOrDefaultAsync() ?? new(); + } + + /// + /// Recupero PODL da IdxOdl + /// + /// + /// + public async Task PODL_getByOdlAsync(int idxODL) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => x.IdxOdl == idxODL) + .FirstOrDefaultAsync() ?? new(); + } + + /// + /// Dizionario associazione ODL/PODL + /// + /// + /// + public async Task> PODL_getDictOdlPodlAsync(List missingIds) + { + if (missingIds == null || !missingIds.Any()) + return new Dictionary(); + + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => missingIds.Contains(x.IdxOdl)) + .ToDictionaryAsync(x => x.IdxOdl, x => x.IdxPromessa); + } + + /// + /// Avvio setup ODL da PODL + /// + /// + /// + /// + /// + /// + /// + public async Task PODL_startSetup(PODLExpModel editRec, int matrOpr, double tcRich, int pzPallet, string note, DateTime dtEvent) + { + bool answ = false; + PODLModel recPODL = new PODLModel() + { + IdxPromessa = editRec.IdxPromessa, + KeyRichiesta = editRec.KeyRichiesta, + KeyBCode = editRec.KeyBCode, + IdxOdl = editRec.IdxOdl, + CodArticolo = editRec.CodArticolo, + CodGruppo = editRec.CodGruppo, + IdxMacchina = editRec.IdxMacchina, + NumPezzi = editRec.NumPezzi, + Tcassegnato = editRec.Tcassegnato, + DueDate = editRec.DueDate, + Priorita = editRec.Priorita, + PzPallet = editRec.PzPallet, + Note = editRec.Note, + CodCli = editRec.CodCli, + InsertDate = editRec.InsertDate + }; + + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currRec = await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => x.IdxPromessa == recPODL.IdxPromessa) + .FirstOrDefaultAsync(); + + if (currRec != null) + { + // eseguo stored attrezzaggio + var IdxPromessa = new SqlParameter("@idxPromessa", recPODL.IdxPromessa); + var MatrOpr = new SqlParameter("@MatrOpr", matrOpr); + var IdxMacchina = new SqlParameter("@IdxMacchina", recPODL.IdxMacchina); + var TCRichAttr = new SqlParameter("@TCRichAttr", tcRich); + var PzPallet = new SqlParameter("@PzPallet", pzPallet); + var Note = new SqlParameter("@Note", note); + var DtEvento = new SqlParameter("@dtEvento", dtEvent); + var callResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ODL_inizioSetupPromessa @idxPromessa, @MatrOpr, @IdxMacchina, @TCRichAttr, @PzPallet, @Note, @dtEvento", IdxPromessa, MatrOpr, IdxMacchina, TCRichAttr, PzPallet, Note, DtEvento); + + answ = true; + } + return answ; + } + + /// + /// Chiamata salvataggio ricetta su DB + /// + /// + /// + /// + public async Task PODL_updateRecipe(int idxPODL, string recipeName) + { + bool answ = false; + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currRec = await dbCtx + .DbSetPODL + .Where(x => x.IdxPromessa == idxPODL) + .FirstOrDefaultAsync(); + + if (currRec != null) + { + currRec.Recipe = recipeName; + dbCtx.Entry(currRec).State = EntityState.Modified; + answ = await dbCtx.SaveChangesAsync() > 0; + } + return answ; + } + + /// + /// Eliminazione Record + /// + /// + /// + public async Task PODLDeleteRecordAsync(PODLExpModel currRec) + { + PODLModel recPODL = new PODLModel() + { + IdxPromessa = currRec.IdxPromessa, + KeyRichiesta = currRec.KeyRichiesta, + KeyBCode = currRec.KeyBCode, + IdxOdl = currRec.IdxOdl, + CodArticolo = currRec.CodArticolo, + CodGruppo = currRec.CodGruppo, + IdxMacchina = currRec.IdxMacchina, + NumPezzi = currRec.NumPezzi, + Tcassegnato = currRec.Tcassegnato, + DueDate = currRec.DueDate, + Priorita = currRec.Priorita, + PzPallet = currRec.PzPallet, + Note = currRec.Note, + CodCli = currRec.CodCli, + InsertDate = currRec.InsertDate + }; + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currVal = await dbCtx + .DbSetPODL + .Where(x => x.IdxPromessa == recPODL.IdxPromessa) + .FirstOrDefaultAsync(); + dbCtx + .DbSetPODL + .Remove(currVal); + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Effettua il task di eliminazione PODL KIT + istanze + riattivazione PODL originali disattivate tramite stored + /// + /// IdxPODL parent + public async Task PodlIstKitDeleteAsync(int IdxPODL) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var pIdxPODL = new SqlParameter("@IdxPODL", IdxPODL); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC dbo.stp_PodlIstKit_delete @IdxPODL", pIdxPODL); + return dbResult != 0; + } + + /// + /// Update Record + /// + /// + /// + public async Task PODLUpdateRecordAsync(PODLModel editRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var currRec = await dbCtx + .DbSetPODL + .Where(x => x.IdxPromessa == editRec.IdxPromessa) + .FirstOrDefaultAsync(); + if (currRec != null) + { + currRec.CodGruppo = editRec.CodGruppo; + currRec.CodArticolo = editRec.CodArticolo; + currRec.IdxMacchina = editRec.IdxMacchina; + currRec.KeyBCode = editRec.KeyBCode; + currRec.KeyRichiesta = editRec.KeyRichiesta; + currRec.NumPezzi = editRec.NumPezzi; + currRec.Tcassegnato = editRec.Tcassegnato; + currRec.Attivabile = editRec.Attivabile; + currRec.Note = editRec.Note; + dbCtx.Entry(currRec).State = EntityState.Modified; + } + else + { + await dbCtx + .DbSetPODL + .AddAsync(editRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Stato macchina (da key) + /// + /// + /// + public async Task StatoMacchinaAsync(string idxMacchina) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetStatoMacc + .Where(x => x.IdxMacchina == idxMacchina) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + + /// + /// Elimina record + /// + /// + public async Task TemplateKitDeleteAsync(TemplateKitModel rec2del) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetTempKit + .Where(x => x.CodArtParent == rec2del.CodArtParent && x.CodArtChild == rec2del.CodArtChild) + .FirstOrDefaultAsync(); + // se ci fosse aggiorno... + if (actRec != null) + { + dbCtx + .DbSetTempKit + .Remove(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elenco template KIT da ricerca + /// + /// + /// + /// + public async Task> TemplateKitFiltAsync(string KitCode, string codChild) + { + List dbResult = new List(); + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + dbResult = await dbCtx + .DbSetTempKit + .Where(x => (string.IsNullOrEmpty(KitCode) && string.IsNullOrEmpty(codChild)) || (x.CodArtParent.Contains(KitCode) && !string.IsNullOrEmpty(KitCode)) || (x.CodArtChild.Contains(codChild) && !string.IsNullOrEmpty(codChild))) + .AsNoTracking() + .ToListAsync(); + return dbResult; + } + + /// + /// Esegue upsert record + /// + /// + /// + public async Task TemplateKitUpsertAsync(TemplateKitModel editRec, string codAzienda) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + // verifico preliminarmente articolo... + var recArt = dbCtx + .DbSetArticoli + .FirstOrDefault(x => x.CodArticolo == editRec.CodArtParent); + // se mancasse... + if (recArt == null) + { + // aggiungo! + AnagArticoliModel newRecArt = new AnagArticoliModel() + { + CodArticolo = editRec.CodArtParent, + Tipo = "KIT", + DescArticolo = $"Articolo KIT - {DateTime.Now:yyyy-MM-dd HH:mm:ss}", + Disegno = "", + Azienda = codAzienda, + CurrRev = "", + ProdRev = "" + }; + dbCtx + .DbSetArticoli + .Add(newRecArt); + } + + // proseguo col KIT + var actRec = await dbCtx + .DbSetTempKit + .Where(x => x.CodArtParent == editRec.CodArtParent && x.CodArtChild == editRec.CodArtChild) + .FirstOrDefaultAsync(); + + // se NON ci fosse aggiungo... + if (actRec == null) + { + await dbCtx + .DbSetTempKit + .AddAsync(editRec); + } + else + { + actRec.Qty = editRec.Qty; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Punteggio compatibilità KIT per KeyFilt indicato + /// + /// + /// + /// + public async Task> TksScoreAsync(string KeyFilt, int MaxResult) + { + List dbResult = new List(); + if (!string.IsNullOrEmpty(KeyFilt)) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var pKeyFilt = new SqlParameter("@KeyFilt", KeyFilt); + var pMaxRes = new SqlParameter("@maxResult", MaxResult); + dbResult = await dbCtx + .DbSetTksScore + .FromSqlRaw("EXEC stp_TKS_Search @KeyFilt, @maxResult", pKeyFilt, pMaxRes) + .AsNoTracking() + .ToListAsync(); + } + return dbResult; + } + +#if false + /// + /// Elenco Vocabolario di una lingua + /// + /// + public Dictionary VocabolarioGetLang(string lingua) + { + using var dbCtx = _ctxFactory.CreateDbContext(); + var rawList = dbCtx + .DbSetVocabolario + .AsNoTracking() + .Where(x => x.Lingua.ToLower() == lingua.ToLower()) + .OrderBy(x => x.Lemma) + .ToList(); + // Proietto in dizionario + return rawList + .DistinctBy(t => t.Lemma, StringComparer.OrdinalIgnoreCase) + .ToDictionary(t => t.Lemma, t => t.Traduzione, StringComparer.OrdinalIgnoreCase); + } + + /// + /// Upsert record Vocabolario + /// + /// + /// + public async Task VocabolarioUpsertAsync(VocabolarioModel upsRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetVocabolario + .Where(x => x.Lingua == upsRec.Lingua && x.Lemma == upsRec.Lemma) + .FirstOrDefaultAsync(); + + // se ci fosse aggiorno... + if (actRec == null) + { + dbCtx + .DbSetVocabolario + .Add(upsRec); + } + else + { + actRec.Traduzione = upsRec.Traduzione; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elimina record + /// + /// + public async Task WipKitDeleteAsync(WipSetupKitModel rec2del) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetWipKit + .Where(x => x.KeyFilt == rec2del.KeyFilt && x.CodOrd == rec2del.CodOrd) + .FirstOrDefaultAsync(); + // se ci fosse aggiorno... + if (actRec != null) + { + dbCtx + .DbSetWipKit + .Remove(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } +#endif + + /// + /// Elimina record + vecchi della data-ora indicata + /// + /// + /// + public async Task WipKitDeleteOlderAsync(DateTime dateLimit) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetWipKit + .Where(x => x.DataIns < dateLimit) + .ToListAsync(); + // se ci fosse aggiorno... + if (actRec != null) + { + dbCtx + .DbSetWipKit + .RemoveRange(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + /// Elenco record WipSetupKit da KeyFilt + /// + /// + /// + public async Task> WipKitFiltAsync(string KeyFilt) + { + List dbResult = new List(); + // solo se filtro valido... + if (!string.IsNullOrEmpty(KeyFilt)) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + dbResult = await dbCtx + .DbSetWipKit + .Where(x => x.KeyFilt.Contains(KeyFilt)) + .AsNoTracking() + .ToListAsync(); + } + return dbResult; + } + + /// + /// Esegue upsert record + /// + /// + public async Task WipKitUpsertAsync(WipSetupKitModel editRec) + { + using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var actRec = await dbCtx + .DbSetWipKit + .Where(x => x.KeyFilt == editRec.KeyFilt && x.CodOrd == editRec.CodOrd) + .FirstOrDefaultAsync(); + + // se ci fosse aggiorno... + if (actRec == null) + { + dbCtx + .DbSetWipKit + .Add(editRec); + } + else + { + actRec.CodArt = editRec.CodArt; + actRec.DescArt = editRec.DescArt; + actRec.Qta = editRec.Qta; + actRec.DataIns = editRec.DataIns; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + #endregion Public Methods + + #region Private Fields + + private static IConfiguration _configuration; + private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); +#if false + private DbContextOptions options; +#endif + + #endregion Private Fields + } +} \ No newline at end of file diff --git a/MP.Data/Controllers/MpStatsController.cs b/MP.Data/Controllers/MpStatsController.cs index 046d5549..46b4e137 100644 --- a/MP.Data/Controllers/MpStatsController.cs +++ b/MP.Data/Controllers/MpStatsController.cs @@ -19,11 +19,15 @@ namespace MP.Data.Controllers public MpStatsController(IConfiguration configuration) { _configuration = configuration; + string connStr = _configuration.GetConnectionString("MP.Stats"); + options = new DbContextOptionsBuilder() + .UseSqlServer(connStr) + .Options; Log.Info("Avviata classe MpStatsController"); } #endregion Public Constructors - + private DbContextOptions options; #region Public Methods /// @@ -33,13 +37,10 @@ namespace MP.Data.Controllers public List ActionsGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) - { - dbResult = dbCtx + using var dbCtx = new MoonPro_STATSContext(options); + return dbCtx .DbSetAzioniUL .ToList(); - } - return dbResult; } /// @@ -49,13 +50,10 @@ namespace MP.Data.Controllers public List AnagFLTransGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) - { - dbResult = dbCtx - .DbSetAnagFLTrans - .ToList(); - } - return dbResult; + using var dbCtx = new MoonPro_STATSContext(options); + return dbCtx + .DbSetAnagFLTrans + .ToList(); } /// @@ -67,7 +65,7 @@ namespace MP.Data.Controllers public List ArticoliGetSearch(int numRecord, string searchVal = "") { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetArticoli @@ -88,7 +86,7 @@ namespace MP.Data.Controllers public List CommesseGetSearch(int numRecord, string searchVal = "") { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetODL @@ -107,7 +105,7 @@ namespace MP.Data.Controllers public List ConfigGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetConfig @@ -133,7 +131,7 @@ namespace MP.Data.Controllers public List FluxLogRawData(string IdxMacchina, DateTime DtStart, DateTime DtEnd, string fluxType) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetFL @@ -153,7 +151,7 @@ namespace MP.Data.Controllers public List FluxTypeList() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetFL @@ -172,7 +170,7 @@ namespace MP.Data.Controllers public List MacchineEnergy() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetMaccStat @@ -188,7 +186,7 @@ namespace MP.Data.Controllers public List MacchineGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetMacchine @@ -204,7 +202,7 @@ namespace MP.Data.Controllers public async Task> MacchineEnergyCheckGetAllAsync() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = await dbCtx .DbSetMacchineCheck @@ -222,7 +220,7 @@ namespace MP.Data.Controllers public bool RollBackEntity(object item) { bool answ = false; - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { try { @@ -248,7 +246,7 @@ namespace MP.Data.Controllers public List StatControlliGetAll(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DataStart); var dataTo = new SqlParameter("@dataTo", DataEnd); @@ -280,7 +278,7 @@ namespace MP.Data.Controllers public List StatDdbGetAll(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo, int FirstRecord, int NumRecord) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DataStart); var dataTo = new SqlParameter("@dataTo", DataEnd); @@ -312,7 +310,7 @@ namespace MP.Data.Controllers public int StatDdbGetCount(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo) { int numResult = 0; - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { numResult = dbCtx .DbSetDdbTurni @@ -335,7 +333,7 @@ namespace MP.Data.Controllers public List StatOdlEnergyGetFilt(string IdxMacchina, DateTime DtStart, DateTime DtEnd, int IdxODL, string KeyRichiesta, string CodArticolo) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DtStart); var dataTo = new SqlParameter("@dataTo", DtEnd); @@ -361,7 +359,7 @@ namespace MP.Data.Controllers public List StatOdlGetAll(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DataStart); var dataTo = new SqlParameter("@dataTo", DataEnd); @@ -389,7 +387,7 @@ namespace MP.Data.Controllers public List StatScartiGetAll(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DataStart); var dataTo = new SqlParameter("@dataTo", DataEnd); @@ -417,7 +415,7 @@ namespace MP.Data.Controllers public List StatTurniOeeGetAll(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DataStart); var dataTo = new SqlParameter("@dataTo", DataEnd); @@ -443,7 +441,7 @@ namespace MP.Data.Controllers public List StatUserLogGetAll(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo) { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { var dataFrom = new SqlParameter("@dataFrom", DataStart); var dataTo = new SqlParameter("@dataTo", DataEnd); @@ -467,7 +465,7 @@ namespace MP.Data.Controllers public List VocabolarioGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_STATSContext(_configuration)) + using (var dbCtx = new MoonPro_STATSContext(options)) { dbResult = dbCtx .DbSetVocabolario diff --git a/MP.Data/Controllers/MpTabController.cs b/MP.Data/Controllers/MpTabController.cs index 55981185..0aaa045e 100644 --- a/MP.Data/Controllers/MpTabController.cs +++ b/MP.Data/Controllers/MpTabController.cs @@ -688,7 +688,7 @@ namespace MP.Data.Controllers } catch (Exception exc) { - Log.Error($"Eccezione durante EvListInsert{Environment.NewLine}{exc}"); + Log.Error($"Eccezione durante EvListInsertAsync{Environment.NewLine}{exc}"); } } await Task.Delay(1); @@ -1029,7 +1029,7 @@ namespace MP.Data.Controllers } catch (Exception exc) { - Log.Error($"Eccezione in MacchineByMatrOper{Environment.NewLine}{exc}"); + Log.Error($"Eccezione in MacchineByMatrOperAsync{Environment.NewLine}{exc}"); } return dbResult; } @@ -1709,7 +1709,7 @@ namespace MP.Data.Controllers } catch (Exception exc) { - Log.Error($"Eccezione durante PODL_getByKey{Environment.NewLine}{exc}"); + Log.Error($"Eccezione durante PODL_getByKeyAsync{Environment.NewLine}{exc}"); } } return dbResult; diff --git a/MP.Data/Controllers/MpVocController.cs b/MP.Data/Controllers/MpVocController.cs index 713dc387..e78b7a8b 100644 --- a/MP.Data/Controllers/MpVocController.cs +++ b/MP.Data/Controllers/MpVocController.cs @@ -1,14 +1,10 @@ -using DnsClient.Protocol; -using Microsoft.Data.SqlClient; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MP.Data.DbModels; using NLog; using System; using System.Collections.Generic; -using System.Drawing.Drawing2D; using System.Linq; -using static MP.Core.Objects.Enums; namespace MP.Data.Controllers { @@ -19,6 +15,10 @@ namespace MP.Data.Controllers public MpVocController(IConfiguration configuration) { _configuration = configuration; + string connStr = _configuration.GetConnectionString("MP.Voc"); + options = new DbContextOptionsBuilder() + .UseSqlServer(connStr) + .Options; Log.Info("Avviata classe MpVocController"); } @@ -26,6 +26,7 @@ namespace MP.Data.Controllers #region Public Methods + private DbContextOptions options; /// /// Elenco da tabella Config /// @@ -33,15 +34,12 @@ namespace MP.Data.Controllers public List ConfigGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_VocContext(_configuration)) - { - dbResult = dbCtx - .DbSetConfig - .AsNoTracking() - .OrderBy(x => x.Chiave) - .ToList(); - } - return dbResult; + using var dbCtx = new MoonPro_VocContext(options); + return dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToList(); } public void Dispose() @@ -55,15 +53,12 @@ namespace MP.Data.Controllers public List LingueGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_VocContext(_configuration)) - { - dbResult = dbCtx - .DbSetLilngue - .AsNoTracking() - .OrderBy(x => x.Lingua) - .ToList(); - } - return dbResult; + using var dbCtx = new MoonPro_VocContext(options); + return dbCtx + .DbSetLilngue + .AsNoTracking() + .OrderBy(x => x.Lingua) + .ToList(); } /// @@ -73,15 +68,12 @@ namespace MP.Data.Controllers public List VocabolarioGetAll() { List dbResult = new List(); - using (var dbCtx = new MoonPro_VocContext(_configuration)) - { - dbResult = dbCtx - .DbSetVocabolario - .AsNoTracking() - .OrderBy(x => x.Lemma) - .ToList(); - } - return dbResult; + using var dbCtx = new MoonPro_VocContext(options); + return dbCtx + .DbSetVocabolario + .AsNoTracking() + .OrderBy(x => x.Lemma) + .ToList(); } #endregion Public Methods diff --git a/MP.Data/DataServiceCollectionExtensions.cs b/MP.Data/DataServiceCollectionExtensions.cs index 2ff337b3..ddc1ef7c 100644 --- a/MP.Data/DataServiceCollectionExtensions.cs +++ b/MP.Data/DataServiceCollectionExtensions.cs @@ -1,9 +1,20 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using MP.AppAuth.Controllers; +using MP.AppAuth.Services; using MP.Data.Controllers; +using MP.Data.Repository.Anag; +using MP.Data.Repository.Dossier; +using MP.Data.Repository.FluxLog; using MP.Data.Repository.IOC; +using MP.Data.Repository.MpLand; +using MP.Data.Repository.MpMon; +using MP.Data.Repository.MpVoc; using MP.Data.Repository.Mtc; +using MP.Data.Repository.Production; +using MP.Data.Repository.System; using MP.Data.Repository.Utils; +using MP.Data.Services; using MP.Data.Services.IOC; using MP.Data.Services.Mtc; using MP.Data.Services.Utils; @@ -12,10 +23,18 @@ namespace MP.Data { public static class DataServiceCollectionExtensions { + #region Public Methods + + /// + /// Aggiunta repository/servizi specifici per IOC + /// + /// + /// public static IServiceCollection AddIocDataLayer(this IServiceCollection services) { // Repository Singleton services.TryAddSingleton(); + services.TryAddSingleton(); // Repository Scoped services.TryAddScoped(); @@ -33,5 +52,122 @@ namespace MP.Data return services; } + + /// + /// Aggiunta repository/servizi specifici per LAND + /// + /// + /// + public static IServiceCollection AddLandDataLayer(this IServiceCollection services) + { + // Controllers MP.AppAuth (dipendenze di AppAuthService) + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + + // Servizi LAND + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + + return services; + } + + /// + /// Aggiunta repository/servizi specifici per MON + /// + /// + /// + public static IServiceCollection AddMonDataLayer(this IServiceCollection services) + { + services.TryAddSingleton(); + services.TryAddSingleton(); + return services; + } + + /// + /// Aggiunta repository/servizi specifici per SPEC + /// + /// + /// + public static IServiceCollection AddSpecDataLayer(this IServiceCollection services) + { + // ---------- Start Repository ---------- + services.TryAddScoped(); + + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + // ---------- End Repository ---------- + + // ---------- Start Servizi ---------- + //services.TryAddSingleton(); + // ---------- End Servizi ---------- + + // ---------- Start Altro ---------- + services.TryAddSingleton(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddScoped(); + services.AddScoped(); + services.AddScoped(); + // ---------- End Altro ---------- + + return services; + } + + /// + /// Aggiunta repository/servizi specifici per STATS + /// + /// + /// + public static IServiceCollection AddStatsDataLayer(this IServiceCollection services) + { + services.AddSingleton(); + + services.AddSingleton(); + return services; + } + + /// + /// Aggiunta repository/servizi specifici per TAB + /// + /// + /// + public static IServiceCollection AddTabDataLayer(this IServiceCollection services) + { + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + + services.TryAddSingleton(); + + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddScoped(); + // aggiunta helper local/session storage service + services.TryAddScoped(); + services.TryAddScoped(); + return services; + } + + #endregion Public Methods } -} +} \ No newline at end of file diff --git a/MP.Data/DbModels/AlarmLogModel.cs b/MP.Data/DbModels/AlarmLogModel.cs index d7578850..59baf27f 100644 --- a/MP.Data/DbModels/AlarmLogModel.cs +++ b/MP.Data/DbModels/AlarmLogModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -16,6 +17,7 @@ namespace MP.Data.DbModels [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int AlarmLogId { get; set; } = 0; public DateTime DtRif { get; set; } = DateTime.Now; + [Precision(18, 6)] public decimal Duration { get; set; } = 0; public string MachineId { get; set; } = ""; public string MemAddress { get; set; } = ""; diff --git a/MP.Data/DbModels/DbSizeModel.cs b/MP.Data/DbModels/DbSizeModel.cs index 1704ae77..4606349f 100644 --- a/MP.Data/DbModels/DbSizeModel.cs +++ b/MP.Data/DbModels/DbSizeModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; namespace MP.Data.DbModels { @@ -6,6 +7,7 @@ namespace MP.Data.DbModels { [Key] public string DbName { get; set; } = ""; + [Precision(18, 6)] public decimal DbSizeMb { get; set; } = 0; public int NumTables { get; set; } = 0; public string BigTable { get; set; } = ""; diff --git a/MP.Data/DbModels/InsManualiModel.cs b/MP.Data/DbModels/InsManualiModel.cs index a692763d..a1e8e3c7 100644 --- a/MP.Data/DbModels/InsManualiModel.cs +++ b/MP.Data/DbModels/InsManualiModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -35,11 +36,13 @@ namespace MP.Data.DbModels /// /// Tempo Ciclo std /// + [Precision(18, 6)] public decimal TCiclo { get; set; } = 0; /// /// Minuti prodotti (da TC e pz prod /// + [Precision(18, 6)] public decimal MinProd { get; set; } = 0; /// @@ -50,7 +53,7 @@ namespace MP.Data.DbModels [NotMapped] public bool IsWork { - get => IdxTipoEv == 1; + get => IdxTipoEv == 1; } diff --git a/MP.Data/DbModels/ODLExpModel.cs b/MP.Data/DbModels/ODLExpModel.cs index 6c6d5b45..1517d9d8 100644 --- a/MP.Data/DbModels/ODLExpModel.cs +++ b/MP.Data/DbModels/ODLExpModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -19,7 +20,9 @@ namespace MP.Data.DbModels public string CodArticolo { get; set; } = ""; public string IdxMacchina { get; set; } public int NumPezzi { get; set; } + [Precision(18, 6)] public decimal Tcassegnato { get; set; } + [Precision(18, 6)] public decimal TCRichAttr { get; set; } public DateTime? DataInizio { get; set; } public DateTime? DataFine { get; set; } diff --git a/MP.Data/DbModels/ODLModel.cs b/MP.Data/DbModels/ODLModel.cs index caaf0845..0bfff032 100644 --- a/MP.Data/DbModels/ODLModel.cs +++ b/MP.Data/DbModels/ODLModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -21,6 +22,7 @@ namespace MP.Data.DbModels [MaxLength(50)] public string IdxMacchina { get; set; } public int NumPezzi { get; set; } + [Precision(18, 6)] public decimal Tcassegnato { get; set; } public DateTime? DataInizio { get; set; } public DateTime? DataFine { get; set; } diff --git a/MP.Data/DbModels/PODLExpModel.cs b/MP.Data/DbModels/PODLExpModel.cs index 05617844..7b8fecd0 100644 --- a/MP.Data/DbModels/PODLExpModel.cs +++ b/MP.Data/DbModels/PODLExpModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -28,6 +29,7 @@ namespace MP.Data.DbModels [MaxLength(50)] public string IdxMacchina { get; set; } public int NumPezzi { get; set; } = 1; + [Precision(18, 6)] public decimal Tcassegnato { get; set; } = 1; public DateTime? DueDate { get; set; } public int Priorita { get; set; } = 1; @@ -39,6 +41,8 @@ namespace MP.Data.DbModels public DateTime InsertDate { get; set; } = DateTime.Now; [MaxLength(500)] public string Recipe { get; set; } = ""; + public bool IsKitParent { get; set; } = false; + public bool IsKitChild { get; set; } = false; [NotMapped] public string CodFase @@ -66,7 +70,8 @@ namespace MP.Data.DbModels [NotMapped] public bool IsKit { - get => KeyRichiesta.StartsWith("KIT"); + get => IsKitParent || IsKitChild; // KeyRichiesta.StartsWith("KIT"); + //get => KeyRichiesta.StartsWith("KIT"); } /// @@ -74,6 +79,7 @@ namespace MP.Data.DbModels /// [ForeignKey("IdxMacchina")] public virtual MacchineModel MachineNav { get; set; } = null!; + /// /// Navigazione oggetto Articolo /// diff --git a/MP.Data/DbModels/PODLModel.cs b/MP.Data/DbModels/PODLModel.cs index 818c5235..66d79107 100644 --- a/MP.Data/DbModels/PODLModel.cs +++ b/MP.Data/DbModels/PODLModel.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.EntityFrameworkCore; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -29,6 +30,7 @@ namespace MP.Data.DbModels [MaxLength(50)] public string IdxMacchina { get; set; } public int NumPezzi { get; set; } = 1; + [Precision(18, 6)] public decimal Tcassegnato { get; set; } = 1; public DateTime? DueDate { get; set; } public int Priorita { get; set; } = 1; diff --git a/MP.Data/DbModels/TksScoreModel.cs b/MP.Data/DbModels/TksScoreModel.cs index d90efb2d..e541bf58 100644 --- a/MP.Data/DbModels/TksScoreModel.cs +++ b/MP.Data/DbModels/TksScoreModel.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; // // This is here so CodeMaid doesn't reorganize this document @@ -24,10 +25,12 @@ namespace MP.Data.DbModels /// /// Score Cicli Associati /// + [Precision(18, 6)] public decimal ChildScore { get; set; } = 0; /// /// Score complessivo /// + [Precision(18, 6)] public decimal TotalScore { get; set; } = 0; } diff --git a/MP.Data/MessagePipe.cs b/MP.Data/MessagePipe.cs index 1094cc72..e306f874 100644 --- a/MP.Data/MessagePipe.cs +++ b/MP.Data/MessagePipe.cs @@ -3,7 +3,7 @@ using StackExchange.Redis; using System; using System.Collections.Generic; using System.Diagnostics; -using System.Threading.Channels; +using System.Threading.Tasks; namespace MP.Data { @@ -44,17 +44,17 @@ namespace MP.Data /// /// Chiave REDIS x salvare valore /// Messaggio serializzato da inviare - public bool saveAndSendMessage(string memKey, string message) + public async Task SaveAndSendMessageAsync(string memKey, string message) { bool answ = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // invio notifica tramite il canale richiesto - answ = sendMessage(message); + answ = await SendMessageAsync(message); if (redisDb != null) { - redisDb.StringSetAsync(memKey, message); + await redisDb.StringSetAsync(memKey, message); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; @@ -68,7 +68,7 @@ namespace MP.Data } if (enableLog || numSent[memKey] > 30) { - Log.Info($"saveAndSendMessage| mKey {memKey} x {numSent[memKey]} | {message.Length} size | {ts.TotalMilliseconds} ms"); + Log.Info($"SaveAndSendMessageAsync| mKey {memKey} x {numSent[memKey]} | {message.Length} size | {ts.TotalMilliseconds} ms"); numSent[memKey] = 0; } @@ -80,7 +80,7 @@ namespace MP.Data /// /// /// - public bool sendMessage(string newMess) + public async Task SendMessageAsync(string newMess) { bool answ = false; if (!string.IsNullOrEmpty(_channel)) @@ -89,7 +89,7 @@ namespace MP.Data ISubscriber sub = redis.GetSubscriber(); sub.Publish(_channel, newMess); #endif - var numCli = redisSub.Publish(rChannel, newMess); + var numCli = await redisSub.PublishAsync(rChannel, newMess); answ = numCli > 0; } return answ; diff --git a/MP.Data/MoonProContext.cs b/MP.Data/MoonProContext.cs index 0d65c590..16fef1fa 100644 --- a/MP.Data/MoonProContext.cs +++ b/MP.Data/MoonProContext.cs @@ -1,8 +1,7 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; +using MP.Core.DTO; using MP.Data.DbModels; using MP.Data.DbModels.Anag; -using NLog; #nullable disable // @@ -12,27 +11,9 @@ namespace MP.Data { public partial class MoonProContext : DbContext { - #region Private Fields - - private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - - private IConfiguration _configuration; - - #endregion Private Fields #region Public Constructors - //public MoonProContext(IConfiguration configuration) - //{ - // _configuration = configuration; - //} - - //public MoonProContext(DbContextOptions options, IConfiguration configuration) - //: base(options) - //{ - // _configuration = configuration; - //} - public MoonProContext(DbContextOptions options) : base(options) { } @@ -41,6 +22,7 @@ namespace MP.Data #region Public Properties + public virtual DbSet DbSetCounter { get; set; } public virtual DbSet DbSetDbSize { get; set; } public virtual DbSet DbSetAlarmLog { get; set; } @@ -90,7 +72,6 @@ namespace MP.Data public virtual DbSet DbSetRegWithCheck { get; set; } public virtual DbSet DbSetSignalLog { get; set; } - public virtual DbSet DbSetStAct { get; set; } public virtual DbSet DbSetStActRow { get; set; } public virtual DbSet DbSetStAnagGruppi { get; set; } @@ -128,26 +109,8 @@ namespace MP.Data { if (!optionsBuilder.IsConfigured) { - string connString = _configuration.GetConnectionString("MP.Data"); - if (string.IsNullOrEmpty(connString)) - { - connString = _configuration.GetConnectionString("MP.All"); - } - if (string.IsNullOrEmpty(connString)) - { - connString = _configuration.GetConnectionString("MP.Land"); - } - if (string.IsNullOrEmpty(connString)) - { - connString = _configuration.GetConnectionString("MP.Mon"); - } - if (string.IsNullOrEmpty(connString)) - { - connString = _configuration.GetConnectionString("MP.STATS"); - } - - optionsBuilder.UseSqlServer(connString); - //optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro;Trusted_Connection=True;"); + // fallback si spera non necessario + optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro;Trusted_Connection=True;"); } } @@ -155,6 +118,10 @@ namespace MP.Data { modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS"); + + modelBuilder.Entity().HasNoKey(); + + modelBuilder.Entity(entity => { entity.HasKey(e => e.CodArticolo); diff --git a/MP.Data/MoonPro_FluxContext.cs b/MP.Data/MoonPro_FluxContext.cs index 117777b7..db5ae409 100644 --- a/MP.Data/MoonPro_FluxContext.cs +++ b/MP.Data/MoonPro_FluxContext.cs @@ -17,7 +17,9 @@ namespace MP.Data private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - private IConfiguration _configuration; +#if false + private IConfiguration _configuration; +#endif #endregion Private Fields @@ -27,15 +29,17 @@ namespace MP.Data /// Indispensabile x prima generazione migrations EFCore /// - [Obsolete("This constructor should never be used directly, and is only needed to generate entityframework stuff. Connection string can be adapted as pleased.")] + [Obsolete("This constructor should never be used directly, and is only needed to generate entityframework stuff. use DbContextoptions instead.")] public MoonPro_FluxContext() { } - +#if false + [Obsolete("This constructor should never be used directly, and is only needed to generate entityframework stuff. use DbContextoptions instead.")] public MoonPro_FluxContext(IConfiguration configuration) { _configuration = configuration; - } + } +#endif public MoonPro_FluxContext(DbContextOptions options) : base(options) { @@ -69,6 +73,7 @@ namespace MP.Data { if (!optionsBuilder.IsConfigured) { +#if false string connString = _configuration.GetConnectionString("MP.Flux"); if (!string.IsNullOrEmpty(connString)) { @@ -77,7 +82,9 @@ namespace MP.Data else { optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro_FluxData;Trusted_Connection=True;"); - } + } +#endif + optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro_FluxData;Trusted_Connection=True;"); } } diff --git a/MP.Data/MoonPro_STATSContext.cs b/MP.Data/MoonPro_STATSContext.cs index 11ba7efd..18b8ae1e 100644 --- a/MP.Data/MoonPro_STATSContext.cs +++ b/MP.Data/MoonPro_STATSContext.cs @@ -16,16 +16,20 @@ namespace MP.Data private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - private IConfiguration _configuration; +#if false + private IConfiguration _configuration; +#endif #endregion Private Fields #region Public Constructors +#if false public MoonPro_STATSContext(IConfiguration configuration) { _configuration = configuration; - } + } +#endif public MoonPro_STATSContext(DbContextOptions options) : base(options) { @@ -68,10 +72,7 @@ namespace MP.Data { if (!optionsBuilder.IsConfigured) { - string connString = _configuration.GetConnectionString("MP.Stats"); - - optionsBuilder.UseSqlServer(connString); - //optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro_STATS;Trusted_Connection=True;"); + optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro_STATS;Trusted_Connection=True;"); } } diff --git a/MP.Data/MoonPro_UtilsContext.cs b/MP.Data/MoonPro_UtilsContext.cs index edb248e1..a7c673e3 100644 --- a/MP.Data/MoonPro_UtilsContext.cs +++ b/MP.Data/MoonPro_UtilsContext.cs @@ -1,8 +1,6 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; using MP.Data.DbModels.Mtc; using MP.Data.DbModels.Utils; -using NLog; using System; #nullable disable @@ -13,14 +11,6 @@ namespace MP.Data { public partial class MoonPro_UtilsContext : DbContext { - #region Private Fields - - private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - - private IConfiguration _configuration; - - #endregion Private Fields - #region Public Constructors /// @@ -66,15 +56,8 @@ namespace MP.Data { if (!optionsBuilder.IsConfigured) { - string connString = _configuration.GetConnectionString("MP.Utils"); - if (!string.IsNullOrEmpty(connString)) - { - optionsBuilder.UseSqlServer(connString); - } - else - { - optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro_Utils;Trusted_Connection=True;"); - } + // fallback (si spera non necessario) + optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro_Utils;Trusted_Connection=True;"); } } diff --git a/MP.Data/MoonPro_VocContext.cs b/MP.Data/MoonPro_VocContext.cs index ca357a74..441d5e1b 100644 --- a/MP.Data/MoonPro_VocContext.cs +++ b/MP.Data/MoonPro_VocContext.cs @@ -1,7 +1,4 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.Extensions.Configuration; +using Microsoft.EntityFrameworkCore; using MP.Data.DbModels; using NLog; @@ -17,16 +14,16 @@ namespace MP.Data private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - private IConfiguration _configuration; + //private IConfiguration _configuration; #endregion Private Fields #region Public Constructors - public MoonPro_VocContext(IConfiguration configuration) - { - _configuration = configuration; - } + //public MoonPro_VocContext(IConfiguration configuration) + //{ + // _configuration = configuration; + //} public MoonPro_VocContext(DbContextOptions options) : base(options) { @@ -52,11 +49,16 @@ namespace MP.Data protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { + //if (!optionsBuilder.IsConfigured) + //{ + // string connString = _configuration.GetConnectionString("MP.Voc"); + + // optionsBuilder.UseSqlServer(connString); + //} if (!optionsBuilder.IsConfigured) { - string connString = _configuration.GetConnectionString("MP.Voc"); - - optionsBuilder.UseSqlServer(connString); + // fallback si spera non necessario + optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=MoonPro;Trusted_Connection=True;"); } } diff --git a/MP.Data/Repository/Anag/AnagRepository.cs b/MP.Data/Repository/Anag/AnagRepository.cs new file mode 100644 index 00000000..03721446 --- /dev/null +++ b/MP.Data/Repository/Anag/AnagRepository.cs @@ -0,0 +1,489 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using MP.Core.DTO; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Anag +{ + public class AnagRepository : BaseRepository, IAnagRepository + { + #region Public Constructors + + public AnagRepository(IDbContextFactory ctxFactory) : base(ctxFactory) + { + } + + #endregion Public Constructors + + #region Public Methods + + /// + public async Task AnagCountersGetNextAsync(string cntType) + { + AnagCountersModel answ = new AnagCountersModel(); + await using var dbCtx = await CreateContextAsync(); + bool outTable = true; + if (outTable) + { + var pCntType = new SqlParameter("@CntType", cntType); + var pLastNum = new SqlParameter + { + ParameterName = "@LastNum", + SqlDbType = SqlDbType.Int, + Direction = ParameterDirection.Output + }; + + var dbResult = await dbCtx + .DbSetAnagCount + .FromSqlRaw("EXEC dbo.stp_getNextNumb @CntType, @LastNum OUTPUT", pCntType, pLastNum) + .AsNoTracking() + .FirstOrDefaultAsync(); + if (dbResult != null) + { + answ = dbResult; + } + } + else + { + // se si volessero impiegare parametri OUTPUT (qui ne mancherebbe 1 nella stored x CntCode...) + var pCntType = new SqlParameter("@CntType", cntType); + var pLastNum = new SqlParameter + { + ParameterName = "@LastNum", + SqlDbType = SqlDbType.Int, + Direction = ParameterDirection.Output + }; + var pCntCode = new SqlParameter + { + ParameterName = "@CntCode", + SqlDbType = SqlDbType.NVarChar, + Direction = ParameterDirection.Output + }; + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC dbo.stp_getNextNumb @CntType, @LastNum OUTPUT, @CntCode OUTPUT", pCntType, pLastNum, pCntCode); + if (dbResult != 0) + { + answ.CntType = cntType; + answ.CntCode = $"{pCntCode.Value}"; + int lNum = 0; + int.TryParse($"{pLastNum.Value}", out lNum); + answ.LastNum = lNum; + } + } + return answ; + } + + /// + public async Task> AnagEventiGeneralAsync(string TableName = "EvList", string FieldName = "Common") + { + await using var dbCtx = await CreateContextAsync(); + var pTableName = new SqlParameter("@TableName", TableName); + var pFieldName = new SqlParameter("@FieldName", FieldName); + var dbResult = await dbCtx + .DbSetVSEB + .FromSqlRaw("exec dbo.stp_vseb_getGenerallyAvailable @TableName, @FieldName", pTableName, pFieldName) + .AsNoTracking() + .ToListAsync(); + return dbResult ?? new(); + } + + /// + public async Task> AnagGruppiAziendeAsync() + { + return await AnagGruppiGetTipoAsync("AZIENDA"); + } + + /// + public async Task AnagGruppiDeleteAsync(AnagGruppiModel updRec) + { + await using var dbCtx = await CreateContextAsync(); + var dbRec = await dbCtx + .DbSetAnagGruppi + .AsNoTracking() + .Where(x => x.CodGruppo == updRec.CodGruppo) + .FirstOrDefaultAsync(); + if (dbRec != null) + { + dbCtx.DbSetAnagGruppi.Remove(dbRec); + } + var numRes = await dbCtx.SaveChangesAsync(); + return numRes != 0; + } + + /// + public async Task> AnagGruppiFaseAsync() + { + return await AnagGruppiGetTipoAsync("FASE"); + } + + /// + public async Task> AnagGruppiGetTipoAsync(string tipoGruppo) + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx + .DbSetAnagGruppi + .Where(x => x.TipoGruppo == tipoGruppo) + .AsNoTracking() + .OrderBy(x => x.CodGruppo) + .ToListAsync(); + } + + /// + public async Task> AnagGruppiRepartoDtoAsync() + { + await using var dbCtx = await CreateContextAsync(); + var listReparti = await AnagGruppiGetTipoAsync("REPARTO"); + + var listMacc = await dbCtx + .DbSetGrp2Macc + .AsNoTracking() + .ToListAsync(); + var listOpr = await dbCtx + .DbSetGrp2Oper + .AsNoTracking() + .ToListAsync(); + + return listReparti + .Select(x => new RepartiDTO() + { + CodGruppo = x.CodGruppo, + TipoGruppo = x.TipoGruppo, + DescrGruppo = x.DescrGruppo, + SelEnabled = x.SelEnabled, + CountMacc = listMacc.Where(y => y.CodGruppo == x.CodGruppo).Select(y => y.IdxMacchina).Distinct().Count(), + CountOpr = listOpr.Where(y => y.CodGruppo == x.CodGruppo).Select(y => y.MatrOpr).Distinct().Count() + }) + .ToList(); + } + + /// + public async Task> GruppiRepartoDtoByOperAsync(int matrOpr) + { + await using var dbCtx = await CreateContextAsync(); + var listReparti = await AnagGruppiGetTipoAsync("REPARTO"); + + var listMacc = await dbCtx + .DbSetGrp2Macc + .AsNoTracking() + .ToListAsync(); + var listOpr = await dbCtx + .DbSetGrp2Oper + .AsNoTracking() + .ToListAsync(); + + var gruppiOpr = await dbCtx.DbSetGrp2Oper + .Where(x => x.MatrOpr == matrOpr) + .Select(x => x.CodGruppo) + .Distinct() + .ToListAsync(); + return listReparti + .Where(r => gruppiOpr.Contains(r.CodGruppo)) + .Select(x => new RepartiDTO() + { + CodGruppo = x.CodGruppo, + TipoGruppo = x.TipoGruppo, + DescrGruppo = x.DescrGruppo, + SelEnabled = x.SelEnabled, + CountMacc = listMacc.Where(y => y.CodGruppo == x.CodGruppo).Select(y => y.IdxMacchina).Distinct().Count(), + CountOpr = listOpr.Where(y => y.CodGruppo == x.CodGruppo).Select(y => y.MatrOpr).Distinct().Count() + }) + .ToList(); + } + + /// + public async Task AnagGruppiUpsertAsync(AnagGruppiModel updRec) + { + await using var dbCtx = await CreateContextAsync(); + var dbRec = await dbCtx + .DbSetAnagGruppi + .AsNoTracking() + .Where(x => x.CodGruppo == updRec.CodGruppo) + .FirstOrDefaultAsync(); + if (dbRec != null) + { + dbRec.DescrGruppo = updRec.DescrGruppo; + dbCtx.Entry(dbRec).State = EntityState.Modified; + } + else + { + await dbCtx.DbSetAnagGruppi.AddAsync(updRec); + } + var numRes = await dbCtx.SaveChangesAsync(); + return numRes != 0; + } + + /// + public async Task> AnagStatiCommAsync() + { + return await ListValuesFiltAsync("PODL", "StatoComm"); + } + + /// + public async Task> AnagTipoArtLvAsync() + { + return await ListValuesFiltAsync("AnagArticoli", "Tipo"); + } + + /// + public async Task ArticoliCountAsync() + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetArticoli.CountAsync(); + } + + /// + public async Task ArticoliCountSearchAsync(string tipoArt = "*", string azienda = "*", string searchVal = "") + { + await using var dbCtx = await CreateContextAsync(); + IQueryable query = dbCtx.DbSetArticoli.AsNoTracking(); + + if (tipoArt != "*") + { + query = query.Where(x => EF.Functions.Like(x.Tipo, tipoArt)); + } + if (azienda != "*") + { + query = query.Where(x => EF.Functions.Like(x.Azienda, azienda)); + } + if (!string.IsNullOrWhiteSpace(searchVal)) + { + string pattern = $"%{searchVal}%"; + query = query.Where(x => + EF.Functions.Like(x.CodArticolo, pattern) || + EF.Functions.Like(x.DescArticolo, pattern) || + EF.Functions.Like(x.Disegno, pattern)); + } + + return await query.OrderBy(x => x.CodArticolo).CountAsync(); + } + + /// + public async Task ArticoliCountUsedAsync() + { + await using var dbCtx = await CreateContextAsync(); + var result = await dbCtx + .DbSetCounter + .FromSqlRaw("EXEC stp_ART_CountUsed") + .AsNoTracking() + .ToListAsync(); + + return result.FirstOrDefault()?.NumCount ?? 0; + } + + /// + public async Task ArticoliDeleteRecordAsync(AnagArticoliModel currRec) + { + await using var dbCtx = await CreateContextAsync(); + var currVal = await dbCtx + .DbSetArticoli + .Where(x => x.CodArticolo == currRec.CodArticolo) + .FirstOrDefaultAsync(); + if (currVal != null) + { + dbCtx.DbSetArticoli.Remove(currVal); + return await dbCtx.SaveChangesAsync() > 0; + } + return false; + } + + /// + public async Task> ArticoliGetByTipoAsync(string tipo, string azienda = "*") + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx + .DbSetArticoli + .AsNoTracking() + .Where(x => x.Tipo.ToUpper() == tipo.ToUpper() && (azienda == "*" || x.Azienda.ToUpper() == azienda.ToUpper())) + .OrderBy(x => x.CodArticolo) + .ToListAsync(); + } + + /// + public async Task> ArticoliGetSearchAsync(int numRecord, string tipoArt = "*", string azienda = "*", string searchVal = "") + { + await using var dbCtx = await CreateContextAsync(); + IQueryable query = dbCtx.DbSetArticoli.AsNoTracking(); + + if (tipoArt != "*") + { + query = query.Where(x => EF.Functions.Like(x.Tipo, tipoArt)); + } + if (azienda != "*") + { + query = query.Where(x => EF.Functions.Like(x.Azienda, azienda)); + } + if (!string.IsNullOrWhiteSpace(searchVal)) + { + string pattern = $"%{searchVal}%"; + query = query.Where(x => + EF.Functions.Like(x.CodArticolo, pattern) || + EF.Functions.Like(x.DescArticolo, pattern) || + EF.Functions.Like(x.Disegno, pattern)); + } + + return await query.OrderBy(x => x.CodArticolo).Take(numRecord).ToListAsync(); + } + + /// + public async Task> ArticoliGetUnusedAsync() + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetArticoli.FromSqlRaw("EXEC stp_ART_getNotUsed").AsNoTracking().ToListAsync(); + } + + /// + public async Task> ArticoliGetUsedAsync() + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetArticoli.FromSqlRaw("EXEC stp_ART_getUsed").AsNoTracking().ToListAsync(); + } + + /// + public async Task> ArticoliInKitAsync() + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetArticoli.FromSqlRaw("EXEC stp_TempKIT_getArtChild").AsNoTracking().ToListAsync(); + } + + /// + public async Task ArticoliUpdateRecord(AnagArticoliModel editRec) + { + await using var dbCtx = await CreateContextAsync(); + var currRec = await dbCtx.DbSetArticoli.FirstOrDefaultAsync(x => x.CodArticolo == editRec.CodArticolo); + if (currRec != null) + { + currRec.Disegno = editRec.Disegno; + currRec.DescArticolo = editRec.DescArticolo; + currRec.Tipo = editRec.Tipo; + currRec.Azienda = editRec.Azienda; + dbCtx.Entry(currRec).State = EntityState.Modified; + return await dbCtx.SaveChangesAsync() > 0; + } + return false; + } + + /// + public async Task> ListValuesFiltAsync(string tabName, string fieldName) + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetListValues + .Where(x => x.TableName == tabName && x.FieldName == fieldName) + .AsNoTracking() + .OrderBy(x => x.ordinal) + .ToListAsync(); + } + + /// + public async Task> MacchineByMatrOperAsync(int MatrOpr) + { + await using var dbCtx = await CreateContextAsync(); + if (MatrOpr == 0) + { + return await dbCtx.DbSetMacchine.AsNoTracking().OrderBy(x => x.IdxMacchina).ToListAsync(); + } + else + { + return await dbCtx.DbSetGrp2Oper + .Where(g => g.MatrOpr == MatrOpr) + .Join(dbCtx.DbSetGrp2Macc, g => g.CodGruppo, m => m.CodGruppo, (g, m) => m) + .Distinct() + .Join(dbCtx.DbSetMacchine, g => g.IdxMacchina, m => m.IdxMacchina, (g, m) => m) + .Distinct() + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + } + + /// + public async Task> MacchineGetFiltAsync(string codGruppo) + { + await using var dbCtx = await CreateContextAsync(); + if (codGruppo == "*") + { + return await dbCtx.DbSetMacchine.AsNoTracking().OrderBy(x => x.IdxMacchina).ToListAsync(); + } + else + { + return await dbCtx.DbSetGrp2Macc + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbSetMacchine, g => g.IdxMacchina, m => m.IdxMacchina, (g, m) => m) + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + } + + /// + public async Task> OperatoriGetFiltAsync(string codGruppo) + { + List dbResult = new List(); + await using var dbCtx = await CreateContextAsync(); + if (codGruppo == "*") + { + dbResult = await dbCtx + .DbOperatori + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToListAsync(); + } + else + { + dbResult = await dbCtx + .DbSetGrp2Oper + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbOperatori, + g => g.MatrOpr, + m => m.MatrOpr, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToListAsync(); + } + return dbResult; + } + + /// + public async Task> PODL_getDictOdlPodlAsync(List missingIds) + { + if (missingIds == null || !missingIds.Any()) + return new Dictionary(); + + await using var dbCtx = await CreateContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => missingIds.Contains(x.IdxOdl)) + .ToDictionaryAsync(x => x.IdxOdl, x => x.IdxPromessa); + } + + /// + /// Recupero dizionario traduzioni + /// + /// Codice lingua + /// Dizionario di traduzioni + public Dictionary VocabolarioGetLang(string lingua) + { + using var dbCtx = _ctxFactory.CreateDbContextAsync().GetAwaiter().GetResult(); + var rawList = dbCtx + .DbSetVocabolario + .AsNoTracking() + .Where(x => x.Lingua.ToLower() == lingua.ToLower()) + .OrderBy(x => x.Lemma) + .ToList(); + // Proietto in dizionario + return rawList + .DistinctBy(t => t.Lemma, StringComparer.OrdinalIgnoreCase) + .ToDictionary(t => t.Lemma, t => t.Traduzione, StringComparer.OrdinalIgnoreCase); + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/MP.Data/Repository/Anag/BaseRepository.cs b/MP.Data/Repository/Anag/BaseRepository.cs new file mode 100644 index 00000000..bc26dc68 --- /dev/null +++ b/MP.Data/Repository/Anag/BaseRepository.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Anag +{ + public abstract class BaseRepository : IBaseRepository + { + #region Protected Fields + + protected readonly IDbContextFactory _ctxFactory; + + #endregion Protected Fields + + #region Protected Constructors + + protected BaseRepository(IDbContextFactory ctxFactory) => _ctxFactory = ctxFactory; + + #endregion Protected Constructors + + #region Protected Methods + + /// + /// Creazione dbcontext per singola transazione + /// + /// + protected async Task CreateContextAsync() => await _ctxFactory.CreateDbContextAsync(); + + #endregion Protected Methods + + } +} \ No newline at end of file diff --git a/MP.Data/Repository/Anag/IAnagRepository.cs b/MP.Data/Repository/Anag/IAnagRepository.cs new file mode 100644 index 00000000..728a4657 --- /dev/null +++ b/MP.Data/Repository/Anag/IAnagRepository.cs @@ -0,0 +1,208 @@ +using MP.Core.DTO; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Anag +{ + public interface IAnagRepository + { + #region Public Methods + + /// + /// Stacca un nuovo counter x il tipo richiesto + /// + /// Tipo di contatore + /// Modello del contatore aggiornato + Task AnagCountersGetNextAsync(string cntType); + + /// + /// Restituisce l'anagrafica EVENTI generalmente disponibile per OGNI macchina + /// + /// Nome Table x filtro (std: EvList) + /// Nome Field x filtro (std: Common) + /// Lista di eventi generali + Task> AnagEventiGeneralAsync(string TableName = "EvList", string FieldName = "Common"); + + /// + /// Elenco Gruppi tipo Azienda + /// + /// Lista di modelli anagrafica gruppi + Task> AnagGruppiAziendeAsync(); + + /// + /// Delete record AnagraficaGruppi + /// + /// Record da eliminare + /// True se l'eliminazione � avvenuta + Task AnagGruppiDeleteAsync(AnagGruppiModel updRec); + + /// + /// Elenco Gruppi tipo Fasi + /// + /// Lista di modelli anagrafica gruppi + Task> AnagGruppiFaseAsync(); + + /// + /// Gruppi x tipo modalit� Async + /// + /// Tipo di gruppo (es. REPARTO, FASE, AZIENDA) + /// Lista di modelli anagrafica gruppi + Task> AnagGruppiGetTipoAsync(string tipoGruppo); + + /// + /// Elenco Gruppi tipo REPARTO (x associazione Macchine-Operatori) in formato DTO con conteggi del numero record trovati + /// + /// Lista di DTO reparti con conteggio macchine e operatori + Task> AnagGruppiRepartoDtoAsync(); + + /// + /// Upsert record AnagraficaGruppi (solo codice/descrizione) + /// + /// Record da inserire o aggiornare + /// True se l'operazione � riuscita + Task AnagGruppiUpsertAsync(AnagGruppiModel updRec); + + /// + /// Elenco valori ammessi x Stati commessa (es Yacht Baglietto) + /// + /// Lista di valori ammessi + Task> AnagStatiCommAsync(); + + /// + /// Elenco valori ammessi x Tipo articoli + /// + /// Lista di valori ammessi + Task> AnagTipoArtLvAsync(); + + /// + /// Conteggio num articoli Async + /// + /// Conteggio totale articoli + Task ArticoliCountAsync(); + + /// + /// Conteggio articoli data condizione ricerca + /// + /// Tipo articolo + /// Azienda + /// Valore di ricerca + /// Conteggio risultati ricerca + Task ArticoliCountSearchAsync(string tipoArt = "*", string azienda = "*", string searchVal = ""); + + /// + /// Conteggio articoli IMPIEGATI (da stored stp_ART_getUsed) Async + /// + /// Conteggio articoli impiegati + Task ArticoliCountUsedAsync(); + + /// + /// Eliminazione Record Articolo + /// + /// Record da eliminare + /// True se eliminato + Task ArticoliDeleteRecordAsync(AnagArticoliModel currRec); + + /// + /// Restituisce elenco articoli dato tipo (es KIT) + /// + /// Tipo articolo (es. KIT) + /// Azienda (opzionale) + /// Lista di articoli per tipo + Task> ArticoliGetByTipoAsync(string tipo, string azienda = "*"); + + /// + /// Elenco tabella Articoli da filtro + /// + /// Numero massimo di record + /// Tipo articolo + /// Azienda + /// Valore di ricerca + /// Lista di articoli cercati + Task> ArticoliGetSearchAsync(int numRecord, string tipoArt = "*", string azienda = "*", string searchVal = ""); + + /// + /// Elenco tabella Articoli NON IMPIEGATI (da stored stp_ART_getNotUsed) Async + /// + /// Lista di articoli non impiegati + Task> ArticoliGetUnusedAsync(); + + /// + /// Elenco tabella Articoli IMPIEGATI (da stored stp_ART_getUsed) Async + /// + /// Lista di articoli non impiegati + Task> ArticoliGetUsedAsync(); + + /// + /// Dizionario associazione ODL/PODL + /// + /// Lista di articoli in kit + Task> ArticoliInKitAsync(); + + /// + /// Update Record Articolo + /// + /// Record da aggiornare + /// True se aggiornato + Task ArticoliUpdateRecord(AnagArticoliModel editRec); + + /// + /// Elenco Gruppi tipo REPARTOin formato DTO con conteggi del numero record trovati filtrati per operatore + /// + /// Lista di DTO reparti con conteggio macchine e operatori + Task> GruppiRepartoDtoByOperAsync(int matrOpr); + +#if false + /// + /// Elenco codice articoli che abbiano dati Dossier + /// + /// Lista di codici articolo + Task> ArticleWithDossierAsync(); +#endif + + /// + /// Elenco valori ammessi x tabella/colonna Async + /// + /// Nome tabella + /// Nome colonna + /// Lista di valori ammessi + Task> ListValuesFiltAsync(string tabName, string fieldName); + + /// + /// Elenco Macchine dato operatore secondo gruppi (macchine/operatore) + /// + /// Matricola operatore + /// Lista di macchine + Task> MacchineByMatrOperAsync(int MatrOpr); + + /// + /// Elenco da tabella Macchine filtro x gruppo + /// + /// Codice gruppo + /// Lista di macchine + Task> MacchineGetFiltAsync(string codGruppo); + + /// + /// Elenco operatori dato filtro gruppo + /// + /// Codice gruppo + /// Lista di operatori + Task> OperatoriGetFiltAsync(string codGruppo); + + /// + /// Dizionario associazione ODL/PODL + /// + /// Lista di ID mancanti + /// Dizionario di associazione + Task> PODL_getDictOdlPodlAsync(List missingIds); + + /// + /// Recupero dizionario traduzioni + /// + /// Codice lingua + /// Dizionario di traduzioni + Dictionary VocabolarioGetLang(string lingua); + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/MP.Data/Repository/Anag/IBaseRepository.cs b/MP.Data/Repository/Anag/IBaseRepository.cs new file mode 100644 index 00000000..246d20f6 --- /dev/null +++ b/MP.Data/Repository/Anag/IBaseRepository.cs @@ -0,0 +1,8 @@ +namespace MP.Data.Repository.Anag +{ + public interface IBaseRepository + { + //Task CreateContextAsync(); + //Task SaveChangesAsync(DataLayerContext ctx); + } +} diff --git a/MP.Data/Repository/Dossier/DossierRepository.cs b/MP.Data/Repository/Dossier/DossierRepository.cs new file mode 100644 index 00000000..f882df25 --- /dev/null +++ b/MP.Data/Repository/Dossier/DossierRepository.cs @@ -0,0 +1,130 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Dossier +{ + public class DossierRepository : IDossierRepository + { + #region Public Constructors + + public DossierRepository( + IConfiguration configuration, + IDbContextFactory ctxFactoryFL) + { + _configuration = configuration; + _ctxFactoryFL = ctxFactoryFL; + } + + #endregion Public Constructors + + #region Public Methods + + /// + public async Task> ArticleWithDossierAsync() + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetDossiers + .AsNoTracking() + .Select(i => i.CodArticolo) + .Distinct() + .ToListAsync(); + } + + /// + public async Task DossiersDeleteRecordAsync(DossierModel currRec) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + var currVal = await dbCtx + .DbSetDossiers + .Where(x => x.IdxDossier == currRec.IdxDossier) + .FirstOrDefaultAsync(); + dbCtx + .DbSetDossiers + .Remove(currVal); + + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task> DossiersGetLastFiltAsync(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetDossiers + .AsNoTracking() + .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodArticolo == "*" || x.CodArticolo == CodArticolo) && (x.DtRif >= DtStart && x.DtRif <= DtEnd)) + .Include(m => m.MachineNav) + .Include(a => a.ArticoloNav) + .OrderByDescending(x => x.DtRif) + .Take(MaxRec) + .ToListAsync(); + } + + /// + public async Task DossiersInsertAsync(DossierModel newRec) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + await dbCtx + .DbSetDossiers + .AddAsync(newRec); + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task DossiersTakeParamsSnapshotLastAsync(string idxMacchina, DateTime dtMin, DateTime dtMax) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); + var pDtMin = new SqlParameter("@DtMin", dtMin); + var pDtMax = new SqlParameter("@DtMax", dtMax); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_FL_TakeSnapshotLast @IdxMacchina,@DtMin,@DtMax", pIdxMacchina, pDtMin, pDtMax); + return dbResult != 0; + } + + /// + public async Task DossiersUpdateValoreAsync(DossierModel editRec) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + var currRec = await dbCtx + .DbSetDossiers + .Where(x => x.IdxDossier == editRec.IdxDossier) + .FirstOrDefaultAsync(); + if (currRec != null) + { + currRec.Valore = editRec.Valore; + dbCtx.Entry(currRec).State = EntityState.Modified; + } + else + { + await dbCtx + .DbSetDossiers + .AddAsync(editRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + #endregion Public Methods + + #region Protected Fields + + protected readonly IDbContextFactory _ctxFactoryFL; + + #endregion Protected Fields + + #region Private Fields + + private readonly IConfiguration _configuration; + + #endregion Private Fields + } +} \ No newline at end of file diff --git a/MP.Data/Repository/Dossier/IDossierRepository.cs b/MP.Data/Repository/Dossier/IDossierRepository.cs new file mode 100644 index 00000000..73164af9 --- /dev/null +++ b/MP.Data/Repository/Dossier/IDossierRepository.cs @@ -0,0 +1,26 @@ +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Dossier +{ + public interface IDossierRepository + { + #region Public Methods + + Task DossiersDeleteRecordAsync(DossierModel currRec); + + Task> DossiersGetLastFiltAsync(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec); + + Task DossiersInsertAsync(DossierModel newRec); + + Task DossiersTakeParamsSnapshotLastAsync(string idxMacchina, DateTime dtMin, DateTime dtMax); + + Task DossiersUpdateValoreAsync(DossierModel editRec); + + Task> ArticleWithDossierAsync(); + + #endregion + } +} diff --git a/MP.Data/Repository/FluxLog/FluxLogRepository.cs b/MP.Data/Repository/FluxLog/FluxLogRepository.cs new file mode 100644 index 00000000..e0b2bdf4 --- /dev/null +++ b/MP.Data/Repository/FluxLog/FluxLogRepository.cs @@ -0,0 +1,185 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Core.DTO; +using MP.Core.Objects; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using static EgwCoreLib.Utils.DtUtils; + +namespace MP.Data.Repository.FluxLog +{ + public class FluxLogRepository : IFluxLogRepository + { + #region Public Constructors + + public FluxLogRepository(IConfiguration configuration, IDbContextFactory ctxFactoryFL) + { + _configuration = configuration; + _ctxFactoryFL = ctxFactoryFL; + } + + #endregion Public Constructors + + #region Public Methods + + /// + public async Task> FluxLogDataReduxAsync(string idxMaccSel, List fluxList, Periodo currPeriodo, Enums.ValSelection valMode, Enums.DataInterval intReq, int maxItem) + { + List procStats = new List(); + Log.Info($"Inizio FluxLogDataReduxAsync | idxMaccSel: {idxMaccSel} | periodo: {currPeriodo.Inizio:yyyy-MM-dd} --> {currPeriodo.Fine:yyyy-MM-dd}"); + TimeSpan step = TimeSpan.FromHours(1); + switch (intReq) + { + case Enums.DataInterval.minute: + step = TimeSpan.FromMinutes(1.00 / maxItem); + break; + + case Enums.DataInterval.hour: + step = TimeSpan.FromHours(1.00 / maxItem); + break; + + case Enums.DataInterval.day: + step = TimeSpan.FromDays(1.00 / maxItem); + break; + + default: + break; + } + + var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMaccSel); + var pOnlyTest = new SqlParameter("@OnlyTest", false); + + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + foreach (var item in fluxList) + { + Log.Info($"FluxLogDataReduxAsync | Flux: {item}"); + int numRecProc = 0; + Stopwatch sw = new Stopwatch(); + sw.Start(); + var pCodFlux = new SqlParameter("@CodFlux", item); + DateTime dtCursStart = currPeriodo.Inizio; + DateTime dtCursEnd = dtCursStart.Add(step); + bool setCompleted = false; + while (!setCompleted) + { + var currFlux = await dbCtx + .DbSetFluxLog + .Where(x => (x.CodFlux == item) && (x.dtEvento >= dtCursStart && x.dtEvento < dtCursEnd) && (x.IdxMacchina == idxMaccSel)) + .ToListAsync(); + + int numRec = currFlux.Count; + numRecProc += numRec; + if (numRec > maxItem) + { + List listPeriodi = new List(); + + switch (valMode) + { + case Enums.ValSelection.First: + var recStart = currFlux.Skip(1).FirstOrDefault(); + listPeriodi.Add(new Periodo(recStart.dtEvento, dtCursEnd)); + break; + + case Enums.ValSelection.Last: + var recEnd = currFlux.LastOrDefault(); + listPeriodi.Add(new Periodo(dtCursStart, recEnd.dtEvento)); + break; + + case Enums.ValSelection.Center: + int idx = 1; + var recCent = currFlux.Skip(idx / (maxItem + 1)).FirstOrDefault(); + listPeriodi.Add(new Periodo(dtCursStart, recCent.dtEvento)); + if (maxItem > 1) + { + for (int i = 2; i < maxItem; i++) + { + DateTime dtInizio = recCent.dtEvento; + recCent = currFlux.Skip(i / (maxItem + 1)).FirstOrDefault(); + listPeriodi.Add(new Periodo(dtInizio, recCent.dtEvento)); + } + } + listPeriodi.Add(new Periodo(recCent.dtEvento.AddSeconds(1), dtCursEnd)); + break; + + default: + break; + } + + foreach (var slot in listPeriodi) + { + var pDtStart = new SqlParameter("@DtStart", slot.Inizio); + var pDtEnd = new SqlParameter("@DtEnd", slot.Fine); + await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC man.stp_ReduceFluxLog @IdxMacchina, @CodFlux, @DtStart, @DtEnd, @OnlyTest", pIdxMacchina, pCodFlux, pDtStart, pDtEnd, pOnlyTest); + } + } + + dtCursStart = dtCursEnd; + dtCursEnd = dtCursStart.Add(step); + setCompleted = dtCursStart >= currPeriodo.Fine; + } + sw.Stop(); + StatDedupDTO currStat = new StatDedupDTO() + { + IdxMacchina = idxMaccSel, + CodFlux = item, + Interval = intReq, + Num4Int = maxItem, + NumRec = numRecProc, + ProcTime = sw.Elapsed.TotalSeconds + }; + procStats.Add(currStat); + } + Log.Info($"FINE FluxLogDataReduxAsync | idxMaccSel: {idxMaccSel} | periodo: {currPeriodo.Inizio:yyyy-MM-dd} --> {currPeriodo.Fine:yyyy-MM-dd}"); + return procStats; + } + + /// + public async Task> FluxLogGetLastFiltAsync(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => (x.dtEvento >= DtMin && x.dtEvento <= DtMax) && (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodFlux == "*" || x.CodFlux == CodFlux)) + .OrderByDescending(x => x.dtEvento) + .Take(MaxRec) + .ToListAsync() ?? new(); + } + + /// + public async Task> FluxLogParetoAsync(string idxMacchina, DateTime dtFrom, DateTime dtTo) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetFluxLog + .Where(x => (string.IsNullOrEmpty(idxMacchina) || x.IdxMacchina == idxMacchina) && (dtFrom <= x.dtEvento && x.dtEvento <= dtTo)) + .AsNoTracking() + .GroupBy(x => x.CodFlux) + .Select(g => new ParetoFluxLogDTO() { IdxMacchina = idxMacchina, CodFlux = g.Key, Qty = g.Count() }) + .OrderByDescending(x => x.Qty) + .ToListAsync() ?? new(); + } + + #endregion Public Methods + + #region Protected Fields + + protected readonly IDbContextFactory _ctxFactoryFL; + + #endregion Protected Fields + + #region Private Fields + + private static NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + private readonly IConfiguration _configuration; + + #endregion Private Fields + } +} \ No newline at end of file diff --git a/MP.Data/Repository/FluxLog/IFluxLogRepository.cs b/MP.Data/Repository/FluxLog/IFluxLogRepository.cs new file mode 100644 index 00000000..c30d4839 --- /dev/null +++ b/MP.Data/Repository/FluxLog/IFluxLogRepository.cs @@ -0,0 +1,19 @@ +using MP.Core.DTO; +using MP.Core.Objects; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using static EgwCoreLib.Utils.DtUtils; + +namespace MP.Data.Repository.FluxLog +{ + public interface IFluxLogRepository + { + Task> FluxLogDataReduxAsync(string idxMaccSel, List fluxList, Periodo currPeriodo, Enums.ValSelection valMode, Enums.DataInterval intReq, int maxItem); + + Task> FluxLogGetLastFiltAsync(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec); + + Task> FluxLogParetoAsync(string idxMacchina, DateTime dtFrom, DateTime dtTo); + } +} diff --git a/MP.Data/Repository/IOC/BaseRepository.cs b/MP.Data/Repository/IOC/BaseRepository.cs index 7814ee85..50877a21 100644 --- a/MP.Data/Repository/IOC/BaseRepository.cs +++ b/MP.Data/Repository/IOC/BaseRepository.cs @@ -13,8 +13,7 @@ namespace MP.Data.Repository.IOC #region Protected Constructors - protected BaseRepository(IDbContextFactory ctxFactory) - => _ctxFactory = ctxFactory; + protected BaseRepository(IDbContextFactory ctxFactory) => _ctxFactory = ctxFactory; #endregion Protected Constructors @@ -24,24 +23,8 @@ namespace MP.Data.Repository.IOC /// Creazione dbcontext per singola transazione /// /// - protected async Task CreateContextAsync() - => await _ctxFactory.CreateDbContextAsync(); + protected async Task CreateContextAsync() => await _ctxFactory.CreateDbContextAsync(); #endregion Protected Methods - -#if false - /// - /// Salvataggio dati asincrono - /// - /// - protected async Task SaveChangesAsync(DataLayerContext ctx) - => await ctx.SaveChangesAsync() > 0; -#endif - -#if false - protected readonly DataLayerContext _dbCtx; - protected BaseRepository(DataLayerContext db) => _dbCtx = db; - public async Task SaveChangesAsync() => await _dbCtx.SaveChangesAsync() > 0; -#endif } } \ No newline at end of file diff --git a/MP.Data/Repository/MpLand/IMpLandRepository.cs b/MP.Data/Repository/MpLand/IMpLandRepository.cs new file mode 100644 index 00000000..a807f751 --- /dev/null +++ b/MP.Data/Repository/MpLand/IMpLandRepository.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpLand +{ + public interface IMpLandRepository + { + Task> AllDbInfoAsync(); + + Task> ConfigGetAllAsync(); + + Task> RemRebootLogGetAllAsync(); + + Task> RemRebootLogGetLastAsync(); + + Task> RemRebootLogGetLastNoMaccAsync(); + + Task> MacchineGetAllAsync(); + } +} diff --git a/MP.Data/Repository/MpLand/MpLandRepository.cs b/MP.Data/Repository/MpLand/MpLandRepository.cs new file mode 100644 index 00000000..3eb4f9d8 --- /dev/null +++ b/MP.Data/Repository/MpLand/MpLandRepository.cs @@ -0,0 +1,173 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpLand +{ + public class MpLandRepository : IMpLandRepository + { + #region Private Fields + + private readonly IConfiguration _configuration; + private readonly IDbContextFactory _ctxFactory; + private readonly IDbContextFactory _ctxFactoryFluxLog; + private readonly IDbContextFactory _ctxFactoryStats; + + #endregion + + #region Public Constructors + + public MpLandRepository( + IConfiguration configuration, + IDbContextFactory ctxFactory, + IDbContextFactory ctxFactoryFL, + IDbContextFactory ctxFactorySta) + { + _configuration = configuration; + _ctxFactory = ctxFactory; + _ctxFactoryFluxLog = ctxFactoryFL; + _ctxFactoryStats= ctxFactorySta; + } + + #endregion + + #region Public Methods + + /// + public async Task> AllDbInfoAsync() + { + List dbResult = new List(); + string stp_DbInfo = @" + ;WITH TableRowCounts AS ( + SELECT + t.name AS TableName, + SUM(p.rows) AS RowNum + FROM sys.tables t + JOIN sys.partitions p ON t.object_id = p.object_id + WHERE p.index_id IN (0, 1) + GROUP BY t.name + ), + LargestTable AS ( + SELECT TOP 1 RowNum, TableName + FROM TableRowCounts + ORDER BY RowNum DESC + ) + SELECT + DB_name() as DbName, + CAST(SUM(size) * 8.0 / 1024 AS DECIMAL(18,2)) AS DbSizeMb, + (SELECT COUNT(*) FROM sys.tables) AS NumTables, + (SELECT TableName FROM LargestTable) AS BigTable, + (SELECT RowNum FROM LargestTable) AS BigTableRows + FROM sys.master_files + WHERE database_id = DB_ID(); + "; + try + { + if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.All"))) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var singleRes = dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsNoTracking() + .AsEnumerable() + .FirstOrDefault(); + if (singleRes != null) + { + dbResult.Add(singleRes); + } + } + if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.Flux"))) + { + await using var dbCtx = await _ctxFactoryFluxLog.CreateDbContextAsync(); + var singleRes = dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsNoTracking() + .AsEnumerable() + .FirstOrDefault(); + if (singleRes != null) + { + dbResult.Add(singleRes); + } + } + if (!string.IsNullOrEmpty(_configuration.GetConnectionString("MP.Stats"))) + { + await using var dbCtx = await _ctxFactoryStats.CreateDbContextAsync(); + var singleRes = dbCtx + .DbSetDbSize + .FromSqlRaw(stp_DbInfo) + .AsNoTracking() + .AsEnumerable() + .FirstOrDefault(); + if (singleRes != null) + { + dbResult.Add(singleRes); + } + } + } + catch + { + } + return dbResult; + } + + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + public async Task> MacchineGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetMacchine + .ToListAsync() ?? new(); + } + + /// + public async Task> RemRebootLogGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetRemRebLog + .AsNoTracking() + .OrderByDescending(x => x.IdxReboot) + .ToListAsync() ?? new(); + } + + /// + public async Task> RemRebootLogGetLastAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetRemRebLog + .FromSqlRaw("EXEC stp_RRL_getLast") + .AsNoTracking() + .ToListAsync() ?? new(); + } + + /// + public async Task> RemRebootLogGetLastNoMaccAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetRemRebLog + .FromSqlRaw("EXEC stp_RRL_GetLastNoMachine") + .AsNoTracking() + .ToListAsync() ?? new(); + } + + #endregion + } +} diff --git a/MP.Data/Repository/MpMon/IMpMonRepository.cs b/MP.Data/Repository/MpMon/IMpMonRepository.cs new file mode 100644 index 00000000..7ddc32e9 --- /dev/null +++ b/MP.Data/Repository/MpMon/IMpMonRepository.cs @@ -0,0 +1,20 @@ +using Microsoft.Data.SqlClient; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpMon +{ + public interface IMpMonRepository + { + Task> ConfigGetAllAsync(); + + Task> MacchineGetAllAsync(); + + Task> MacchineGetFiltAsync(string codGruppo); + + Task> MseGetAllAsync(int maxAge = 2000); + } +} diff --git a/MP.Data/Repository/MpMon/MpMonRepository.cs b/MP.Data/Repository/MpMon/MpMonRepository.cs new file mode 100644 index 00000000..235977b3 --- /dev/null +++ b/MP.Data/Repository/MpMon/MpMonRepository.cs @@ -0,0 +1,100 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpMon +{ + public class MpMonRepository : IMpMonRepository + { + #region Private Fields + + private readonly IDbContextFactory _ctxFactory; + + #endregion + + #region Public Constructors + + public MpMonRepository(IDbContextFactory ctxFactory) + { + _ctxFactory = ctxFactory; + } + + #endregion + + #region Public Methods + + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + public async Task> MacchineGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync() ?? new(); + } + + /// + public async Task> MacchineGetFiltAsync(string codGruppo) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + List dbResult; + if (codGruppo == "*") + { + dbResult = await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + else + { + dbResult = await dbCtx + .DbSetGrp2Macc + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbSetMacchine, + g => g.IdxMacchina, + m => m.IdxMacchina, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + dbResult = dbResult + .Where(x => !string.IsNullOrEmpty(x.locazione)) + .OrderBy(x => x.locazione).ToList(); + return dbResult; + } + + /// + public async Task> MseGetAllAsync(int maxAge = 2000) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); + var dbResult = await dbCtx + .DbSetMSE + .FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec) + .AsNoTracking() + .ToListAsync(); + return dbResult; + } + + #endregion + } +} diff --git a/MP.Data/Repository/MpVoc/IMpVocRepository.cs b/MP.Data/Repository/MpVoc/IMpVocRepository.cs new file mode 100644 index 00000000..733574c1 --- /dev/null +++ b/MP.Data/Repository/MpVoc/IMpVocRepository.cs @@ -0,0 +1,40 @@ +using MP.Data.DbModels; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpVoc +{ + public interface IMpVocRepository + { + #region Public Methods + +#if false + /// + /// Recupero elenco config + /// + /// + Task> ConfigGetAllAsync(); +#endif + + /// + /// recupero elenco lingue + /// + /// + Task> LingueGetAllAsync(); + + /// + /// Recupero tutte le voci dizionario, async + /// + /// + Task> VocabolarioGetAllAsync(); + + /// + /// Recupero dizionario traduzioni x singola lingua + /// + /// Codice lingua + /// Dizionario di traduzioni + Dictionary VocabolarioGetLang(string lingua); + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/MP.Data/Repository/MpVoc/MpVocRepository.cs b/MP.Data/Repository/MpVoc/MpVocRepository.cs new file mode 100644 index 00000000..ae887011 --- /dev/null +++ b/MP.Data/Repository/MpVoc/MpVocRepository.cs @@ -0,0 +1,82 @@ +using Microsoft.EntityFrameworkCore; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.MpVoc +{ + public class MpVocRepository : IMpVocRepository + { + #region Public Constructors + + public MpVocRepository(IDbContextFactory ctxFactory) + { + _ctxFactory = ctxFactory; + } + + #endregion Public Constructors + + #region Public Methods + +#if false + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } +#endif + + /// + public async Task> LingueGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetLilngue + .AsNoTracking() + .OrderBy(x => x.Lingua) + .ToListAsync() ?? new(); + } + + /// + public async Task> VocabolarioGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetVocabolario + .AsNoTracking() + .OrderBy(x => x.Lemma) + .ToListAsync() ?? new(); + } + + /// + public Dictionary VocabolarioGetLang(string lingua) + { + using var dbCtx = _ctxFactory.CreateDbContextAsync().GetAwaiter().GetResult(); + var rawList = dbCtx + .DbSetVocabolario + .AsNoTracking() + .Where(x => x.Lingua.ToLower() == lingua.ToLower()) + .OrderBy(x => x.Lemma) + .ToList(); + // Proietto in dizionario + return rawList + .DistinctBy(t => t.Lemma, StringComparer.OrdinalIgnoreCase) + .ToDictionary(t => t.Lemma, t => t.Traduzione, StringComparer.OrdinalIgnoreCase); + } + + #endregion Public Methods + + #region Private Fields + + private readonly IDbContextFactory _ctxFactory; + + #endregion Private Fields + } +} \ No newline at end of file diff --git a/MP.Data/Repository/Production/BaseRepository.cs b/MP.Data/Repository/Production/BaseRepository.cs new file mode 100644 index 00000000..b7d20e56 --- /dev/null +++ b/MP.Data/Repository/Production/BaseRepository.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Production +{ + public abstract class BaseRepository + { + #region Protected Fields + + protected readonly IDbContextFactory _ctxFactory; + + #endregion Protected Fields + + #region Protected Constructors + + protected BaseRepository(IDbContextFactory ctxFactory) => _ctxFactory = ctxFactory; + + #endregion Protected Constructors + + #region Protected Methods + + /// + /// Creazione dbcontext per singola transazione + /// + /// + protected async Task CreateContextAsync() => await _ctxFactory.CreateDbContextAsync(); + + #endregion Protected Methods + + } +} diff --git a/MP.Data/Repository/Production/IProductionRepository.cs b/MP.Data/Repository/Production/IProductionRepository.cs new file mode 100644 index 00000000..7089a4de --- /dev/null +++ b/MP.Data/Repository/Production/IProductionRepository.cs @@ -0,0 +1,115 @@ +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Production +{ + public interface IProductionRepository + { + #region ODL Methods + + Task> ListODLFiltAsync(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate); + + Task OdlByKeyAsync(int IdxOdl); + + Task ODLCloseAsync(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi, bool confRett, int modoConfProd); + + Task> OdlGetCurrentAsync(); + + Task> OdlGetStatAsync(int IdxOdl); + + Task> OdlByBatchAsync(string batchSel); + + #endregion + + #region PODL Methods + + Task> ListPODLFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate); + + Task> ListPODL_ByCodArtAsync(string CodArticolo, bool OnlyAvail); + + Task> ListPODL_ByKitParentAsync(int IdxPodlParent); + + Task> ListPODL_KitFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate); + + Task PODL_getByKeyAsync(int idxPODL); + + Task PODL_getByOdlAsync(int idxODL); + + Task> PODL_getDictOdlPodlAsync(List missingIds); + + Task PODL_startSetup(PODLExpModel editRec, int matrOpr, double tcRich, int pzPallet, string note, DateTime dtEvent); + + Task PODL_updateRecipe(int idxPODL, string recipeName); + + Task PODLDeleteRecordAsync(PODLExpModel currRec); + + Task PODLUpdateRecordAsync(PODLModel editRec); + + Task PodlIstKitDeleteAsync(int IdxPODL); + + #endregion + + #region Kit Methods + + Task IstKitDeleteAsync(IstanzeKitModel rec2del); + + Task> IstKitFiltAsync(string keyKit, string keyExtOrd); + + Task IstKitInsertByWKSAsync(string CodArtParent, string KeyFilt); + + Task IstKitUpsertAsync(IstanzeKitModel editRec); + + Task TemplateKitDeleteAsync(TemplateKitModel rec2del); + + Task> TemplateKitFiltAsync(string KitCode, string codChild); + + Task TemplateKitUpsertAsync(TemplateKitModel editRec, string codAzienda); + + Task WipKitDeleteAsync(WipSetupKitModel rec2del); + + Task WipKitDeleteOlderAsync(DateTime dateLimit); + + Task> WipKitFiltAsync(string KeyFilt); + + Task WipKitUpsertAsync(WipSetupKitModel editRec); + + Task> TksScoreAsync(string KeyFilt, int MaxResult); + + #endregion + + #region Macchine / Gruppi Methods + + Task> MacchineGetFiltAsync(string codGruppo); + + Task> MacchineByMatrOperAsync(int MatrOpr); + + Task> MacchineWithFluxAsync(DateTime dtStart, DateTime dtEnd); + + Task Grp2MaccDeleteAsync(Gruppi2MaccModel rec2del); + + Task Grp2MaccInsertAsync(Gruppi2MaccModel upsRec); + + Task Grp2OperDeleteAsync(Gruppi2OperModel rec2del); + + Task Grp2OperInsertAsync(Gruppi2OperModel upsRec); + + Task StatoMacchinaAsync(string idxMacchina); + + #endregion + + #region Misc Production Methods + + Task> MseGetAllAsync(int maxAge = 2000); + + Task> ListGiacenzeAsync(int IdxOdl); + + Task> OperatoriGetFiltAsync(string codGruppo); + Task OperatoriUpsertAsync(AnagOperatoriModel updRec); + + Task> ParametriGetFiltAsync(string IdxMacchina); + + #endregion + } +} diff --git a/MP.Data/Repository/Production/ProductionRepository.cs b/MP.Data/Repository/Production/ProductionRepository.cs new file mode 100644 index 00000000..ec051504 --- /dev/null +++ b/MP.Data/Repository/Production/ProductionRepository.cs @@ -0,0 +1,879 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Production +{ + public class ProductionRepository : IProductionRepository + { + #region Private Fields + + private readonly IDbContextFactory _ctxFactory; + private readonly IConfiguration _configuration; + + #endregion + + #region Public Constructors + protected readonly IDbContextFactory _ctxFactoryFL; + + public ProductionRepository( + IConfiguration configuration, + IDbContextFactory ctxFactory, + IDbContextFactory ctxFactoryFL) + { + _ctxFactory = ctxFactory; + _ctxFactoryFL = ctxFactoryFL; + _configuration = configuration; + } + + #endregion + + #region Private Methods + + private async Task GetMoonProContextAsync() => await _ctxFactory.CreateDbContextAsync(); + + #endregion + + #region Public Methods - ODL + + /// + public async Task> ListODLFiltAsync(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) + { + await using var dbCtx = await GetMoonProContextAsync(); + + var InCorso = new SqlParameter("@InCorso", inCorso); + var CodArt = new SqlParameter("@CodArt", codArt); + var KeyRich = new SqlParameter("@KeyRich", keyRichPart); + var CodGruppo = new SqlParameter("@CodGruppo", Reparto); + var IdxMacc = new SqlParameter("@IdxMacchina", IdxMacchina); + var DataFrom = new SqlParameter("@DataFrom", startDate); + var DataTo = new SqlParameter("@DataTo", endDate); + + return await dbCtx + .DbSetODLExp + .FromSqlRaw("EXEC stp_ODL_getByFiltSpec @InCorso, @CodArt, @KeyRich, @CodGruppo, @IdxMacchina, @DataFrom, @DataTo", InCorso, CodArt, KeyRich, CodGruppo, IdxMacc, DataFrom, DataTo) + .AsNoTracking() + .ToListAsync(); + } + + /// + public async Task OdlByKeyAsync(int IdxOdl) + { + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetODLExp + .AsNoTracking() + .FirstOrDefaultAsync(x => x.IdxOdl == IdxOdl); + } + + /// + public async Task ODLCloseAsync(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi, bool confRett, int modoConfProd) + { + bool fatto = false; + if (idxOdl > 0) + { + await using var dbCtx = await GetMoonProContextAsync(); + // preparo i parametri + var IdxODL = new SqlParameter("@IdxODL", idxOdl); + var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); + + try + { + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ODL_fineProd @IdxODL, @IdxMacchina", IdxODL, IdxMacchina); + fatto = dbResult != 0; + } + catch (Exception exc) + { + NLog.LogManager.GetCurrentClassLogger().Error($"Eccezione durante ODLCloseAsync{Environment.NewLine}{exc}"); + } + } + return fatto; + } + + /// + public async Task> OdlGetCurrentAsync() + { + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetODL + .Where(x => x.DataInizio != null && x.DataFine == null) + .ToListAsync(); + } + + /// + public async Task> OdlGetStatAsync(int IdxOdl) + { + List dbResult = new List(); + if (IdxOdl > 0) + { + await using var dbCtx = await GetMoonProContextAsync(); + var IdxODL = new SqlParameter("@IdxODL", IdxOdl); + + dbResult = await dbCtx + .DbSetStatOdl + .FromSqlRaw("EXEC stp_STAT_ODL @IdxODL", IdxODL) + .AsNoTracking() + .ToListAsync(); + } + return dbResult; + } + + /// + public async Task> OdlByBatchAsync(string batchSel) + { + await using var dbCtx = new MoonPro_InveContext(_configuration); + return await dbCtx + .DbGiacenzeData + .AsNoTracking() + .Where(x => x.IdxOdl > 0) + .Select(x => x.IdxOdl) + .ToListAsync(); + } + + #endregion + + #region Public Methods - PODL + + /// + public async Task> ListPODLFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) + { + await using var dbCtx = await GetMoonProContextAsync(); + var Lanc = new SqlParameter("@Lanciato", lanciato); + var KeyRich = new SqlParameter("@KeyRich", keyRichPart); + var CodGrp = new SqlParameter("@CodGruppo", codGruppo); + var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); + var DateFrom = new SqlParameter("@DtInizio", startDate); + var DateTo = new SqlParameter("@DtFine", endDate); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByFiltSpec @Lanciato, @KeyRich, @CodGruppo, @IdxMacchina, @DtInizio, @DtFine", Lanc, KeyRich, CodGrp, IdxMacc, DateFrom, DateTo) + .AsNoTracking() + .ToListAsync(); + } + + /// + public async Task> ListPODL_ByCodArtAsync(string CodArticolo, bool OnlyAvail) + { + await using var dbCtx = await GetMoonProContextAsync(); + var pCodArticolo = new SqlParameter("@CodArticolo", CodArticolo); + var pOnlyAvail = new SqlParameter("@onlyAvail", OnlyAvail); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByCodArt @CodArticolo, @onlyAvail", pCodArticolo, pOnlyAvail) + .AsNoTracking() + .ToListAsync(); + } + + /// + public async Task> ListPODL_ByKitParentAsync(int IdxPodlParent) + { + await using var dbCtx = await GetMoonProContextAsync(); + var pIdxPodlParent = new SqlParameter("@IdxPodlParent", IdxPodlParent); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByParentKitIdx @IdxPodlParent", pIdxPodlParent) + .AsNoTracking() + .ToListAsync(); + } + + /// + public async Task> ListPODL_KitFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) + { + await using var dbCtx = await GetMoonProContextAsync(); + var Lanc = new SqlParameter("@Lanciato", lanciato); + var KeyRich = new SqlParameter("@KeyRich", keyRichPart); + var CodGrp = new SqlParameter("@CodGruppo", codGruppo); + var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); + var DateFrom = new SqlParameter("@DtInizio", startDate); + var DateTo = new SqlParameter("@DtFine", endDate); + + return await dbCtx + .DbSetPODLExp + .FromSqlRaw("EXEC stp_PODL_getByFiltSpecKit @Lanciato, @KeyRich, @CodGruppo, @IdxMacchina, @DtInizio, @DtFine", Lanc, KeyRich, CodGrp, IdxMacc, DateFrom, DateTo) + .AsNoTracking() + .ToListAsync(); + } + + /// + public async Task PODL_getByKeyAsync(int idxPODL) + { + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => x.IdxPromessa == idxPODL) + .Include(a => a.ArticoloNav) + .FirstOrDefaultAsync() ?? new(); + } + + /// + public async Task PODL_getByOdlAsync(int idxODL) + { + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => x.IdxOdl == idxODL) + .FirstOrDefaultAsync() ?? new(); + } + + /// + public async Task> PODL_getDictOdlPodlAsync(List missingIds) + { + if (missingIds == null || !missingIds.Any()) + return new Dictionary(); + + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => missingIds.Contains(x.IdxOdl)) + .ToDictionaryAsync(x => x.IdxOdl, x => x.IdxPromessa); + } + + /// + public async Task PODL_startSetup(PODLExpModel editRec, int matrOpr, double tcRich, int pzPallet, string note, DateTime dtEvent) + { + bool answ = false; + PODLModel recPODL = new PODLModel() + { + IdxPromessa = editRec.IdxPromessa, + KeyRichiesta = editRec.KeyRichiesta, + KeyBCode = editRec.KeyBCode, + IdxOdl = editRec.IdxOdl, + CodArticolo = editRec.CodArticolo, + CodGruppo = editRec.CodGruppo, + IdxMacchina = editRec.IdxMacchina, + NumPezzi = editRec.NumPezzi, + Tcassegnato = editRec.Tcassegnato, + DueDate = editRec.DueDate, + Priorita = editRec.Priorita, + PzPallet = editRec.PzPallet, + Note = editRec.Note, + CodCli = editRec.CodCli, + InsertDate = editRec.InsertDate + }; + + await using var dbCtx = await GetMoonProContextAsync(); + var currRec = await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => x.IdxPromessa == recPODL.IdxPromessa) + .FirstOrDefaultAsync(); + + if (currRec != null) + { + var IdxPromessa = new SqlParameter("@idxPromessa", recPODL.IdxPromessa); + var MatrOpr = new SqlParameter("@MatrOpr", matrOpr); + var IdxMacchina = new SqlParameter("@IdxMacchina", recPODL.IdxMacchina); + var TCRichAttr = new SqlParameter("@TCRichAttr", tcRich); + var PzPallet = new SqlParameter("@PzPallet", pzPallet); + var Note = new SqlParameter("@Note", note); + var DtEvento = new SqlParameter("@dtEvento", dtEvent); + await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ODL_inizioSetupPromessa @idxPromessa, @MatrOpr, @IdxMacchina, @TCRichAttr, @PzPallet, @Note, @dtEvento", IdxPromessa, MatrOpr, IdxMacchina, TCRichAttr, PzPallet, Note, DtEvento); + + answ = true; + } + return answ; + } + + /// + public async Task PODL_updateRecipe(int idxPODL, string recipeName) + { + bool answ = false; + await using var dbCtx = await GetMoonProContextAsync(); + var currRec = await dbCtx + .DbSetPODL + .Where(x => x.IdxPromessa == idxPODL) + .FirstOrDefaultAsync(); + + if (currRec != null) + { + currRec.Recipe = recipeName; + dbCtx.Entry(currRec).State = EntityState.Modified; + answ = await dbCtx.SaveChangesAsync() > 0; + } + return answ; + } + + /// + public async Task PODLDeleteRecordAsync(PODLExpModel currRec) + { + PODLModel recPODL = new PODLModel() + { + IdxPromessa = currRec.IdxPromessa, + KeyRichiesta = currRec.KeyRichiesta, + KeyBCode = currRec.KeyBCode, + IdxOdl = currRec.IdxOdl, + CodArticolo = currRec.CodArticolo, + CodGruppo = currRec.CodGruppo, + IdxMacchina = currRec.IdxMacchina, + NumPezzi = currRec.NumPezzi, + Tcassegnato = currRec.Tcassegnato, + DueDate = currRec.DueDate, + Priorita = currRec.Priorita, + PzPallet = currRec.PzPallet, + Note = currRec.Note, + CodCli = currRec.CodCli, + InsertDate = currRec.InsertDate + }; + await using var dbCtx = await GetMoonProContextAsync(); + var currVal = await dbCtx + .DbSetPODL + .Where(x => x.IdxPromessa == recPODL.IdxPromessa) + .FirstOrDefaultAsync(); + dbCtx + .DbSetPODL + .Remove(currVal); + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task PODLUpdateRecordAsync(PODLModel editRec) + { + await using var dbCtx = await GetMoonProContextAsync(); + var currRec = await dbCtx + .DbSetPODL + .Where(x => x.IdxPromessa == editRec.IdxPromessa) + .FirstOrDefaultAsync(); + if (currRec != null) + { + currRec.CodGruppo = editRec.CodGruppo; + currRec.CodArticolo = editRec.CodArticolo; + currRec.IdxMacchina = editRec.IdxMacchina; + currRec.KeyBCode = editRec.KeyBCode; + currRec.KeyRichiesta = editRec.KeyRichiesta; + currRec.NumPezzi = editRec.NumPezzi; + currRec.Tcassegnato = editRec.Tcassegnato; + currRec.Attivabile = editRec.Attivabile; + currRec.Note = editRec.Note; + dbCtx.Entry(currRec).State = EntityState.Modified; + } + else + { + await dbCtx + .DbSetPODL + .AddAsync(editRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task PodlIstKitDeleteAsync(int IdxPODL) + { + await using var dbCtx = await GetMoonProContextAsync(); + var pIdxPODL = new SqlParameter("@IdxPODL", IdxPODL); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC dbo.stp_PodlIstKit_delete @IdxPODL", pIdxPODL); + return dbResult != 0; + } + + #endregion + + #region Public Methods - Kit + + /// + public async Task IstKitDeleteAsync(IstanzeKitModel rec2del) + { + await using var dbCtx = await GetMoonProContextAsync(); + var actRec = await dbCtx + .DbSetInstKit + .Where(x => x.KeyKit == rec2del.KeyKit && x.KeyExtOrd == rec2del.KeyExtOrd) + .FirstOrDefaultAsync(); + if (actRec != null) + { + dbCtx + .DbSetInstKit + .Remove(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task> IstKitFiltAsync(string keyKit, string keyExtOrd) + { + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetInstKit + .Where(x => (string.IsNullOrEmpty(keyKit) && string.IsNullOrEmpty(keyExtOrd)) || (x.KeyKit.Contains(keyKit) && !string.IsNullOrEmpty(keyKit)) || (x.KeyExtOrd.Contains(keyExtOrd) && !string.IsNullOrEmpty(keyExtOrd))) + .AsNoTracking() + .ToListAsync() ?? new(); + } + + /// + public async Task IstKitInsertByWKSAsync(string CodArtParent, string KeyFilt) + { + await using var dbCtx = await GetMoonProContextAsync(); + + var pCodArtParent = new SqlParameter("@CodArtParent", CodArtParent); + var pKeyFilt = new SqlParameter("@KeyFilt", KeyFilt); + + var dbResult = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC dbo.stp_IstKit_insertByWKS @CodArtParent,@KeyFilt", pCodArtParent, pKeyFilt); + return dbResult != 0; + } + + /// + public async Task IstKitUpsertAsync(IstanzeKitModel editRec) + { + await using var dbCtx = await GetMoonProContextAsync(); + var actRec = await dbCtx + .DbSetInstKit + .Where(x => x.KeyKit == editRec.KeyKit && x.KeyExtOrd == editRec.KeyExtOrd) + .FirstOrDefaultAsync(); + + if (actRec == null) + { + await dbCtx + .DbSetInstKit + .AddAsync(editRec); + } + else + { + actRec.CodArtParent = editRec.CodArtParent; + actRec.CodArtChild = editRec.CodArtChild; + actRec.QtyART = editRec.QtyART; + actRec.QtyKIT = editRec.QtyKIT; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task TemplateKitDeleteAsync(TemplateKitModel rec2del) + { + await using var dbCtx = await GetMoonProContextAsync(); + var actRec = await dbCtx + .DbSetTempKit + .Where(x => x.CodArtParent == rec2del.CodArtParent && x.CodArtChild == rec2del.CodArtChild) + .FirstOrDefaultAsync(); + if (actRec != null) + { + dbCtx + .DbSetTempKit + .Remove(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task> TemplateKitFiltAsync(string KitCode, string codChild) + { + List dbResult = new List(); + await using var dbCtx = await GetMoonProContextAsync(); + dbResult = await dbCtx + .DbSetTempKit + .Where(x => (string.IsNullOrEmpty(KitCode) && string.IsNullOrEmpty(codChild)) || (x.CodArtParent.Contains(KitCode) && !string.IsNullOrEmpty(KitCode)) || (x.CodArtChild.Contains(codChild) && !string.IsNullOrEmpty(codChild))) + .AsNoTracking() + .ToListAsync(); + return dbResult; + } + + /// + public async Task TemplateKitUpsertAsync(TemplateKitModel editRec, string codAzienda) + { + await using var dbCtx = await GetMoonProContextAsync(); + var recArt = await dbCtx + .DbSetArticoli + .FirstOrDefaultAsync(x => x.CodArticolo == editRec.CodArtParent); + if (recArt == null) + { + AnagArticoliModel newRecArt = new AnagArticoliModel() + { + CodArticolo = editRec.CodArtParent, + Tipo = "KIT", + DescArticolo = $"Articolo KIT - {DateTime.Now:yyyy-MM-dd HH:mm:ss}", + Disegno = "", + Azienda = codAzienda, + CurrRev = "", + ProdRev = "" + }; + dbCtx + .DbSetArticoli + .Add(newRecArt); + } + + var actRec = await dbCtx + .DbSetTempKit + .Where(x => x.CodArtParent == editRec.CodArtParent && x.CodArtChild == editRec.CodArtChild) + .FirstOrDefaultAsync(); + + if (actRec == null) + { + await dbCtx + .DbSetTempKit + .AddAsync(editRec); + } + else + { + actRec.Qty = editRec.Qty; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task WipKitDeleteAsync(WipSetupKitModel rec2del) + { + await using var dbCtx = await GetMoonProContextAsync(); + var actRec = await dbCtx + .DbSetWipKit + .Where(x => x.KeyFilt == rec2del.KeyFilt && x.CodOrd == rec2del.CodOrd) + .FirstOrDefaultAsync(); + if (actRec != null) + { + dbCtx + .DbSetWipKit + .Remove(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task WipKitDeleteOlderAsync(DateTime dateLimit) + { + await using var dbCtx = await GetMoonProContextAsync(); + var actRec = await dbCtx + .DbSetWipKit + .Where(x => x.DataIns < dateLimit) + .ToListAsync(); + if (actRec != null && actRec.Any()) + { + dbCtx + .DbSetWipKit + .RemoveRange(actRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task> WipKitFiltAsync(string KeyFilt) + { + List dbResult = new List(); + if (!string.IsNullOrEmpty(KeyFilt)) + { + await using var dbCtx = await GetMoonProContextAsync(); + dbResult = await dbCtx + .DbSetWipKit + .Where(x => x.KeyFilt.Contains(KeyFilt)) + .AsNoTracking() + .ToListAsync(); + } + return dbResult; + } + + /// + public async Task WipKitUpsertAsync(WipSetupKitModel editRec) + { + await using var dbCtx = await GetMoonProContextAsync(); + var actRec = await dbCtx + .DbSetWipKit + .Where(x => x.KeyFilt == editRec.KeyFilt && x.CodOrd == editRec.CodOrd) + .FirstOrDefaultAsync(); + + if (actRec == null) + { + dbCtx + .DbSetWipKit + .Add(editRec); + } + else + { + actRec.CodArt = editRec.CodArt; + actRec.DescArt = editRec.DescArt; + actRec.Qta = editRec.Qta; + actRec.DataIns = editRec.DataIns; + dbCtx.Entry(actRec).State = EntityState.Modified; + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task> TksScoreAsync(string KeyFilt, int MaxResult) + { + List dbResult = new List(); + if (!string.IsNullOrEmpty(KeyFilt)) + { + await using var dbCtx = await GetMoonProContextAsync(); + var pKeyFilt = new SqlParameter("@KeyFilt", KeyFilt); + var pMaxRes = new SqlParameter("@maxResult", MaxResult); + dbResult = await dbCtx + .DbSetTksScore + .FromSqlRaw("EXEC stp_TKS_Search @KeyFilt, @maxResult", pKeyFilt, pMaxRes) + .AsNoTracking() + .ToListAsync(); + } + return dbResult; + } + + #endregion + + #region Public Methods - Macchine/Gruppi + + /// + public async Task> MacchineGetFiltAsync(string codGruppo) + { + await using var dbCtx = await GetMoonProContextAsync(); + if (codGruppo == "*") + { + return await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + else + { + return await dbCtx + .DbSetGrp2Macc + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbSetMacchine, + g => g.IdxMacchina, + m => m.IdxMacchina, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + } + + /// + public async Task> MacchineByMatrOperAsync(int MatrOpr) + { + await using var dbCtx = await GetMoonProContextAsync(); + if (MatrOpr == 0) + { + return await dbCtx + .DbSetMacchine + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + else + { + return await dbCtx + .DbSetGrp2Oper + .Where(g => g.MatrOpr == MatrOpr) + .Join(dbCtx.DbSetGrp2Macc, + g => g.CodGruppo, + m => m.CodGruppo, + (g, m) => m + ) + .Distinct() + .Join(dbCtx.DbSetMacchine, + g => g.IdxMacchina, + m => m.IdxMacchina, + (g, m) => m + ) + .Distinct() + .AsNoTracking() + .OrderBy(x => x.IdxMacchina) + .ToListAsync(); + } + } + + /// + public async Task> MacchineWithFluxAsync(DateTime dtStart, DateTime dtEnd) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => x.dtEvento >= dtStart && x.dtEvento <= dtEnd) + .Select(i => i.IdxMacchina) + .Distinct() + .ToListAsync() ?? new(); + } + + /// + public async Task Grp2MaccDeleteAsync(Gruppi2MaccModel rec2del) + { + bool answ = false; + await using var dbCtx = await GetMoonProContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Macc + .Where(x => x.CodGruppo == rec2del.CodGruppo && x.IdxMacchina == rec2del.IdxMacchina) + .FirstOrDefaultAsync(); + if (dbRec != null) + { + dbCtx.DbSetGrp2Macc.Remove(dbRec); + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + public async Task Grp2MaccInsertAsync(Gruppi2MaccModel upsRec) + { + bool answ = false; + await using var dbCtx = await GetMoonProContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Macc + .Where(x => x.CodGruppo == upsRec.CodGruppo && x.IdxMacchina == upsRec.IdxMacchina) + .FirstOrDefaultAsync(); + if (dbRec == null) + { + await dbCtx.DbSetGrp2Macc.AddAsync(upsRec); + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + public async Task Grp2OperDeleteAsync(Gruppi2OperModel rec2del) + { + bool answ = false; + await using var dbCtx = await GetMoonProContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Oper + .Where(x => x.CodGruppo == rec2del.CodGruppo && x.MatrOpr == rec2del.MatrOpr) + .FirstOrDefaultAsync(); + if (dbRec != null) + { + dbCtx.DbSetGrp2Oper.Remove(dbRec); + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + public async Task Grp2OperInsertAsync(Gruppi2OperModel upsRec) + { + bool answ = false; + await using var dbCtx = await GetMoonProContextAsync(); + var dbRec = await dbCtx + .DbSetGrp2Oper + .Where(x => x.CodGruppo == upsRec.CodGruppo && x.MatrOpr == upsRec.MatrOpr) + .FirstOrDefaultAsync(); + if (dbRec == null) + { + await dbCtx.DbSetGrp2Oper.AddAsync(upsRec); + int numDone = await dbCtx.SaveChangesAsync(); + answ = numDone != 0; + } + return answ; + } + + /// + public async Task StatoMacchinaAsync(string idxMacchina) + { + await using var dbCtx = await GetMoonProContextAsync(); + return await dbCtx + .DbSetStatoMacc + .Where(x => x.IdxMacchina == idxMacchina) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + + #endregion + + #region Public Methods - Misc + + /// + public async Task> MseGetAllAsync(int maxAge = 2000) + { + List dbResult = new List(); + await using var dbCtx = await GetMoonProContextAsync(); + + var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge); + + dbResult = await dbCtx + .DbSetMSE + .FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec) + .AsNoTracking() + .ToListAsync(); + + return dbResult; + } + + /// + public async Task> ListGiacenzeAsync(int IdxOdl) + { + await using var dbCtx = new MoonPro_InveContext(_configuration); + return await dbCtx + .DbGiacenzeData + .Where(x => x.IdxOdl == IdxOdl) + .AsNoTracking() + .ToListAsync() ?? new(); + } + + /// + public async Task> OperatoriGetFiltAsync(string codGruppo) + { + List dbResult = new List(); + await using var dbCtx = await GetMoonProContextAsync(); + if (codGruppo == "*") + { + dbResult = await dbCtx + .DbOperatori + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToListAsync(); + } + else + { + dbResult = await dbCtx + .DbSetGrp2Oper + .Where(g => g.CodGruppo == codGruppo) + .Join(dbCtx.DbOperatori, + g => g.MatrOpr, + m => m.MatrOpr, + (g, m) => m + ) + .AsNoTracking() + .OrderBy(x => x.MatrOpr) + .ToListAsync(); + } + return dbResult; + } + + public async Task OperatoriUpsertAsync(AnagOperatoriModel updRec) + { + await using var dbCtx = await GetMoonProContextAsync(); + var dbRec = await dbCtx + .DbOperatori + .FindAsync(updRec.MatrOpr); + if (dbRec != null) + { + dbCtx.Entry(dbRec).CurrentValues.SetValues(updRec); + } + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task> ParametriGetFiltAsync(string IdxMacchina) + { + await using var dbCtx = await _ctxFactoryFL.CreateDbContextAsync(); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina)) + .Take(1000) + .Select(i => i.CodFlux) + .Distinct() + .OrderBy(x => x) + .ToListAsync(); + } + + #endregion + } +} diff --git a/MP.Data/Repository/System/ISystemRepository.cs b/MP.Data/Repository/System/ISystemRepository.cs new file mode 100644 index 00000000..055c3a87 --- /dev/null +++ b/MP.Data/Repository/System/ISystemRepository.cs @@ -0,0 +1,24 @@ +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Repository.System +{ + public interface ISystemRepository + { + Task> ConfigGetAllAsync(); + + Task ConfigUpdateAsync(ConfigModel updRec); + + Task EvListInsertAsync(EventListModel newRec); + + Task ForceDbMaintAsync(bool doExec, bool doUpdStat, bool doSave, int minPgCnt, int minAvgFrag, int maxAvgFragReb); + + Task> ListLinkAllAsync(); + + Task> ListLinkFiltAsync(string tipoLink); + + Task> ElencoLinkAsync(); + } +} diff --git a/MP.Data/Repository/System/SystemRepository.cs b/MP.Data/Repository/System/SystemRepository.cs new file mode 100644 index 00000000..1f078364 --- /dev/null +++ b/MP.Data/Repository/System/SystemRepository.cs @@ -0,0 +1,114 @@ +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using MP.Data.DbModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MP.Data.Repository.System +{ + public class SystemRepository : ISystemRepository + { + #region Private Fields + + private readonly IDbContextFactory _ctxFactory; + private readonly IConfiguration _configuration; + + #endregion + + #region Public Constructors + + public SystemRepository(IDbContextFactory ctxFactory, IConfiguration configuration) + { + _ctxFactory = ctxFactory; + _configuration = configuration; + } + + #endregion + + #region Public Methods + + /// + public async Task> ConfigGetAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetConfig + .AsNoTracking() + .OrderBy(x => x.Chiave) + .ToListAsync() ?? new(); + } + + /// + public async Task ConfigUpdateAsync(ConfigModel updRec) + { + bool fatto = false; + ConfigModel dbResult = new(); + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + dbResult = await dbCtx + .DbSetConfig + .Where(x => x.Chiave == updRec.Chiave) + .FirstOrDefaultAsync(); + if (dbResult != null) + { + dbResult.Valore = updRec.Valore; + fatto = await dbCtx.SaveChangesAsync() > 0; + } + return fatto; + } + + /// + public async Task EvListInsertAsync(EventListModel newRec) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + _ = await dbCtx + .DbSetEvList + .AddAsync(newRec); + return await dbCtx.SaveChangesAsync() > 0; + } + + /// + public async Task ForceDbMaintAsync(bool doExec, bool doUpdStat, bool doSave, int minPgCnt, int minAvgFrag, int maxAvgFragReb) + { + await using var dbCtx = new MoonProAdminContext(_configuration); + + _ = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC man.stp_Utility_Maintanance"); + return true; + } + + /// + public async Task> ListLinkAllAsync() + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetLinkMenu + .AsNoTracking() + .OrderBy(x => x.Ordine) + .ToListAsync(); + } + + /// + public async Task> ListLinkFiltAsync(string tipoLink) + { + await using var dbCtx = await _ctxFactory.CreateDbContextAsync(); + return await dbCtx + .DbSetLinkMenu + .Where(x => x.TipoLink == tipoLink) + .AsNoTracking() + .OrderBy(x => x.Ordine) + .ToListAsync(); + } + + /// + public Task> ElencoLinkAsync() + { + return ListLinkFiltAsync("SpecLink"); + } + + #endregion + } +} diff --git a/MP.Data/Repository/Utils/BaseRepository.cs b/MP.Data/Repository/Utils/BaseRepository.cs index 4e709040..aceaa04a 100644 --- a/MP.Data/Repository/Utils/BaseRepository.cs +++ b/MP.Data/Repository/Utils/BaseRepository.cs @@ -13,8 +13,7 @@ namespace MP.Data.Repository.Utils #region Protected Constructors - protected BaseRepository(IDbContextFactory ctxFactory) - => _ctxFactory = ctxFactory; + protected BaseRepository(IDbContextFactory ctxFactory) => _ctxFactory = ctxFactory; #endregion Protected Constructors @@ -24,24 +23,9 @@ namespace MP.Data.Repository.Utils /// Creazione dbcontext per singola transazione /// /// - protected async Task CreateContextAsync() - => await _ctxFactory.CreateDbContextAsync(); + protected async Task CreateContextAsync() => await _ctxFactory.CreateDbContextAsync(); #endregion Protected Methods -#if false - /// - /// Salvataggio dati asincrono - /// - /// - protected async Task SaveChangesAsync(DataLayerContext ctx) - => await ctx.SaveChangesAsync() > 0; -#endif - -#if false - protected readonly DataLayerContext _dbCtx; - protected BaseRepository(DataLayerContext db) => _dbCtx = db; - public async Task SaveChangesAsync() => await _dbCtx.SaveChangesAsync() > 0; -#endif } } \ No newline at end of file diff --git a/MP.Data/Services/BaseServ.cs b/MP.Data/Services/BaseServ.cs index 51355686..0a6dbf7e 100644 --- a/MP.Data/Services/BaseServ.cs +++ b/MP.Data/Services/BaseServ.cs @@ -9,6 +9,8 @@ using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; +using static Org.BouncyCastle.Asn1.Cmp.Challenge; namespace MP.Data.Services { @@ -19,10 +21,12 @@ namespace MP.Data.Services { #region Public Constructors - public BaseServ(IConfiguration configuration, IConnectionMultiplexer redConn) + public BaseServ(IConfiguration configuration, IFusionCache cache, IConnectionMultiplexer redConn) { _configuration = configuration; + _cache = cache; + slowLogThresh = _configuration.GetValue("ServerConf:slowLogThresh", 1); // Verifica conf trace... _traceEnabled = _configuration.GetValue("Otel:EnableTracing", false); @@ -161,13 +165,23 @@ namespace MP.Data.Services /// protected static readonly ActivitySource ActivitySource = new ActivitySource("MP.IOC"); - protected static IConfiguration _configuration = null!; + /// + /// Oggetto gestione FusionCache + /// + protected readonly IFusionCache _cache; + + /// + /// Path base chiavi REDIS + /// + protected readonly string _redisBaseKey = "MP:IOC"; /// /// Abilitazione operazioni tracing generiche /// protected readonly bool _traceEnabled = false; + protected IConfiguration _configuration = null!; + /// /// Oggetto per connessione a REDIS /// @@ -180,8 +194,19 @@ namespace MP.Data.Services protected IDatabase _redisDb = null!; protected JsonSerializerSettings? JSSettings; + protected string MpIoNS = ""; + /// + /// Durata cache Lunga standard (300 sec) + /// + protected int redisLongTimeCache = 300; + + /// + /// Durata cache Breve standard (5 sec) + /// + protected int redisShortTimeCache = 5; + #endregion Protected Fields #region Protected Properties @@ -281,6 +306,75 @@ namespace MP.Data.Services } } + /// + /// Implementa gestione FusionCache+ tracking attività + /// - recupero cache da memoria o da obj esterno + cache memoria + /// - recupero da fetchFunc se mancasse + store in cache L1/L2 + /// + /// + /// + /// + /// + /// + protected async Task GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tagList) + { + using var activity = ActivitySource.StartActivity(operationName); + string source; + var tryGet = await _cache.TryGetAsync(cacheKey); + if (tryGet.HasValue) + { + source = "MEMORY"; + var result = tryGet.Value!; + + activity?.SetTag("data.source", source); + activity?.Stop(); + // se supero la soglia loggo... + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + } + return result; + } + bool fromDb = false; + // cache in redis + var cacheOptions = new FusionCacheEntryOptions() + .SetDuration(expiration) + .SetFailSafe(true); + // cache in RAM per 1/3 del tempo x risparmiare risorse + cacheOptions.MemoryCacheDuration = expiration / 3; + + var final = await _cache.GetOrSetAsync( + cacheKey, + async _ => + { + fromDb = true; + return await fetchFunc(); + }, + options: cacheOptions, + tags: tagList + ); + + source = fromDb ? "DB" : "REDIS"; + activity?.SetTag("data.source", source); + activity?.Stop(); + // switch log in base a source.. + switch (source) + { + case "DB": + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms", reqLevel: NLog.LogLevel.Info); + break; + + case "REDIS": + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms", reqLevel: NLog.LogLevel.Debug); + break; + + default: + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + break; + } + return final!; + } + /// /// Helper generale di lettura da cache o da funzione (DB) con caching successivo /// @@ -327,6 +421,18 @@ namespace MP.Data.Services return result!; } + /// + /// Restituisce un timeout dal valore secondi richiesti + tempo random +/-3% + /// + /// + /// + protected TimeSpan GetRandTOut(double durationSec) + { + double noise = (rand.NextDouble() * 0.06) - 0.03; + double rValue = durationSec * (1 + noise); + return TimeSpan.FromSeconds(rValue); + } + /// /// Helper trace messaggio log (SE abilitato) /// @@ -396,6 +502,7 @@ namespace MP.Data.Services #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); + private bool _disposed = false; /// @@ -408,12 +515,14 @@ namespace MP.Data.Services /// private int cacheTtlShort = 60 * 1; + private Random rand = new Random(); + private Random rnd = new Random(); /// - /// Path base chiavi REDIS + /// Soglia minima (ms) per log timing in console /// - protected readonly string _redisBaseKey = "MP:IOC"; + private double slowLogThresh = 0; #endregion Private Fields } diff --git a/MP.Data/Services/IOC/IocService.cs b/MP.Data/Services/IOC/IocService.cs index c3a8369e..0a709a30 100644 --- a/MP.Data/Services/IOC/IocService.cs +++ b/MP.Data/Services/IOC/IocService.cs @@ -23,17 +23,19 @@ namespace MP.Data.Services.IOC public IocService( IConfiguration config, IConnectionMultiplexer redis, + IFusionCache cache, IIocRepository repo, - IServiceScopeFactory scopeFactory, - //Microsoft.Extensions.Caching.Memory.IMemoryCache cache - IFusionCache cache) : base(config, redis) + IServiceScopeFactory scopeFactory + ) : base(config, cache, redis) { _className = "IocServ"; int.TryParse(config.GetValue("ServerConf:redisLongTimeCache"), out redisLongTimeCache); int.TryParse(config.GetValue("ServerConf:redisShortTimeCache"), out redisShortTimeCache); _repo = repo; _scopeFactory = scopeFactory; - _cache = cache; +#if false + _cache = cache; +#endif } #endregion Public Constructors @@ -79,7 +81,7 @@ namespace MP.Data.Services.IOC result = await GetCurrOdlByProdAsync(idxMacchina); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); - _redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); + _redisDb.StringSet(currKey, rawData, GetRandTOut(redisLongTimeCache)); } return result; } @@ -261,16 +263,18 @@ namespace MP.Data.Services.IOC #region Protected Methods +#if false /// /// Restituisce un timeout dai minuti richiesti + tempo random 1..60 sec /// /// /// - protected TimeSpan getRandTOut(double stdMinutes) + protected TimeSpan GetRandTOut(double stdMinutes) { double rndValue = stdMinutes + (double)rand.Next(1, 60) / 60; return TimeSpan.FromMinutes(rndValue); - } + } +#endif #endregion Protected Methods @@ -278,7 +282,9 @@ namespace MP.Data.Services.IOC private static Logger Log = LogManager.GetCurrentClassLogger(); - private readonly IFusionCache _cache; +#if false + private readonly IFusionCache _cache; +#endif private readonly string _className; @@ -295,9 +301,11 @@ namespace MP.Data.Services.IOC /// private string dtFormat = "yyyyMMddHHmmssfff"; +#if false private int redisLongTimeCache = 5; - private int redisShortTimeCache = 2; + private int redisShortTimeCache = 2; +#endif #endregion Private Fields @@ -417,7 +425,7 @@ namespace MP.Data.Services.IOC { result = await _repo.ConfigGetAllAsync(); rawData = JsonConvert.SerializeObject(result); - await _redisDb.StringSetAsync(MP.Data.Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); + await _redisDb.StringSetAsync(MP.Data.Utils.redisConfKey, rawData, GetRandTOut(redisLongTimeCache)); } Log.Debug($"ConfigGetAllAsync Read from {source}"); if (result == null) @@ -468,10 +476,6 @@ namespace MP.Data.Services.IOC /// private async Task GetOrFetchAsync(string cacheKey, Func> fetchFunc, TimeSpan expiration) { - // GetOrSetAsync di Fusion cache: - // - TryGetValue, se mancasse crea un lock solo per QUELLA key - // - Esegue fetchFunc (la logica Redis + DB) - // - Salva in memoria e rilascia il lock return await _cache.GetOrSetAsync( cacheKey, async ct => await fetchFunc(), @@ -548,7 +552,7 @@ namespace MP.Data.Services.IOC var fullList = await Macchine2SlaveGetAllAsync(); result = fullList.Select(x => x.IdxMacchina).ToHashSet(); rawData = JsonConvert.SerializeObject(result); - await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); + await _redisDb.StringSetAsync(currKey, rawData, GetRandTOut(redisLongTimeCache * 10)); } return result; }, TimeSpan.FromMinutes(15)); @@ -570,7 +574,7 @@ namespace MP.Data.Services.IOC var fullList = await Macchine2SlaveGetAllAsync(); result = fullList.Select(x => x.IdxMacchinaSlave).Distinct().ToHashSet(); rawData = JsonConvert.SerializeObject(result); - await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); + await _redisDb.StringSetAsync(currKey, rawData, GetRandTOut(redisLongTimeCache * 10)); } return result; }, TimeSpan.FromMinutes(15)); @@ -597,7 +601,7 @@ namespace MP.Data.Services.IOC result = await _repo.Macchine2SlaveAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); - await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); + await _redisDb.StringSetAsync(currKey, rawData, GetRandTOut(redisLongTimeCache * 10)); } if (result == null) { @@ -1066,19 +1070,19 @@ namespace MP.Data.Services.IOC string currVals = $"idxMacchina: {idxMacchina} | valOut: {valore} | dtEve: {dtEve} | dtCurr:{dtCurr}"; if (dtEve == null || dtCurr == null) { - Log.Warn($"procInput: null found | {currVals}"); + Log.Warn($"{_className} | procInput: null found | {currVals}"); } else if (dtEve.Length < 17 || dtCurr.Length < 17) { - Log.Info($"procInput: invalid data | {currVals}"); + Log.Info($"{_className} | procInput: invalid data | {currVals}"); } else if (string.IsNullOrEmpty(idxMacchina)) { - Log.Info($"procInput: missing IdxMacchina | {currVals}"); + Log.Info($"{_className} | procInput: missing IdxMacchina | {currVals}"); } else if (string.IsNullOrEmpty(valore)) { - Log.Info($"procInput: missing valOut | {currVals}"); + Log.Info($"{_className} | procInput: missing valOut | {currVals}"); } else { diff --git a/MP.Data/Services/LandDataService.cs b/MP.Data/Services/LandDataService.cs index 8607bf6a..8351a4b8 100644 --- a/MP.Data/Services/LandDataService.cs +++ b/MP.Data/Services/LandDataService.cs @@ -14,6 +14,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -21,8 +22,14 @@ namespace MP.Data.Services { #region Public Constructors - public LandDataService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public LandDataService( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache, + Repository.MpLand.IMpLandRepository mpLandRepository + ) : base(configuration, cache, redConn) { + _mpLandRepository = mpLandRepository; // conf DB string connStr = _configuration.GetConnectionString("MP.Land"); if (string.IsNullOrEmpty(connStr)) @@ -31,28 +38,21 @@ namespace MP.Data.Services } else { - dbController = new Controllers.MpLandController(configuration); StringBuilder sb = new StringBuilder(); - sb.AppendLine($"LandService | MpLandController OK"); + sb.AppendLine($"LandService | MpLandRepository OK"); Log.Info(sb.ToString()); } } #endregion Public Constructors - #region Public Properties - - public static MpLandController dbController { get; set; } = null!; - - #endregion Public Properties - #region Public Methods /// /// Restituisce info dimensione, tabelle e num righe DB /// /// - public List AllDbInfo() + public async Task> AllDbInfoAsync() { // setup parametri costanti string source = "DB"; @@ -61,7 +61,7 @@ namespace MP.Data.Services List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:DbInfo:ALL"; - RedisValue rawData = _redisDb.StringGet(currKey); + RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); @@ -69,17 +69,17 @@ namespace MP.Data.Services } else { - result = dbController.AllDbInfo(); + result = await _mpLandRepository.AllDbInfoAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); - _redisDb.StringSet(currKey, rawData, UltraFastCache); + await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); - Log.Debug($"AllDbInfo | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"AllDbInfoAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -88,15 +88,15 @@ namespace MP.Data.Services /// /// /// - public List IobListAll() + public async Task> IobListAllAsync() { string source = "DB"; List? dbResult = new List(); string currKey = $"{redisBaseKey}:IobList"; Stopwatch sw = new Stopwatch(); sw.Start(); - string? rawData = _redisDb.StringGet(currKey); - if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2) + var rawData = await _redisDb.StringGetAsync(currKey); + if (rawData.HasValue) { source = "REDIS"; var tempResult = JsonConvert.DeserializeObject>(rawData); @@ -105,10 +105,10 @@ namespace MP.Data.Services else { // recupero RRL missing - var listRRl = dbController.RemRebootLogGetLast(); - var listRRlAdd = dbController.RemRebootLogGetLastNoMacc(); + var listRRl = await _mpLandRepository.RemRebootLogGetLastAsync(); + var listRRlAdd = await _mpLandRepository.RemRebootLogGetLastNoMaccAsync(); // recupero lista macchine - var ListMacch = dbController.MacchineGetAll(); + var ListMacch = await _mpLandRepository.MacchineGetAllAsync(); // ...converto in DTO dbResult = ListMacch .Select(x => new IobDTO(x, IobInfo(x.IdxMacchina), MachIobConf(x.IdxMacchina))) @@ -125,14 +125,14 @@ namespace MP.Data.Services // serializzo in cache _redisConn rawData = JsonConvert.SerializeObject(dbResult, JSSettings); - _redisDb.StringSet(currKey, rawData, UltraLongCache); + await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (dbResult == null) { dbResult = new List(); } sw.Stop(); - Log.Debug($"IobListAll | {source} | {sw.ElapsedMilliseconds} ms"); + Log.Debug($"IobListAllAsync | {source} | {sw.ElapsedMilliseconds} ms"); return dbResult; } @@ -158,7 +158,7 @@ namespace MP.Data.Services } else { - result = dbController.RemRebootLogGetAll(); + result = _mpLandRepository.RemRebootLogGetAllAsync().GetAwaiter().GetResult(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraFastCache); @@ -194,7 +194,7 @@ namespace MP.Data.Services } else { - result = dbController.RemRebootLogGetLast(); + result = _mpLandRepository.RemRebootLogGetLastAsync().GetAwaiter().GetResult(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraFastCache); @@ -219,7 +219,6 @@ namespace MP.Data.Services if (disposing) { // Free managed resources here - dbController.Dispose(); } // Free unmanaged resources here @@ -234,6 +233,7 @@ namespace MP.Data.Services #region Private Fields + private readonly Repository.MpLand.IMpLandRepository _mpLandRepository; private static Logger Log = LogManager.GetCurrentClassLogger(); private bool _disposed = false; private string redisBaseKey = "MP:LAND:Cache"; diff --git a/MP.Data/Services/ListSelectDataSrv.cs b/MP.Data/Services/ListSelectDataSrv.cs index b541ee06..c93c8e44 100644 --- a/MP.Data/Services/ListSelectDataSrv.cs +++ b/MP.Data/Services/ListSelectDataSrv.cs @@ -1,5 +1,8 @@ using Microsoft.Extensions.Configuration; using MP.Data.DbModels; +using MP.Data.Repository.Anag; +using MP.Data.Repository.Production; +using MP.Data.Repository.System; using Newtonsoft.Json; using NLog; using StackExchange.Redis; @@ -8,8 +11,8 @@ using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; -using System.Text; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -18,32 +21,34 @@ namespace MP.Data.Services /// public class ListSelectDataSrv : BaseServ { + #region Private Fields + + private static Logger Log = LogManager.GetCurrentClassLogger(); + private readonly IAnagRepository _anagRepository; + private readonly IProductionRepository _productionRepository; + private readonly ISystemRepository _systemRepository; + private bool _disposed = false; + private string redisBaseKey = "MP:ALL:Cache"; + + #endregion + #region Public Constructors - public ListSelectDataSrv(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public ListSelectDataSrv( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache, + IAnagRepository anagRepository, + IProductionRepository productionRepository, + ISystemRepository systemRepository + ) : base(configuration, cache, redConn) { - // conf DB - string connStr = _configuration.GetConnectionString("MP.All"); - if (string.IsNullOrEmpty(connStr)) - { - Log.Error("ConnString empty!"); - } - else - { - StringBuilder sb = new StringBuilder(); - dbController = new Controllers.MpSpecController(configuration); - sb.AppendLine($"ListSelectDataSrv | MpSpecController OK"); - Log.Info(sb.ToString()); - } + _anagRepository = anagRepository; + _productionRepository = productionRepository; + _systemRepository = systemRepository; } - #endregion Public Constructors - - #region Public Properties - - public static Controllers.MpSpecController dbController { get; set; } = null!; - - #endregion Public Properties + #endregion #region Public Methods @@ -54,14 +59,14 @@ namespace MP.Data.Services /// cod azienda, * = tutte /// Ricerca testuale /// - public async Task> ArticoliGetSearch(int numRecord, string azienda, string searchVal) + public async Task> ArticoliGetSearch(int numRecord, string tipoArt, string azienda, string searchVal) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... - string currKey = $"{redisBaseKey}:Art:{azienda}:{searchVal}:{numRecord}"; + string currKey = $"{redisBaseKey}:Art:{azienda}:{tipoArt}:{searchVal}:{numRecord}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { @@ -70,10 +75,7 @@ namespace MP.Data.Services } else { - result = dbController.ArticoliGetSearch(numRecord, azienda, searchVal); -#if false - result = await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal)); -#endif + result = await _anagRepository.ArticoliGetSearchAsync(numRecord, tipoArt, azienda, searchVal); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); @@ -83,7 +85,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ArticoliGetSearch | azienda: {azienda} | searchVal: {searchVal} | numRecord: {numRecord} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Trace($"ArticoliGetSearchAsync | azienda: {azienda} | tipoArt: {tipoArt} | searchVal: {searchVal} | numRecord: {numRecord} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -107,7 +109,7 @@ namespace MP.Data.Services } else { - result = dbController.ConfigGetAll(); + result = await _systemRepository.ConfigGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); @@ -117,7 +119,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ConfigGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -163,7 +165,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.ListLinkAll()); + result = await _systemRepository.ListLinkAllAsync(); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); @@ -173,7 +175,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ListLinkAll | tipoLink: * | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ListLinkAllAsync | tipoLink: * | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -199,7 +201,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.ListLinkFilt(tipoLink)); + result = await _systemRepository.ListLinkFiltAsync(tipoLink); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); @@ -235,7 +237,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.MacchineByMatrOper(MatrOpr)); + result = await _productionRepository.MacchineByMatrOperAsync(MatrOpr); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); @@ -257,12 +259,6 @@ namespace MP.Data.Services { if (!_disposed) { - if (disposing) - { - // Free managed resources here - dbController.Dispose(); - } - // Free unmanaged resources here _disposed = true; } @@ -273,14 +269,6 @@ namespace MP.Data.Services #endregion Protected Methods - #region Private Fields - - private static Logger Log = LogManager.GetCurrentClassLogger(); - private bool _disposed = false; - private string redisBaseKey = "MP:ALL:Cache"; - - #endregion Private Fields - #region Private Methods /// @@ -391,7 +379,7 @@ namespace MP.Data.Services } answ = true; } - return answ; + return answ; #endif } diff --git a/MP.Data/Services/MessageService.cs b/MP.Data/Services/MessageService.cs index 38d4db11..dda06848 100644 --- a/MP.Data/Services/MessageService.cs +++ b/MP.Data/Services/MessageService.cs @@ -47,10 +47,6 @@ namespace MP.Data.Services public event Action EA_OperUpdated = null!; - public event Action EA_PageUpdated = null!; - - public event Action EA_ResetFooterTimer = null!; - #endregion Public Events #region Public Properties @@ -707,26 +703,12 @@ namespace MP.Data.Services private AnagOperatoriModel? _rigaOper; - /// - /// Durata cache lunga IN SECONDI - /// - private int cacheTtlLong = 60 * 5; - - /// - /// Durata cache breve IN SECONDI - /// - private int cacheTtlShort = 60 * 1; - - private string lastIdxMacc = ""; - private DateTime lastUserUpd = DateTime.Now; private Logger Log = LogManager.GetCurrentClassLogger(); private string redisBaseKey = "MP:TAB:User"; - private Random rnd = new Random(); - #endregion Private Fields #region Private Properties diff --git a/MP.Data/Services/MonDataFeeder.cs b/MP.Data/Services/MonDataFeeder.cs index 15c151a9..37d6f4b0 100644 --- a/MP.Data/Services/MonDataFeeder.cs +++ b/MP.Data/Services/MonDataFeeder.cs @@ -11,7 +11,7 @@ namespace MP.Data.Services { #region Public Constructors - public MonDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public MonDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpMon.IMpMonRepository mpMonRepository) : base(configuration, redConn, mpMonRepository) { // setup canali pub/sub dataPipe = new MessagePipe(redisConn, Constants.MON_ACT_MSE_DATA_KEY); @@ -113,17 +113,17 @@ namespace MP.Data.Services if (resto == 0) { // invio in channel blink il segnale - blinkPipe.sendMessage("true"); + await blinkPipe.SendMessageAsync("true"); Log.Debug("Elapsed Fast Timer Blink"); } else { // invio in channel blink segnale false - blinkPipe.sendMessage("false"); + await blinkPipe.SendMessageAsync("false"); // rileggo dati... var newData = await MseGetAll(); // invio tramite la pipe... - dataPipe.sendMessage(JsonConvert.SerializeObject(newData)); + await dataPipe.SendMessageAsync(JsonConvert.SerializeObject(newData)); Log.Debug("Elapsed Fast Timer reload"); } }); diff --git a/MP.Data/Services/Mtc/MtcSetupService.cs b/MP.Data/Services/Mtc/MtcSetupService.cs index 8ea00bf4..8a003d9f 100644 --- a/MP.Data/Services/Mtc/MtcSetupService.cs +++ b/MP.Data/Services/Mtc/MtcSetupService.cs @@ -5,6 +5,7 @@ using MP.Data.Repository.Mtc; using StackExchange.Redis; using System.Collections.Generic; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services.Mtc { @@ -18,7 +19,8 @@ namespace MP.Data.Services.Mtc public MtcSetupService( IConfiguration config, IConnectionMultiplexer redis, - IMtcSetupRepository repo) : base(config, redis) + IFusionCache cache, + IMtcSetupRepository repo) : base(config, cache, redis) { _className = "MtcSetup"; _repo = repo; diff --git a/MP.Data/Services/OrderDataSrv.cs b/MP.Data/Services/OrderDataSrv.cs index 19a08304..0f5ec926 100644 --- a/MP.Data/Services/OrderDataSrv.cs +++ b/MP.Data/Services/OrderDataSrv.cs @@ -1,18 +1,17 @@ using Microsoft.Extensions.Configuration; -using MP.Core.Conf; +using MP.Core.Objects; using MP.Data.DbModels; +using MP.Data.Repository.Production; +using MP.Data.Repository.System; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Data; using System.Diagnostics; -using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -21,32 +20,31 @@ namespace MP.Data.Services /// public class OrderDataSrv : BaseServ { + #region Private Fields + + private static Logger Log = LogManager.GetCurrentClassLogger(); + private readonly IProductionRepository _productionRepository; + private readonly ISystemRepository _systemRepository; + private bool _disposed = false; + private string redisBaseKey = "MP:ALL:Cache"; + + #endregion + #region Public Constructors - public OrderDataSrv(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public OrderDataSrv( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache, + IProductionRepository productionRepository, + ISystemRepository systemRepository + ) : base(configuration, cache, redConn) { - // conf DB - string connStr = _configuration.GetConnectionString("MP.All"); - if (string.IsNullOrEmpty(connStr)) - { - Log.Error("ConnString empty!"); - } - else - { - dbController = new Controllers.MpSpecController(configuration); - StringBuilder sb = new StringBuilder(); - sb.AppendLine($"OrderDataSrv | MpSpecController OK"); - Log.Info(sb.ToString()); - } + _productionRepository = productionRepository; + _systemRepository = systemRepository; } - #endregion Public Constructors - - #region Public Properties - - public static Controllers.MpSpecController dbController { get; set; } = null!; - - #endregion Public Properties + #endregion #region Public Methods @@ -71,7 +69,7 @@ namespace MP.Data.Services } else { - result = dbController.ConfigGetAll(); + result = await _systemRepository.ConfigGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); @@ -81,7 +79,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ConfigGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -114,7 +112,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.ListODLFilt(inCorso, CodArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate)); + result = await _productionRepository.ListODLFiltAsync(inCorso, CodArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); @@ -124,7 +122,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ListODLFilt | CodArt: {CodArt} | IdxMacchina: {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ListODLFiltAsync | CodArt: {CodArt} | IdxMacchina: {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -136,12 +134,6 @@ namespace MP.Data.Services { if (!_disposed) { - if (disposing) - { - // Free managed resources here - dbController.Dispose(); - } - // Free unmanaged resources here _disposed = true; } @@ -151,13 +143,5 @@ namespace MP.Data.Services } #endregion Protected Methods - - #region Private Fields - - private static Logger Log = LogManager.GetCurrentClassLogger(); - private bool _disposed = false; - private string redisBaseKey = "MP:ALL:Cache"; - - #endregion Private Fields } } \ No newline at end of file diff --git a/MP.Data/Services/SchedulerDataService.cs b/MP.Data/Services/SchedulerDataService.cs index 46bb8638..6644187f 100644 --- a/MP.Data/Services/SchedulerDataService.cs +++ b/MP.Data/Services/SchedulerDataService.cs @@ -4,6 +4,7 @@ using StackExchange.Redis; using System; using System.Collections.Generic; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -13,7 +14,11 @@ namespace MP.Data.Services /// Init servizio TAB /// /// - public SchedulerDataService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public SchedulerDataService( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache + ) : base(configuration, cache, redConn) { _configuration = configuration; diff --git a/MP.Data/Services/SharedMemService.cs b/MP.Data/Services/SharedMemService.cs index 6609ecc1..93fd6e28 100644 --- a/MP.Data/Services/SharedMemService.cs +++ b/MP.Data/Services/SharedMemService.cs @@ -4,6 +4,7 @@ using NLog; using StackExchange.Redis; using System.Collections.Generic; using System.Linq; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -15,7 +16,11 @@ namespace MP.Data.Services /// Init servizio TAB /// /// - public SharedMemService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public SharedMemService( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache + ) : base(configuration, cache, redConn) { } diff --git a/MP.Data/Services/StatusData.cs b/MP.Data/Services/StatusData.cs index 02b0b848..a267c7cf 100644 --- a/MP.Data/Services/StatusData.cs +++ b/MP.Data/Services/StatusData.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Configuration; using MP.Core.Conf; -using MP.Data.Controllers; using MP.Data.DbModels; using Newtonsoft.Json; using NLog; @@ -20,9 +19,10 @@ namespace MP.Data.Services { #region Public Constructors - public StatusData(IConfiguration configuration, IConnectionMultiplexer redConn) + public StatusData(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpMon.IMpMonRepository mpMonRepository) { _configuration = configuration; + _mpMonRepository = mpMonRepository; // setup componenti REDIS this.redisConn = redConn; @@ -42,9 +42,8 @@ namespace MP.Data.Services } else { - dbController = new MpMonController(configuration); StringBuilder sb = new StringBuilder(); - sb.AppendLine($"StatusData | MpMonController OK"); + sb.AppendLine($"StatusData | MpMonRepository OK"); Log.Info(sb.ToString()); } @@ -70,8 +69,6 @@ namespace MP.Data.Services #region Public Properties - public static MpMonController dbController { get; set; } = null!; - /// /// Dizionario dei tag configurati per IOB /// @@ -102,7 +99,7 @@ namespace MP.Data.Services } else { - result = dbController.ConfigGetAll(); + result = await _mpMonRepository.ConfigGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, LongCache); @@ -112,7 +109,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ConfigGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -186,7 +183,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.MacchineGetAll()); + result = await _mpMonRepository.MacchineGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(currKey, rawData, LongCache); @@ -198,7 +195,6 @@ namespace MP.Data.Services sw.Stop(); Log.Debug($"MacchineGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; - //return Task.FromResult(dbController.MacchineGetAll()); } public async Task> MacchineGetByGruppo(string CodGruppo) @@ -217,8 +213,7 @@ namespace MP.Data.Services } else { - result = await Task.FromResult(dbController.MacchineGetFilt(CodGruppo)); - //result = dbController.MacchineGetFilt(CodGruppo); + result = await _mpMonRepository.MacchineGetFiltAsync(CodGruppo); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(currKey, rawData, LongCache); @@ -339,7 +334,7 @@ namespace MP.Data.Services } else { - result = await dbController.MseGetAllAsync(maxAge); + result = await _mpMonRepository.MseGetAllAsync(maxAge); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(Constants.redisMseKey, rawData, UltraFastCache); @@ -383,8 +378,6 @@ namespace MP.Data.Services MachineProdStatus.Clear(); // REDIS dispose redisDb = null; - // Clear database controller - dbController.Dispose(); } // Free unmanaged resources here @@ -397,6 +390,7 @@ namespace MP.Data.Services #region Private Fields private static IConfiguration _configuration = null!; + private readonly Repository.MpMon.IMpMonRepository _mpMonRepository; private static Logger Log = LogManager.GetCurrentClassLogger(); private bool _disposed = false; @@ -512,7 +506,7 @@ namespace MP.Data.Services if (fileConfData.IobSetup.ContainsKey("***")) { // recupero elenco macchine... - var elencoMacc = dbController.MacchineGetAll(); + var elencoMacc = _mpMonRepository.MacchineGetAllAsync().GetAwaiter().GetResult(); // x ogni macchina creo le righe standard da conf... var baseConf = fileConfData.IobSetup.Where(x => x.Key == "***").FirstOrDefault(); foreach (var item in elencoMacc) diff --git a/MP.Data/Services/TabDataFeeder.cs b/MP.Data/Services/TabDataFeeder.cs index 8d4c00a2..a9cbf01b 100644 --- a/MP.Data/Services/TabDataFeeder.cs +++ b/MP.Data/Services/TabDataFeeder.cs @@ -11,7 +11,7 @@ namespace MP.Data.Services { #region Public Constructors - public TabDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public TabDataFeeder(IConfiguration configuration, IConnectionMultiplexer redConn, Repository.MpMon.IMpMonRepository mpMonRepository) : base(configuration, redConn, mpMonRepository) { // setup canali pub/sub dataPipe = new MessagePipe(redisConn, Constants.TAB_ACT_MSE_DATA_KEY, false); @@ -133,17 +133,17 @@ namespace MP.Data.Services if (resto == 0) { // invio in channel blink il segnale - blinkPipe.sendMessage("true"); + await blinkPipe.SendMessageAsync("true"); Log.Trace("Elapsed Fast Timer Blink"); } else { // invio in channel blink segnale false - blinkPipe.sendMessage("false"); + await blinkPipe.SendMessageAsync("false"); // rileggo dati... var newData = await MseGetAll(); // invio tramite la pipe... - dataPipe.sendMessage(JsonConvert.SerializeObject(newData)); + await dataPipe.SendMessageAsync(JsonConvert.SerializeObject(newData)); Log.Trace("Elapsed Fast Timer reload"); } }); diff --git a/MP.Data/Services/TabDataService.cs b/MP.Data/Services/TabDataService.cs index b12f9bc2..0ee1616f 100644 --- a/MP.Data/Services/TabDataService.cs +++ b/MP.Data/Services/TabDataService.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MP.Core.DTO; using MP.Core.Objects; +using MP.Data.Controllers; using MP.Data.DbModels; using Newtonsoft.Json; using NLog; @@ -15,6 +16,7 @@ using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -26,7 +28,12 @@ namespace MP.Data.Services /// Init servizio TAB /// /// - public TabDataService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public TabDataService( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache, + MpIocController iocContr + ) : base(configuration, cache, redConn) { _configuration = configuration; @@ -41,7 +48,7 @@ namespace MP.Data.Services StringBuilder sb = new StringBuilder(); dbTabController = new Controllers.MpTabController(configuration); sb.AppendLine($"TabDataService | MpTabController OK"); - dbIocController = new Controllers.MpIocController(configuration); + dbIocController = iocContr;// new Controllers.MpIocController(configuration); sb.AppendLine($"TabDataService | MpIocController OK"); dbInveController = new Controllers.MpInveController(configuration); sb.AppendLine($"TabDataService | MpInveController OK"); @@ -392,7 +399,7 @@ namespace MP.Data.Services } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ArticoliGetByTipo | Read from {readType}: {ts.TotalMilliseconds}ms"); + Log.Debug($"ArticoliGetByTipoAsync | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } @@ -505,7 +512,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ConfigGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -1485,7 +1492,7 @@ namespace MP.Data.Services } sw.Stop(); - string callName = $"MacchineByMatrOper.{source}"; + string callName = $"MacchineByMatrOperAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { @@ -2412,7 +2419,7 @@ namespace MP.Data.Services #if false Log.Debug($"PODL_getByKey | {idxPODL} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); #endif - string callName = $"PODL_getByKey.{source}"; + string callName = $"PODL_getByKeyAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { @@ -3417,7 +3424,7 @@ namespace MP.Data.Services result = new StatoMacchineModel(); } sw.Stop(); - Log.Debug($"StatoMacchina | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"StatoMacchinaAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -3498,7 +3505,7 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"TemplateKitFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"TemplateKitFiltAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } @@ -3945,75 +3952,13 @@ namespace MP.Data.Services #region Private Methods - /// - /// Esegue flush memoria _redisConn dato pat2Flush, metodo sincrono - /// - /// - /// - private bool ExecFlushRedisPattern(RedisValue pat2Flush) - { - bool answ = false; - var masterEndpoint = _redisConn.GetEndPoints() - .Where(ep => _redisConn.GetServer(ep).IsConnected && !_redisConn.GetServer(ep).IsReplica) - .FirstOrDefault(); - - // sepattern è "*" elimino intero DB... - if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null)) - { - _redisConn.GetServer(masterEndpoint).FlushDatabase(database: _redisDb.Database); - } - else - { - var server = _redisConn.GetServer(masterEndpoint); - var keys = server.Keys(database: _redisDb.Database, pattern: pat2Flush, pageSize: 1000); - var batch = new List(); - foreach (var key in keys) - { - batch.Add(key); - - // Flush in batches of 1000 - if (batch.Count >= 1000) - { - foreach (var item in batch) - _redisDb.KeyDelete(item); - - batch.Clear(); - } - } - - // Flush remaining keys - foreach (var item in batch) - _redisDb.KeyDelete(item); - } - answ = true; -#if 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; - } - } -#endif - // notifico update ai client in ascolto x reset cache - NotifyReloadRequest($"FlushRedisCache | {pat2Flush}"); - return answ; - } /// /// Esegue flush memoria _redisConn dato pat2Flush in async /// /// /// - private async Task ExecFlushRedisPatternAsync(RedisValue pat2Flush) + private async new Task ExecFlushRedisPatternAsync(RedisValue pat2Flush) { bool answ = false; var masterEndpoint = _redisConn.GetEndPoints() diff --git a/MP.Data/Services/TranslateSrv.cs b/MP.Data/Services/TranslateSrv.cs index 10af4614..f3ffdfde 100644 --- a/MP.Data/Services/TranslateSrv.cs +++ b/MP.Data/Services/TranslateSrv.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Configuration; using MP.Core.Conf; using MP.Data.DbModels; +using MP.Data.Repository.FluxLog; using Newtonsoft.Json; using NLog; using StackExchange.Redis; @@ -13,6 +14,7 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services { @@ -23,35 +25,57 @@ namespace MP.Data.Services { #region Public Constructors - public TranslateSrv(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public TranslateSrv( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache, + Repository.MpVoc.IMpVocRepository mpVocRepository + ) : base(configuration, cache, redConn) { - Stopwatch sw = new Stopwatch(); - sw.Start(); - // conf DB - string connStr = _configuration.GetConnectionString("MP.Voc"); - if (string.IsNullOrEmpty(connStr)) - { - Log.Error("MP.Voc: ConnString empty!"); - } - else - { - dbController = new Controllers.MpVocController(configuration); - InitDict(); - sw.Stop(); - Log.Info($"TranslateSrv | MpVocController OK | {sw.Elapsed.TotalMilliseconds} ms"); - } + _mpVocRepository = mpVocRepository; } #endregion Public Constructors - #region Public Properties - - public static Controllers.MpVocController dbController { get; set; } = null!; - - #endregion Public Properties - #region Public Methods + /// + /// Esegue traduzione dato vocabolario da Lingua + Lemma + /// + /// + /// + /// + public string Traduci(string lemma, string lingua = "IT") + { + if (string.IsNullOrWhiteSpace(lemma)) return string.Empty; + if (string.IsNullOrWhiteSpace(lingua)) return lemma; + + string linguaKey = lingua.ToLowerInvariant().Trim(); + string cacheKey = $"vocab:{linguaKey}"; + + // FusionCache gestisce il lock e recupera l'intero dizionario della lingua. + // Se è in L1 (Memory), restituisce l'oggetto C# istantaneamente. + // Se non c'è, passa a L2 (Redis) o invoca la factory per caricarlo. + var dizionarioLingua = _cache.GetOrSet>( + cacheKey, + _ => _mpVocRepository.VocabolarioGetLang(linguaKey), + options => options + .SetDuration(TimeSpan.FromHours(8)) // Durata logica della cache + .SetFailSafe(true, TimeSpan.FromHours(1)) // Se Redis/DB è giù, usa i vecchi dati L1 + ); + + // Ricerca O(1) nel dizionario in memoria + if (dizionarioLingua != null && dizionarioLingua.TryGetValue(lemma, out var traduzione)) + { + return traduzione; + } + + // Fallback: se la parola non è censita, restituisce il lemma originale (lingua + lemma) + return $"{lingua}_{lemma}"; + } + + +#if false /// /// Recupero elenco config /// @@ -73,7 +97,7 @@ namespace MP.Data.Services } else { - result = dbController.ConfigGetAll(); + result = await _mpVocRepository.ConfigGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); @@ -83,9 +107,10 @@ namespace MP.Data.Services result = new List(); } sw.Stop(); - Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"ConfigGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; - } + } +#endif /// /// Pulizia cache Redis (tutta) @@ -93,12 +118,15 @@ namespace MP.Data.Services /// public async Task FlushCache() { +#if false RedisValue pattern = new RedisValue($"{redisBaseKey}:*"); bool answ = await ExecFlushRedisPattern(pattern); // rileggo vocabolario! var rawData = await VocabolarioGetAll(); DictVocab = rawData.ToDictionary(kvp => $"{kvp.Lingua}_{kvp.Lemma}".ToUpper(), kvp => kvp.Traduzione); - return answ; + return answ; +#endif + return await FlushFusionCacheAsync(); } /// @@ -107,9 +135,51 @@ namespace MP.Data.Services /// public async Task FlushCache(string KeyReq) { +#if false RedisValue pattern = new RedisValue($"{redisBaseKey}:{KeyReq}:*"); bool answ = await ExecFlushRedisPattern(pattern); - return answ; + return answ; +#endif + return await FlushFusionCacheAsync(KeyReq); + } + + /// + /// Cancellazione FusionCache (totale) + /// + /// + private async Task FlushFusionCacheAsync() + { + await _cache.ClearAsync(allowFailSafe: false); + return true; + } + + /// + /// Cancellazione FusionCache dato singolo tag + /// + /// + private async Task FlushFusionCacheAsync(string tag) + { + if (string.IsNullOrWhiteSpace(tag)) return false; + + await _cache.RemoveByTagAsync(tag); + return true; + } + + /// + /// Cancellazione FusionCache dato elenco tags + /// + /// + private async Task FlushFusionCacheAsync(List listTags) + { + if (listTags == null || listTags.Count == 0) return false; + + // Generiamo i Task di rimozione ed eseguiamoli in parallelo su Redis/L1 + var tasks = listTags + .Where(tag => !string.IsNullOrWhiteSpace(tag)) + .Select(tag => _cache.RemoveByTagAsync(tag).AsTask()); + + await Task.WhenAll(tasks); + return true; } /// @@ -118,6 +188,17 @@ namespace MP.Data.Services /// public async Task> LingueGetAll() { + string currKey = $"{redisBaseKey}:Lang"; + + return await GetOrFetchAsync( + operationName: "LingueGetAll", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _mpVocRepository.LingueGetAllAsync() ?? new(), + tagList: [currKey] + ); + +#if false string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); @@ -133,7 +214,7 @@ namespace MP.Data.Services } else { - result = dbController.LingueGetAll(); + result = await _mpVocRepository.LingueGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); @@ -144,9 +225,11 @@ namespace MP.Data.Services } sw.Stop(); Log.Debug($"LingueGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; + return result; +#endif } +#if false /// /// Traduzione termine /// @@ -162,7 +245,8 @@ namespace MP.Data.Services answ = DictVocab[key]; } return answ; - } + } +#endif /// /// Recupero elenco config @@ -170,6 +254,18 @@ namespace MP.Data.Services /// public async Task> VocabolarioGetAll() { + string currKey = $"{redisBaseKey}:VocAll"; + + return await GetOrFetchAsync( + operationName: "VocabolarioGetAll", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _mpVocRepository.VocabolarioGetAllAsync() ?? new(), + tagList: [currKey] + ); + + +#if false string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); @@ -185,7 +281,7 @@ namespace MP.Data.Services } else { - result = dbController.VocabolarioGetAll(); + result = await _mpVocRepository.VocabolarioGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); @@ -196,63 +292,41 @@ namespace MP.Data.Services } sw.Stop(); Log.Debug($"VocabolarioGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; + return result; +#endif } #endregion Public Methods #region Protected Fields +#if false /// /// Vocabolario x recupero rapido traduzioni /// - protected static Dictionary DictVocab = new Dictionary(); + protected static Dictionary DictVocab = new Dictionary(); +#endif #endregion Protected Fields #region Protected Methods - protected override void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - // Free managed resources here - DictVocab.Clear(); - dbController.Dispose(); - } - - // Free unmanaged resources here - _disposed = true; - } - - // Call base class implementation. - base.Dispose(disposing); - } - #endregion Protected Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); - private bool _disposed = false; + private string redisBaseKey = "MP:Voc:Cache"; + private readonly Repository.MpVoc.IMpVocRepository _mpVocRepository; + #endregion Private Fields #region Private Methods - /// - /// Inizializzazione dict vari - /// - private static void InitDict() - { - // inizializzo dizionario vocabolario - var rawData = dbController.VocabolarioGetAll(); - DictVocab = rawData.ToDictionary(kvp => $"{kvp.Lingua}_{kvp.Lemma}".ToUpper(), kvp => kvp.Traduzione); - } +#if false /// /// Esegue flush memoria _redisConn dato pat2Flush /// @@ -291,26 +365,10 @@ namespace MP.Data.Services } } answ = true; -#if 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) - { - await redisDb.KeyDeleteAsync(item); - } - answ = true; - } - } -#endif return answ; - } + } +#endif #endregion Private Methods } diff --git a/MP.Data/Services/Utils/StatsAggrService.cs b/MP.Data/Services/Utils/StatsAggrService.cs index 411b463c..a322b84e 100644 --- a/MP.Data/Services/Utils/StatsAggrService.cs +++ b/MP.Data/Services/Utils/StatsAggrService.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services.Utils { @@ -19,7 +20,8 @@ namespace MP.Data.Services.Utils public StatsAggrService( IConfiguration config, IConnectionMultiplexer redis, - IStatsAggrRepository repo) : base(config, redis) + IFusionCache cache, + IStatsAggrRepository repo) : base(config, cache, redis) { _className = "StatsAggr"; _repo = repo; diff --git a/MP.Data/Services/Utils/StatsCodeService.cs b/MP.Data/Services/Utils/StatsCodeService.cs index 3d2bf4df..8e2b262b 100644 --- a/MP.Data/Services/Utils/StatsCodeService.cs +++ b/MP.Data/Services/Utils/StatsCodeService.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services.Utils { @@ -19,7 +20,9 @@ namespace MP.Data.Services.Utils public StatsCodeService( IConfiguration config, IConnectionMultiplexer redis, - IStatsCodeRepository repo) : base(config, redis) + IFusionCache cache, + IStatsCodeRepository repo + ) : base(config, cache, redis) { _className = "StatsStatusCode"; _repo = repo; diff --git a/MP.Data/Services/Utils/StatsDetailService.cs b/MP.Data/Services/Utils/StatsDetailService.cs index 75738f4d..b637b33d 100644 --- a/MP.Data/Services/Utils/StatsDetailService.cs +++ b/MP.Data/Services/Utils/StatsDetailService.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services.Utils { @@ -19,7 +20,9 @@ namespace MP.Data.Services.Utils public StatsDetailService( IConfiguration config, IConnectionMultiplexer redis, - IStatsDetailRepository repo) : base(config, redis) + IFusionCache cache, + IStatsDetailRepository repo + ) : base(config,cache, redis) { _className = "StatsDetail"; _repo = repo; diff --git a/MP.Data/Services/Utils/StatsErrService.cs b/MP.Data/Services/Utils/StatsErrService.cs index 26e76309..36e5c8e4 100644 --- a/MP.Data/Services/Utils/StatsErrService.cs +++ b/MP.Data/Services/Utils/StatsErrService.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Data.Services.Utils { @@ -19,7 +20,9 @@ namespace MP.Data.Services.Utils public StatsErrService( IConfiguration config, IConnectionMultiplexer redis, - IStatsErrRepository repo) : base(config, redis) + IFusionCache cache, + IStatsErrRepository repo + ) : base(config,cache, redis) { _className = "StatsErr"; _repo = repo; diff --git a/MP.INVE/MP.INVE.csproj b/MP.INVE/MP.INVE.csproj index 7019b116..ef7907fa 100644 --- a/MP.INVE/MP.INVE.csproj +++ b/MP.INVE/MP.INVE.csproj @@ -5,7 +5,7 @@ enable enable MP.INVE - 8.16.2604.2716 + 8.16.2606.408 diff --git a/MP.INVE/Resources/ChangeLog.html b/MP.INVE/Resources/ChangeLog.html index d27ae967..878755a2 100644 --- a/MP.INVE/Resources/ChangeLog.html +++ b/MP.INVE/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOINVE -

    Versione: 8.16.2604.2716

    +

    Versione: 8.16.2606.408


    Note di rilascio:
    • diff --git a/MP.INVE/Resources/VersNum.txt b/MP.INVE/Resources/VersNum.txt index e7a88a55..988a0006 100644 --- a/MP.INVE/Resources/VersNum.txt +++ b/MP.INVE/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2604.2716 +8.16.2606.408 diff --git a/MP.INVE/Resources/manifest.xml b/MP.INVE/Resources/manifest.xml index e7edcec6..e69c68e1 100644 --- a/MP.INVE/Resources/manifest.xml +++ b/MP.INVE/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2604.2716 + 8.16.2606.408 https://nexus.steamware.net/repository/SWS/MP-INVE/stable/LAST/MP.INVE.zip https://nexus.steamware.net/repository/SWS/MP-INVE/stable/LAST/ChangeLog.html false diff --git a/MP.IOC/Controllers/IOBController.cs b/MP.IOC/Controllers/IOBController.cs index 4a486ff9..f0ebee6c 100644 --- a/MP.IOC/Controllers/IOBController.cs +++ b/MP.IOC/Controllers/IOBController.cs @@ -147,7 +147,7 @@ namespace MP.IOC.Controllers /// /// Sistema Dossier/Snapshot giornalieri x impianto indicato, andando a generare 1 Dossier /// giornaliero x ogni giornata dall'ultimo registrato alla data corrente - /// es: http://url_site/MP/IO/IOB/fixDailyDossier/SIMUL_03 + /// es: http://url_site/MP/IOC/api/IOB/fixDailyDossier/SIMUL_03 /// /// /// @@ -174,7 +174,7 @@ namespace MP.IOC.Controllers /// /// Sistema ODL giornalieri x impianto indicato, andando a generare 1 ODL giornaliero x ogni /// giornata dall'ultimo ODL aperto alla data corrente - /// es: http://url_site/MP/IO/IOB/fixDailyOdl/SIMUL_03 + /// es: http://url_site/MP/IOC/api/IOB/fixDailyOdl/SIMUL_03 /// /// /// @@ -218,7 +218,7 @@ namespace MP.IOC.Controllers /// Sistema ODL giornalieri x impianto indicato, andando a generare 1 ODL giornaliero x ogni /// giornata dall'ultimo ODL aperto alla data corrente + conferma pezzi (es TFT x ODL /// giornalieri energia) - /// es: http://url_site/MP/IO/IOB/fixDailyOdlConfPzCount/SIMUL_03 + /// es: http://url_site/MP/IOC/api/IOB/fixDailyOdlConfPzCount/SIMUL_03 ///
    /// /// @@ -525,7 +525,7 @@ namespace MP.IOC.Controllers /// /// Restituisce data-ora inizio dell'odl correntemente in lavorazione sulla macchina... - /// es: http://url_site/MP/IO/IOB/getCurrOdlStart/SIMUL_03 + /// es: http://url_site/MP/IOC/api/IOB/getCurrOdlStart/SIMUL_03 /// /// /// diff --git a/MP.IOC/Data/MpDataService.cs b/MP.IOC/Data/MpDataService.cs index 922965f3..87ed22a2 100644 --- a/MP.IOC/Data/MpDataService.cs +++ b/MP.IOC/Data/MpDataService.cs @@ -7,6 +7,7 @@ using MP.Data.Controllers; using MP.Data.DbModels; using MP.Data.DbModels.Anag; using MP.Data.MgModels; +using MP.Data.Repository.Production; using MP.Data.Services.IOC; using MP.Data.Services.Mtc; using Newtonsoft.Json; @@ -19,20 +20,25 @@ using static MP.Core.Objects.Enums; namespace MP.IOC.Data { - public class MpDataService : IDisposable + public class MpDataService { #region Public Constructors + private readonly IProductionRepository _productionRepository; public MpDataService( IConfiguration configuration, ILogger logger, IServiceScopeFactory scopeFactory, + IProductionRepository productionRepository, + MpIocController mpIocCtr, IMtcSetupService mtcServ) { _logger = logger; _logger.LogInformation("Starting MpDataService INIT"); _configuration = configuration; _scopeFactory = scopeFactory; + _productionRepository = productionRepository; + IocDbController = mpIocCtr; // setup compoenti REDIS redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis")); @@ -58,8 +64,10 @@ namespace MP.IOC.Data } else { - SpecDbController = new MpSpecController(configuration); +#if false + SpecDbController = new MpSpecController(configuration); IocDbController = new MpIocController(configuration); +#endif Log.Info("DbControllers INIT OK"); } @@ -83,9 +91,11 @@ namespace MP.IOC.Data #region Public Properties - public static MpIocController IocDbController { get; set; } = null!; public static MpMongoController mongoController { get; set; } = null!; - public static MpSpecController SpecDbController { get; set; } = null!; + public static MpIocController IocDbController { get; set; } = null!; +#if false + public static MpSpecController SpecDbController { get; set; } = null!; +#endif public MessagePipe BroadastMsgPipe { get; set; } = null!; /// @@ -97,51 +107,6 @@ namespace MP.IOC.Data #region Public Methods - /// - /// Recupera eventuali azioni richieste - /// - /// - public async Task ActionGetReq() - { - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - DisplayAction? result = null; - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisActionReq); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject($"{rawData}"); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ActionGetReq Read from REDIS: {ts.TotalMilliseconds}ms"); - } - if (result == null) - { - result = new DisplayAction(); - } - return result; - } - - /// - /// Salva richiesta azione - /// - /// - /// - public bool ActionSetReq(DisplayAction? act2save) - { - bool fatto = false; - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - // cerco in redis... - string rawData = JsonConvert.SerializeObject(act2save); - // invio broadcast + salvo in redis - BroadastMsgPipe.saveAndSendMessage(Utils.redisActionReq, rawData); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ActionSetReq REDIS send to broadcast + Write cache: {ts.TotalMilliseconds}ms"); - return fatto; - } - /// /// Verifica se sia da reinviare un tName alla macchina dall'elenco di quelli salvati (in /// modalità upsert) se non scaduti @@ -355,37 +320,6 @@ namespace MP.IOC.Data return answ; } - public async Task> AnagStatiComm() - { - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - List? result = new List(); - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisStatoCom); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"AnagStatiComm Read from REDIS: {ts.TotalMilliseconds}ms"); - } - else - { - result = await Task.FromResult(SpecDbController.AnagStatiComm()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Utils.redisStatoCom, rawData, getRandTOut(redisLongTimeCache)); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"AnagStatiComm Read from DB: {ts.TotalMilliseconds}ms"); - } - if (result == null) - { - result = new List(); - } - return result; - } - /// /// Restituisce l'anagrafica STATI per intero /// @@ -410,83 +344,6 @@ namespace MP.IOC.Data return dbResult; } - public async Task> AnagTipoArtLV() - { - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string source = "DB"; - List? result = new List(); - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisTipoArt); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.AnagTipoArtLV()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Utils.redisTipoArt, rawData, getRandTOut(redisLongTimeCache)); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"AnagTipoArtLV Read from {source}: {ts.TotalMilliseconds}ms"); - if (result == null) - { - result = new List(); - } - return result; - } - - /// - /// Elenco Codice articolo con dati dossier gestiti - /// - /// - public async Task> ArticleWithDossier() - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = Utils.redisArtByDossier; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.ArticleWithDossier()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ArticleWithDossier | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Eliminazione record selezionato - /// - /// - /// - public async Task ArticoliDeleteRecord(AnagArticoliModel currRec) - { - bool fatto = await SpecDbController.ArticoliDeleteRecord(currRec); - await resetCacheArticoli(); - return fatto; - } - /// /// Elenco ultimi articoli data amcchina /// @@ -523,123 +380,6 @@ namespace MP.IOC.Data return result; } - /// - /// Restitusice elenco articoli cercati - /// - /// - /// - /// - public async Task> ArticoliGetSearch(int numRecord, string azienda, string searchVal) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string sKey = string.IsNullOrEmpty(searchVal) ? "***" : searchVal; - string currKey = $"{Utils.redisArtList}:{azienda}:{sKey}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.ArticoliGetSearch(numRecord, azienda, searchVal)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ArticoliGetSearch | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Aggiornamento record selezionato - /// - /// - /// - public async Task ArticoliUpdateRecord(AnagArticoliModel currRec) - { - bool fatto = await SpecDbController.ArticoliUpdateRecord(currRec); - await resetCacheArticoli(); - return fatto; - } - - /// - /// Verifica se sia possiubile cancellare articolo dato suo CodArt cercando su redis o su - /// tab veto da DB - /// - /// - /// - public bool ArticoloDelEnabled(object CodArt) - { - bool answ = false; - string codArticolo = $"{CodArt}"; - int cacheCheckArtUsato = 1; - int.TryParse(_configuration.GetValue("ServerConf:cacheCheckArtUsato"), out cacheCheckArtUsato); - TimeSpan TTLCache = getRandTOut(cacheCheckArtUsato); - // cerco in cache redis... - string redKeyArtUsed = $"{Utils.redKeyArtUsed}:{codArticolo}"; - string redKeyTabCheckArt = Utils.redKeyTabCheckArt; - var rawData = redisDb.StringGet(redKeyArtUsed); - if (!string.IsNullOrEmpty(rawData)) - { - bool.TryParse(rawData, out answ); - } - else - { - // controllo non sia stato mai prodotto sennò non posso cancellare... - try - { - // cerco in cache se ci sia la tabella con gli articoli impiegati... - var rawTable = redisDb.StringGet(redKeyTabCheckArt); - List? artList = new List(); - if (!string.IsNullOrEmpty(rawTable)) - { - artList = JsonConvert.DeserializeObject>($"{rawTable}"); - } - // rileggo... - if (artList == null || artList.Count == 0) - { - artList = new List(); - var tabArticoli = SpecDbController.ArticoliGetUsed(); - var codList = tabArticoli.Select(x => x.CodArticolo); - foreach (string cod in codList) - { - artList.Add(cod); - } - // SE fosse vuoto aggiungo comunque il cado "ND"... - if (artList.Count == 0) - { - artList.Add("ND"); - } - // salvo - rawTable = JsonConvert.SerializeObject(artList); - redisDb.StringSet(redKeyTabCheckArt, rawTable, TTLCache); - } - // cerco nella tabella: se ci fosse --> disabilitato delete - bool usato = false; - if (artList != null && artList.Count > 0) - { - usato = artList.Contains(codArticolo); - } - answ = !usato; - redisDb.StringSet(redKeyArtUsed, $"{answ}", TTLCache); - } - catch - { } - } - return answ; - } - /// /// Effettua split ODL /// @@ -1067,7 +807,6 @@ namespace MP.IOC.Data else { result = await IocDbController.ConfigGetAllAsync(); - //result = await Task.FromResult(SpecDbController.ConfigGetAllAsync()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); @@ -1082,59 +821,6 @@ namespace MP.IOC.Data return result; } - /// - /// Reset dati cache config - /// - /// - public async Task ConfigResetCache() - { - await redisDb.StringSetAsync(Utils.redisConfKey, ""); - } - - /// - /// Update chiave config - /// - /// - public async Task ConfigUpdate(ConfigModel updRec) - { - return await Task.FromResult(SpecDbController.ConfigUpdate(updRec)); - } - - /// - /// Elenco completo valori DatiMacchine - /// - /// - public async Task> DatiMacchineGetAll() - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisBaseAddr}:TabDatiMacchine:ALL"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.DatiMacchineGetAll()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"DatiMacchineGetAll | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - public async Task> DecNumArtGetFiltAsync(string codArt = "") { List result = new(); @@ -1156,17 +842,6 @@ namespace MP.IOC.Data return result; } - /// - /// Dispose del connettore ai dati - /// - public void Dispose() - { - // Clear database controller - SpecDbController.Dispose(); - mongoController.Dispose(); - redisConn.Dispose(); - } - /// /// Restituisce l'elenco delle date dei dossier x una macchina (se presenti) Impiegata anche /// cache redis @@ -1197,207 +872,6 @@ namespace MP.IOC.Data return result; } - /// - /// Eliminazione di un dossier - /// - /// record dossier da eliminare - /// - public async Task DossiersDeleteRecord(DossierModel selRecord) - { - bool result = false; - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - result = await SpecDbController.DossiersDeleteRecord(selRecord); - // elimino cache redis... - RedisValue pattern = new RedisValue($"{Utils.redisDossByMac}:*"); - bool answ = await RedisFlushPatternAsync(pattern); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"DossiersDeleteRecord | IdxMacchina {selRecord.IdxMacchina} | DtRif {selRecord.DtRif} | IdxODL {selRecord.IdxODL} | {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato - /// macchina (ordinato x data registrazione) - /// - /// * = tutte, altrimenti solo x una data macchina - /// Data minima per estrazione records - /// Data Massima per estrazione records - /// Num Max records da recuperare - /// - public async Task> DossiersGetLastFilt(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisDossByMac}:{IdxMacchina}:{CodArticolo}:{DtStart:yyyyMMddHHmm}:{DtEnd:yyyyMMddHHmm}:{MaxRec}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await SpecDbController.DossiersGetLastFiltAsync(IdxMacchina, CodArticolo, DtStart, DtEnd, MaxRec); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"DossiersGetLastFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Inserimento nuovo record dossier - /// - /// - /// - public async Task DossiersInsert(DossierModel currDoss) - { - // aggiorno record sul DB - bool answ = await SpecDbController.DossiersInsert(currDoss); - - return answ; - } - - /// - /// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache redis - /// - /// macchina - /// NUm massimo secondi per recuperare dati correnti - /// DataOra riferimento x cui prendere valori antecedenti - /// - public async Task DossiersTakeParamsSnapshotLast(string IdxMacchina, DateTime dtMin, DateTime dtMax) - { - bool answ = false; - await Task.Delay(1); - Log.Info($"Richiesta snapshot per macchina {IdxMacchina} | periodo {dtMin} --> {dtMax}"); - // chiamo stored x salvare parametri - SpecDbController.DossiersTakeParamsSnapshotLast(IdxMacchina, dtMin, dtMax); - // elimino cache redis... - RedisValue pattern = new RedisValue($"{Utils.redisDossByMac}:*"); - answ = await RedisFlushPatternAsync(pattern); - Log.Info($"Svuotata cache dossier | {pattern}"); - return answ; - } - - /// - /// Update valOut dossier - /// - /// - /// - public async Task DossiersUpdateValore(DossierModel currDoss) - { - // aggiorno record sul DB - bool answ = await SpecDbController.DossiersUpdateValore(currDoss); - - return answ; - } - - /// - /// Restitusice elenco aziende - /// - /// - public Task> ElencoAziende() - { - return Task.FromResult(SpecDbController.AnagGruppiAziende()); - } - - /// - /// Restitusice elenco fasi - /// - /// - public Task> ElencoGruppiFase() - { - List result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisAnagGruppi}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - var rawResult = JsonConvert.DeserializeObject>($"{rawData}"); - if (rawResult != null) - { - result = rawResult; - } - readType = "REDIS"; - } - else - { - result = SpecDbController.AnagGruppiFase(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ElencoGruppiFase | Read from {readType}: {ts.TotalMilliseconds}ms"); - return Task.FromResult(result); - } - - public Task> ElencoLink() - { - return Task.FromResult(SpecDbController.ElencoLink()); - } - - /// - /// Aggiunta record EventList - /// - /// - /// - public async Task EvListInsert(EventListModel newRec) - { - return await SpecDbController.EvListInsert(newRec); - } - - /// - /// Imposta in redis la scadenza della pagina x il reload - /// - /// - /// - public DateTime ExpiryReloadParamGet() - { - DateTime dtRif = DateTime.Now; - string currKey = $"{Utils.redisParamPageExp}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - dtRif = JsonConvert.DeserializeObject($"{rawData}"); - } - return dtRif; - } - - /// - /// Imposta in redis la scadenza della pagina x il reload - /// - /// - /// - public bool ExpiryReloadParamSet(DateTime expTime) - { - bool fatto = false; - string currKey = $"{Utils.redisParamPageExp}"; - string rawData = JsonConvert.SerializeObject(expTime); - fatto = redisDb.StringSet(currKey, rawData); - return fatto; - } - /// /// Task completo sistemazione dossier quotidiani mancanti /// @@ -1479,93 +953,6 @@ namespace MP.IOC.Data return answ; } - public async Task FlushRedisCache() - { - await Task.Delay(1); - RedisValue pattern = Utils.RedValue("*"); - bool answ = await RedisFlushPatternAsync(pattern); - // rileggo vocabolario.,.. - ObjVocabolario = VocabolarioGetAll(); - return answ; - } - - public async Task FlushRedisKey(string redKey) - { - await Task.Delay(1); - RedisValue pattern = Utils.RedValue(redKey); - bool answ = await RedisFlushPatternAsync(pattern); - return answ; - } - - public List FluxLogDtoGetByFlux(string Valore) - { - List answ = new List(); - DossierFluxLogDTO? result = JsonConvert.DeserializeObject(Valore); - if (result != null) - { - if (result.ODL != null) - { - answ = result - .ODL - .OrderBy(x => x.CodFlux) - .ToList(); - // inizializzo SE necessario - foreach (var item in answ) - { - item.ValoreEdit = String.IsNullOrEmpty(item.ValoreEdit) ? item.Valore : item.ValoreEdit; - } - } - } - return answ; - } - - /// - /// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione) - /// - /// Data massima x eventi - /// Data minima x eventi - /// * = tutte, altrimenti solo x una data macchina - /// *=tutti, altrimenti solo selezionato - /// numero massimo record da restituire - /// - public async Task> FluxLogGetLastFilt(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec, double redisCacheSec) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisFluxLogFilt}:{IdxMacchina}:{CodFlux}:{MaxRec}:{DtMax:yyyyMMddHHmm}:{DtMin:yyyyMMddHHmm}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.FluxLogGetLastFilt(DtMax, DtMin, IdxMacchina, CodFlux, MaxRec)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - if (string.IsNullOrEmpty(canCacheParametri)) - { - canCacheParametri = await tryGetConfigAsync("SPEC_ParametriEnableRedisCache"); - } - if (canCacheParametri != "false") - { - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisCacheSec)); - } - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"FluxLogGetLastFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - /// /// Restituisce il valOut dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza /// ODL NO invio/gestione ODL) @@ -1592,32 +979,6 @@ namespace MP.IOC.Data return result; } - /// - /// Restituisce il valOut dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza - /// ODL NO invio/gestione ODL) - /// - /// - /// indica se forzare lettura da db (true) o meno - /// - public async Task GetCurrOdlAsync(string idxMacchina, bool forceDb) - { - string answ = ""; - // se ho forceDB leggo dai dati prod... - if (forceDb) - { - var datiProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now, true); - if (datiProd != null) - { - answ = datiProd.IdxOdl.ToString(); - } - } - else - { - answ = await GetCurrOdlAsync(idxMacchina); - } - return answ; - } - /// /// Restituisce il valOut dell'ultimo ODL /// @@ -1695,29 +1056,6 @@ namespace MP.IOC.Data return dataOraEvento; } - /// - /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato - /// - /// - /// - public async Task> GetTask2ExeMacchinaAsync(string idxMacchina) - { - var currHash = Utils.RedKeyTask2ExeMacc(idxMacchina, MpIoNS); - return await RedisGetHashDictAsync(currHash); - } - - /// - /// Init ricetta - /// - /// - /// - /// - /// - public RecipeModel InitRecipe(string confPath, int idxPODL, Dictionary CalcArgs) - { - return mongoController.InitRecipe(confPath, idxPODL, CalcArgs); - } - /// /// Restituisce il valOut booleano se la macchina sia abilitata all'input /// @@ -1795,41 +1133,6 @@ namespace MP.IOC.Data return answ; } - /// - /// - /// idxMacc odl da cercare - /// - public async Task> ListGiacenze(int IdxOdl) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisGiacenzaList}:{IdxOdl}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.ListGiacenze(IdxOdl)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ListGiacenze | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - public async Task> ListValuesFilt(string tabName, string fieldName) { List resultList = new List(); @@ -1916,7 +1219,7 @@ namespace MP.IOC.Data } else { - result = await Task.FromResult(SpecDbController.MacchineGetFilt(codGruppo)); + result = await _productionRepository.MacchineGetFiltAsync(codGruppo); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); @@ -1966,113 +1269,6 @@ namespace MP.IOC.Data return result ?? ""; } - /// - /// Verifica se la macchina abbia un codice CONF ricetta associato - /// - /// - /// - public async Task MacchineRecipeConf(string idxMacchina) - { - string? result = ""; - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisMacRecipeConf}:{idxMacchina}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject($"{rawData}"); - readType = "REDIS"; - } - else - { - //recupero elenco macchine... - var machineList = await MacchineGetFilt("*"); - var currMach = machineList.Where(x => x.IdxMacchina == idxMacchina).FirstOrDefault(); - result = currMach != null ? currMach.RecipePath : null; - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"MacchineRecipeConf | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result ?? ""; - } - - /// - /// Elenco idxMacc Macchine che abbiano dati FLuxLog, nel periodo indicato - /// - /// - /// - /// - public async Task> MacchineWithFlux(DateTime dtStart, DateTime dtEnd) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisMacByFlux}:{dtStart:yyyyMMddHHmm}:{dtEnd:yyyyMMddHHmm}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await SpecDbController.MacchineWithFlux(dtStart, dtEnd); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"MacchineWithFlux | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Lista parametri correnti (ObjItemDTO) della macchina (ex getCurrObjItems) - /// - /// - /// - public List MachineParamList(string idxMacchina) - { - // setup parametri costanti - string source = "NA"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - List? result = new List(); - // cerco in _redisConn... - var currKey = Utils.RedKeyCurrObjItems(idxMacchina, MpIoNS); - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue && rawData.Length() > 2) - { - var rawVal = JsonConvert.DeserializeObject>($"{rawData}"); - // ordino! - result = rawVal - .OrderBy(x => x.displOrdinal) - .ThenBy(x => x.description) - .ToList(); - source = "REDIS"; - } - if (result == null) - { - result = new List(); - source = "NONE"; - } - sw.Stop(); - Log.Debug($"MachineParamList | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; - } - /// /// Lista parametri correnti (ObjItemDTO) della macchina (ex getCurrObjItems) /// @@ -2378,94 +1574,6 @@ namespace MP.IOC.Data return result; } - /// - /// Elenco ODL dato batch selezionato - /// - /// Batch richiesto - /// - public async Task> OdlByBatch(string BatchSel) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = Utils.redisOdlByBatch; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.OdlByBatch(BatchSel)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"OdlByBatch | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// ODL da chiave - /// - /// - /// - public ODLExpModel OdlByKey(int IdxOdl) - { - ODLExpModel? result = new ODLExpModel(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - result = SpecDbController.OdlByKey(IdxOdl); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"OdlByKey | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Effettua chiusura dell'ODL indicato, andand - /// - /// idx odl da chiudere - /// idx macchina - /// matricola operatore - /// indica se confermare i pezzi priam di chiudere ODL - public async Task ODLClose(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi) - { - bool fatto = false; - await Task.Delay(1); - // recupero dati x conf modalità conferma - var configData = await ConfigGetAllAsync(); - if (configData != null) - { - bool confRett = false; - var currRec = configData.FirstOrDefault(x => x.Chiave == "confRett"); - if (currRec != null) - { - bool.TryParse(currRec.Valore, out confRett); - } - int modoConfProd = 0; - currRec = configData.FirstOrDefault(x => x.Chiave == "modoConfProd"); - if (currRec != null) - { - int.TryParse(currRec.Valore, out modoConfProd); - } - // chiamo metodo conferma! - fatto = await SpecDbController.ODLClose(idxOdl, idxMacchina, matrOpr, confPezzi, confRett, modoConfProd); - } - - return fatto; - } - public async Task OdlCurrByMaccAsync(string IdxMacchina) { ODLExpModel result = new(); @@ -2497,182 +1605,6 @@ namespace MP.IOC.Data return result; } - /// - /// Record ODL da chaive - /// - /// - public async Task OdlGetByKey(int IdxOdl) - { - await Task.Delay(1); - var dbResult = await SpecDbController.OdlGetByKey(IdxOdl); - return dbResult; - } - - /// - /// ODL correnti (tutti) - /// - /// - /// - public List OdlGetCurrent() - { - List? dbResult = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisOdlCurrByMac}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - try - { - dbResult = JsonConvert.DeserializeObject>($"{rawData}"); - } - catch - { } - readType = "REDIS"; - } - else - { - dbResult = SpecDbController.OdlGetCurrent().Select(x => x.IdxMacchina).Distinct().ToList(); - rawData = JsonConvert.SerializeObject(dbResult); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(3)); - } - if (dbResult == null) - { - dbResult = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"OdlGetCurrent | Read from {readType}: {ts.TotalMilliseconds}ms"); - - return dbResult; - } - - /// - /// elenco TUTTI gli ODL - /// - /// - /// - public List OdlListAll() - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - result = SpecDbController.OdlListAll(); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"OdlListAll | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato) - /// - /// Stato ODL: true=in corso/completato - /// Cod articolo - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Reparto selezionato - /// Macchina selezionata - /// Data inizio - /// Data fine - /// - public async Task> OdlListGetFilt(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisOdlList}:{inCorso}:{codArt}:{keyRichPart}:{Reparto}:{IdxMacchina}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.ListODLFilt(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"OdlListGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco di tutti i parametri filtrati x macchina - /// - /// * = tutte, altrimenti solo x una data macchina - /// - public async Task> ParametriGetFilt(string IdxMacchina) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisFluxByMac}:{IdxMacchina}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.ParametriGetFilt(IdxMacchina)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"ParametriGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Eliminazione record selezionato - /// - /// - /// - public async Task POdlDeleteRecord(PODLExpModel currRec) - { - var dbResult = await SpecDbController.PODLDeleteRecord(currRec); - // elimino cache redis... - await POdlFlushCache(); - await Task.Delay(1); - return dbResult; - } - - /// - /// Avvio fase setup per il record selezionato - /// - /// - /// - public async Task POdlDoSetup(PODLExpModel currRec) - { - var dbResult = await SpecDbController.PODL_startSetup(currRec, 0, 1, 1, "", DateTime.Now); - // elimino cache redis... - await POdlFlushCache(); - await Task.Delay(1); - return dbResult; - } - /// /// Recupero PODL da chiave /// @@ -2700,7 +1632,7 @@ namespace MP.IOC.Data } else { - result = await SpecDbController.PODL_getByKey(idxPODL); + result = await _productionRepository.PODL_getByKeyAsync(idxPODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); @@ -2753,107 +1685,6 @@ namespace MP.IOC.Data return result; } - /// - /// Recupero PODL da IdxODL - /// - /// - /// - public PODLModel POdlGetByOdl(int idxODL) - { - PODLModel result = new PODLModel(); - if (idxODL != 0) - { - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisPOdlByOdl}:{idxODL}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - var rawResult = JsonConvert.DeserializeObject($"{rawData}"); - if (rawResult != null) - { - result = rawResult; - } - readType = "REDIS"; - } - else - { - result = SpecDbController.PODL_getByOdl(idxODL); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new PODLModel(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Trace($"POdlGetByOdl | Read from {readType}: {ts.TotalMilliseconds}ms"); - } - else - { - Log.Debug("Errore IdxODL = 0"); - } - return result; - } - - /// - /// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato) - /// - /// Solo lanciati (1) o ancora disponibili (0) - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Macchina - /// Gruppo - /// Data inizio - /// Data fine - /// - public async Task> POdlListGetFilt(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) - { - List? result = new List(); - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - string readType = "DB"; - string currKey = $"{Utils.redisPOdlList}:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; - // cerco in redis dato valOut sel macchina... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - readType = "REDIS"; - } - else - { - result = await Task.FromResult(SpecDbController.ListPODLFilt(lanciato, keyRichPart, idxMacchina, codGruppo, startDate, endDate)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"POdlListGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); - return result; - } - - /// - /// Aggiornamento record selezionato - /// - /// - /// - public async Task POdlUpdateRecord(PODLModel currRec) - { - var dbResult = await SpecDbController.PODLUpdateRecord(currRec); - // elimino cache redis... - await POdlFlushCache(); - return dbResult; - } - /// /// Processa registrazione FL da IOB /// @@ -3194,22 +2025,6 @@ namespace MP.IOC.Data return result; } - /// - /// Salva ricetta su MongoDB - /// - /// - /// - public async Task RecipeSetByPODL(RecipeModel currRecord) - { - bool answ = false; - answ = await mongoController.RecipeSetByPODL(currRecord); - if (answ) - { - await POdlFlushCache(); - } - return answ; - } - /// /// Effettua conteggio chaivi REDIS dato pattern ricerca /// @@ -3272,31 +2087,6 @@ namespace MP.IOC.Data return await redisDb.KeyDeleteAsync(keyVal); } - /// - /// Esegue flush memoria redis dato keyVal - /// - /// - /// - public bool RedisFlushPattern(string pattern) - { - bool answ = false; - var listEndpoints = redisConnAdmin.GetEndPoints(); - foreach (var endPoint in listEndpoints) - { - var server = redisConnAdmin.GetServer(endPoint); - if (server != null) - { - var keyList = server.Keys(redisDb.Database, pattern); - foreach (var item in keyList) - { - redisDb.KeyDelete(item); - } - answ = true; - } - } - return answ; - } - /// /// Esegue flush memoria redis dato keyVal, async /// @@ -3488,77 +2278,6 @@ namespace MP.IOC.Data return fatto; } - /// - /// Recupera tutti i record di RemoteRebootLog - /// - /// - public async Task> RemRebootLogGetAllAsync() - { - // setup parametri costanti - string source = "DB"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - List result = new List(); - // cerco in _redisConn... - var currKey = $"{Utils.redisRemRebLog}:ALL"; - RedisValue rawData = await redisDb.StringGetAsync(currKey); - //if (!string.IsNullOrEmpty($"{rawData}")) - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}") ?? new(); - source = "REDIS"; - } - else - { - result = await IocDbController.RemRebootLogGetAllAsync(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromSeconds(30)); - } - if (result == null) - { - result = new List(); - } - sw.Stop(); - Log.Debug($"RemRebootLogGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; - } - - /// - /// Recupera ultimo record x ogni IdxMacchina x avere ultimo attivo - /// - /// - public async Task> RemRebootLogGetLast() - { - // setup parametri costanti - string source = "DB"; - Stopwatch sw = new Stopwatch(); - sw.Start(); - List result = new List(); - // cerco in _redisConn... - var currKey = $"{Utils.redisRemRebLog}:LAST"; - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}") ?? new(); - source = "REDIS"; - } - else - { - result = await IocDbController.RemRebootLogGetLastAsync(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromSeconds(30)); - } - if (result == null) - { - result = new List(); - } - sw.Stop(); - Log.Debug($"RemRebootLogGetLast | {source} | {sw.Elapsed.TotalMilliseconds}ms"); - return result; - } - /// /// Elimina da elenco KVP il TASK per l'impianto indicato /// @@ -3674,119 +2393,6 @@ namespace MP.IOC.Data return answ; } - /// - /// Processa registrazione EVENTO CONTEGGIO PEZZI x una data macchina IOB - /// - /// Macchina - /// Pezzi da registrare - /// DataOra evento - /// DataOra corrente - /// - public async Task SaveCaricoPezziAsync(string idxMacchina, string qty, string dtEve = "", string dtCurr = "") - { - // default: 0, non registrato x cautela... - string answ = "0"; - // Verifica se evento realtime oppure ho data specificata x processing @dtEve - DateTime adesso = DateTime.Now; - DateTime dtEvent = adesso; - bool rtimeProc = string.IsNullOrEmpty(dtEve); - if (!rtimeProc) - { - dtEvent = GetSrvDtEvent(dtEve, dtCurr); - } - // controllo per proseguire - if (!string.IsNullOrEmpty(idxMacchina) && !string.IsNullOrEmpty(qty)) - { - int numPzIncr = -1; - int.TryParse(qty, out numPzIncr); - // se il conteggio è >= 0 SALVO evento... - if (numPzIncr >= 0) - { - var listOdl = await IocDbController.OdlListByMaccPeriodoAsync(idxMacchina, dtEvent, dtEvent.AddSeconds(1)); - if (listOdl != null && listOdl.Count > 0) - { - string codArticolo = listOdl.FirstOrDefault()?.CodArticolo ?? "ND"; - // registro evento 120 --> contapezzi in blocco !!!HARD CODED!!! !!!FIXME!!! - int idxEvento = 120; - // creo evento - EventListModel newRecEv = new EventListModel() - { - CodArticolo = codArticolo, - IdxMacchina = idxMacchina, - IdxTipo = idxEvento, - InizioStato = dtEvent, - MatrOpr = 0, - pallet = "-", - Value = qty - }; - // salva e processa - var resp = await scriviRigaEventoAsync(newRecEv); - // registro in risposta che è andato tutto bene... ovvero la qty richiesta... - answ = qty; - } - } - } - else - { - string errore = $"Errore: mancano parametri macchina/incremento: idxMacchina {idxMacchina} | qty {qty}"; - Log.Error(errore); - answ = errore; - } - return answ; - } - - /// - /// Processa registrazione di un counter x una data macchina IOB - /// - /// - /// contapezzi - /// - public async Task SaveCounterAsync(string idxMacchina, string counter) - { - string answ = "0"; - // inizio processing vero e proprio INPUT... - if (string.IsNullOrEmpty(idxMacchina)) - { - string errore = "Errore: parametro macchina vuoto"; - Log.Info(errore); - answ = errore; - } - else - { - if (string.IsNullOrEmpty(counter)) - { - string errore = "Errore: parametro counter vuoto"; - Log.Error(errore); - answ = errore; - } - else - { - int newCounter = -1; - int.TryParse(counter, out newCounter); - // se il conteggio è >= 0 SALVO come nuovo conteggio... - if (newCounter >= 0) - { - var currKey = Utils.RedKeyPzCount(idxMacchina, MpIoNS); - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - // salvo per + tempo... - await redisDb.StringSetAsync(currKey, answ.ToString()); - answ = counter; - } - else - { - int currCount = await PzCounterTcAsync(idxMacchina); - answ = currCount.ToString(); - // salvo per meno tempo... - await redisDb.StringSetAsync(currKey, answ); - } - } - } - } - return answ; - } - public async Task SaveDataItemsAsync(string id, List dataList) { bool answ = false; @@ -3943,104 +2549,6 @@ namespace MP.IOC.Data return answ; } - /// - /// Statistiche ODL calcolate (da stored stp_STAT_ODL) - /// - /// - public Task> StatOdl(int IdxOdl) - { - return SpecDbController.OdlStart(IdxOdl); - } - - /// - /// restituisce il valOut da REDIS associato al tag richeisto - /// - /// Chiave in cui cercare il valOut - /// - public string TagConfGetKey(string redKey) - { - string outVal = ""; - // cerco in REDIS la conf x l'IOB - var rawData = redisDb.StringGet(redKey); - if (!string.IsNullOrEmpty(rawData)) - { - outVal = $"{rawData}"; - } - return outVal; - } - - /// - /// Elenco setup dei tag conf correnti - /// - /// - public Task>> TagsGetAll() - { - return Task.FromResult(currTagConf); - } - - /// - /// Esegue traduzione dato vocabolario da Lingua + Lemma - /// - /// - /// - /// - public string Traduci(string lemma, string lingua) - { - string answ = $"[{lemma}]"; - // verifico se ho qualcosa nell'obj vocabolario... - if (ObjVocabolario == null || ObjVocabolario.Count == 0) - { - // inizializzo il vocabolario... - ObjVocabolario = VocabolarioGetAll(); - } - var record = ObjVocabolario.Where(x => x.Lingua == lingua && x.Lemma == lemma).FirstOrDefault(); - if (record != null) - { - answ = record.Traduzione; - } - return answ; - } - - public async Task updateDossierValue(DossierModel currDoss, FluxLogDTO editFL) - { - bool answ = false; - // recupero intero set valori dossier deserializzando... - var fluxLogList = FluxLogDtoGetByFlux(currDoss.Valore); - await Task.Delay(1); - - // se tutto ok - if (fluxLogList != null) - { - // da provare...!!!! - - // elimino vecchio record - var currRec = fluxLogList.FirstOrDefault(x => x.CodFlux == editFL.CodFlux && x.dtEvento == editFL.dtEvento); - if (currRec != null) - { - fluxLogList.Remove(currRec); - // aggiungo nuovo - fluxLogList.Add(editFL); - } - - // serializzo nuovamente valOut - DossierFluxLogDTO? result = new DossierFluxLogDTO(); - var ODLflux = result.ODL.ToList(); - foreach (var item in fluxLogList) - { - ODLflux.Add(item); - } - - DossierFluxLogDTO updatedResult = new DossierFluxLogDTO() { ODL = ODLflux }; - - string rawVal = JsonConvert.SerializeObject(updatedResult); - currDoss.Valore = rawVal; - // aggiorno record sul DB - await SpecDbController.DossiersUpdateValore(currDoss); - } - - return answ; - } - /// /// Effettua UPSERT elenco parametri correnti x IOB (se c'è UPDATE, se manca ADD) /// @@ -4110,40 +2618,6 @@ namespace MP.IOC.Data return valOut; } - /// - /// Elenco completo tabella Vocabolario - /// - /// - public List VocabolarioGetAll() - { - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - List? result = new List(); - string source = "REDIS"; - // cerco in redis... - RedisValue rawData = redisDb.StringGet(Utils.redisVocabolario); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - } - else - { - result = SpecDbController.VocabolarioGetAll(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(Utils.redisVocabolario, rawData, getRandTOut(redisLongTimeCache / 5)); - source = "DB"; - } - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Debug($"VocabolarioGetAll Read from {source}: {ts.TotalMilliseconds}ms"); - if (result == null) - { - result = new List(); - } - return result; - } - #endregion Public Methods #region Internal Methods @@ -4261,11 +2735,6 @@ namespace MP.IOC.Data private string MpIoNS = ""; - /// - /// Oggetto vocabolario x uso continuo traduzione - /// - private List ObjVocabolario = new List(); - /// /// Oggetto per connessione a REDIS /// diff --git a/MP.IOC/MP.IOC.csproj b/MP.IOC/MP.IOC.csproj index ec21f95d..96e0e3b4 100644 --- a/MP.IOC/MP.IOC.csproj +++ b/MP.IOC/MP.IOC.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 8.16.2605.1119 + 8.16.2606.408 diff --git a/MP.IOC/Program.cs b/MP.IOC/Program.cs index 8a3df56f..8945acd4 100644 --- a/MP.IOC/Program.cs +++ b/MP.IOC/Program.cs @@ -42,18 +42,26 @@ logger.Info("RedisScript Provider configured"); // Metodi principali x accesso dati var connStr = builder.Configuration.GetConnectionString("MP.Data") ?? throw new InvalidOperationException("ConnString 'MP.Data' mancante."); - builder.Services.AddMemoryCache(); - builder.Services.AddDbContextFactory(options => options.UseSqlServer(connStr) .EnableSensitiveDataLogging(false) // true solo in Sviluppo .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); // MP.Data DbContext for Stats repositories -string utilsConnString = builder.Configuration.GetConnectionString("MP.Utils") ?? "Server=localhost;Database=MoonPro_Utils; integrated security=True; MultipleActiveResultSets=True; App=MP.IOC;"; +string connStrUtils = builder.Configuration.GetConnectionString("MP.Utils") + ?? throw new InvalidOperationException("ConnString 'MP.Utils' mancante."); +//?? "Server=localhost;Database=MoonPro_Utils; integrated security=True; MultipleActiveResultSets=True; App=MP.IOC;"; builder.Services.AddDbContextFactory(options => - options.UseSqlServer(utilsConnString)); + options.UseSqlServer(connStrUtils).EnableSensitiveDataLogging(false) + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + +var connStrFL = builder.Configuration.GetConnectionString("MP.Flux") + ?? throw new InvalidOperationException("ConnString 'MP.Flux' mancante."); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStrFL) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); // MP.Data Services Utils - Statistiche DB builder.Services.AddIocDataLayer(); diff --git a/MP.IOC/Resources/ChangeLog.html b/MP.IOC/Resources/ChangeLog.html index 480c59fb..421f226c 100644 --- a/MP.IOC/Resources/ChangeLog.html +++ b/MP.IOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-IOC -

    Versione: 8.16.2605.1119

    +

    Versione: 8.16.2606.408


    Note di rilascio:
    • diff --git a/MP.IOC/Resources/VersNum.txt b/MP.IOC/Resources/VersNum.txt index 282e9dc7..988a0006 100644 --- a/MP.IOC/Resources/VersNum.txt +++ b/MP.IOC/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.1119 +8.16.2606.408 diff --git a/MP.IOC/Resources/manifest.xml b/MP.IOC/Resources/manifest.xml index 0bbcd7eb..c0b40892 100644 --- a/MP.IOC/Resources/manifest.xml +++ b/MP.IOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.1119 + 8.16.2606.408 https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html false diff --git a/MP.Land/Components/DbInfoMan.razor.cs b/MP.Land/Components/DbInfoMan.razor.cs index aae03d69..6b434c3a 100644 --- a/MP.Land/Components/DbInfoMan.razor.cs +++ b/MP.Land/Components/DbInfoMan.razor.cs @@ -5,6 +5,7 @@ using MP.Data.Services; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace MP.Land.Components { @@ -21,9 +22,10 @@ namespace MP.Land.Components #region Protected Methods - protected override void OnParametersSet() + + protected override async Task OnParametersSetAsync() { - ReloadData(); + await ReloadDataAsync(); } protected void SortRequested(Sorter.SortCallBack e) @@ -117,9 +119,9 @@ namespace MP.Land.Components } } - private void ReloadData() + private async Task ReloadDataAsync() { - ListRecord = LDService.AllDbInfo(); + ListRecord = await LDService.AllDbInfoAsync(); } #endregion Private Methods diff --git a/MP.Land/MP.Land.csproj b/MP.Land/MP.Land.csproj index 4f1a232f..0bbf51c6 100644 --- a/MP.Land/MP.Land.csproj +++ b/MP.Land/MP.Land.csproj @@ -3,7 +3,7 @@ net8.0 MP.Land - 8.16.2605.0811 + 8.16.2606.0408 Debug;Release;Debug_LiManDebug en True diff --git a/MP.Land/Pages/IobList.razor.cs b/MP.Land/Pages/IobList.razor.cs index 90157bb1..8984045a 100644 --- a/MP.Land/Pages/IobList.razor.cs +++ b/MP.Land/Pages/IobList.razor.cs @@ -173,11 +173,11 @@ namespace MP.Land.Pages return answ; } - protected void DataInit() + protected async Task DataInitAsync() { isLoading = true; // recupero TUTTI i dati IobList gi completi anche on i RemoteRebootLog - AllRecords = LDService.IobListAll(); + AllRecords = await LDService.IobListAllAsync(); #if false @@ -216,7 +216,7 @@ namespace MP.Land.Pages AppMService.PageName = "IobList"; AppMService.PageIcon = "fas fa-computer pe-2"; await SetupRight(); - DataInit(); + await DataInitAsync(); } protected void ResetSearch() diff --git a/MP.Land/Resources/ChangeLog.html b/MP.Land/Resources/ChangeLog.html index 65e63b56..72c86f08 100644 --- a/MP.Land/Resources/ChangeLog.html +++ b/MP.Land/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo Tablet MAPO - DotNet6 -

      Versione: 8.16.2605.0811

      +

      Versione: 8.16.2606.0408


      Note di rilascio:
        diff --git a/MP.Land/Resources/VersNum.txt b/MP.Land/Resources/VersNum.txt index 3249ffa8..47fe7fc3 100644 --- a/MP.Land/Resources/VersNum.txt +++ b/MP.Land/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.0811 +8.16.2606.0408 diff --git a/MP.Land/Resources/manifest.xml b/MP.Land/Resources/manifest.xml index e201bc34..1b36f10a 100644 --- a/MP.Land/Resources/manifest.xml +++ b/MP.Land/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.0811 + 8.16.2606.0408 https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html false diff --git a/MP.Land/Startup.cs b/MP.Land/Startup.cs index 77b74a07..d318e61b 100644 --- a/MP.Land/Startup.cs +++ b/MP.Land/Startup.cs @@ -1,26 +1,27 @@ -using Blazored.LocalStorage; +using Blazored.LocalStorage; using Blazored.SessionStorage; using Microsoft.AspNetCore.Authentication.Negotiate; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Localization; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using MP.AppAuth.Services; -using MP.Data.Services; +using MP.Data; using MP.Land.Data; using MP.TaskMan.Services; using StackExchange.Redis; using System; -using System.Collections.Generic; -using System.Configuration; using System.Globalization; -using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; +using ZiggyCreatures.Caching.Fusion.Backplane.StackExchangeRedis; +using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson; namespace MP.Land { @@ -125,12 +126,22 @@ namespace MP.Land options.FallbackPolicy = options.DefaultPolicy; }); + + // REDIS setup string connStringRedis = Configuration.GetConnectionString("Redis"); string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":")); // avvio oggetto shared x redis... - var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); + IConnectionMultiplexer redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); + // ✅ FusionCache + services.AddFusionCache() + .WithDistributedCache(sp => sp.GetRequiredService()) + .WithSerializer(new FusionCacheNewtonsoftJsonSerializer()) + .WithBackplane(new RedisBackplane(new RedisBackplaneOptions + { + ConnectionMultiplexerFactory = () => Task.FromResult(redisMultiplexer) + })); services.AddLocalization(); @@ -138,12 +149,38 @@ namespace MP.Land services.AddServerSideBlazor(); services.AddSingleton(Configuration); + + // aggiungo il costruttore x i vari DbContextFactory + var connStr = Configuration.GetConnectionString("MP.Land") + ?? throw new InvalidOperationException("ConnString 'MP.Land' mancante."); + services.AddDbContextFactory(options => + options.UseSqlServer(connStr) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + + var connStrFlux = Configuration.GetConnectionString("MP.Flux") + ?? throw new InvalidOperationException("ConnString 'MP.Flux' mancante."); + services.AddDbContextFactory(options => + options.UseSqlServer(connStrFlux) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + + var connStrStats = Configuration.GetConnectionString("MP.Stats") + ?? throw new InvalidOperationException("ConnString 'MP.Stats' mancante."); + services.AddDbContextFactory(options => + options.UseSqlServer(connStrStats) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + + //init servizi specifici LAND + //services.AddAuthLandDataLayer(); + services.AddLandDataLayer(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + //services.AddSingleton(); + //services.AddSingleton(); + //services.AddSingleton(); services.AddScoped(); services.AddScoped(); diff --git a/MP.MON/MP.MON.csproj b/MP.MON/MP.MON.csproj index 83044cfe..1af13f40 100644 --- a/MP.MON/MP.MON.csproj +++ b/MP.MON/MP.MON.csproj @@ -6,7 +6,7 @@ enable MP.MON $(AssemblyName.Replace(' ', '_')) - 8.16.2604.2718 + 8.16.2606.408 diff --git a/MP.MON/Program.cs b/MP.MON/Program.cs index ad200407..20e4cd80 100644 --- a/MP.MON/Program.cs +++ b/MP.MON/Program.cs @@ -1,3 +1,6 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using MP.Data; using MP.Data.Services; using MP.MON.Components; using NLog; @@ -26,10 +29,21 @@ string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":")) // avvio oggetto shared x redis... var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); +// aggiungo il costruttore x i vari DbContextFactory +var connStr = builder.Configuration.GetConnectionString("MP.Mon") + ?? throw new InvalidOperationException("ConnString 'MP.Mon' mancante."); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStr) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + // Add services to the container. logger.Info("Setup Services"); + builder.Services.AddSingleton(redisMultiplexer); -builder.Services.AddSingleton(); +// Init centralizzato Repository/Servizi da MP.Data Services +builder.Services.AddMonDataLayer(); + var app = builder.Build(); diff --git a/MP.MON/Resources/ChangeLog.html b/MP.MON/Resources/ChangeLog.html index 133a7fea..6e774415 100644 --- a/MP.MON/Resources/ChangeLog.html +++ b/MP.MON/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOSPEC -

        Versione: 8.16.2604.2718

        +

        Versione: 8.16.2606.408


        Note di rilascio:
        • diff --git a/MP.MON/Resources/VersNum.txt b/MP.MON/Resources/VersNum.txt index 87ec763e..988a0006 100644 --- a/MP.MON/Resources/VersNum.txt +++ b/MP.MON/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2604.2718 +8.16.2606.408 diff --git a/MP.MON/Resources/manifest.xml b/MP.MON/Resources/manifest.xml index 6546b902..39fe57dc 100644 --- a/MP.MON/Resources/manifest.xml +++ b/MP.MON/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2604.2718 + 8.16.2606.408 https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/MP.MON.zip https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/ChangeLog.html false diff --git a/MP.MON/appsettings.json b/MP.MON/appsettings.json index c9f20d06..5b692c2d 100644 --- a/MP.MON/appsettings.json +++ b/MP.MON/appsettings.json @@ -2,7 +2,9 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Warning", + "Microsoft.EntityFrameworkCore.Database.Command": "Warning" } }, "NLog": { diff --git a/MP.Prog/MP.Prog.csproj b/MP.Prog/MP.Prog.csproj index 7fe982a9..add2792d 100644 --- a/MP.Prog/MP.Prog.csproj +++ b/MP.Prog/MP.Prog.csproj @@ -3,7 +3,7 @@ net8.0 MP.Prog - 6.16.2604.2715 + 8.16.2606.0408 True diff --git a/MP.Prog/Resources/ChangeLog.html b/MP.Prog/Resources/ChangeLog.html index abc709a8..ad30d9e0 100644 --- a/MP.Prog/Resources/ChangeLog.html +++ b/MP.Prog/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo gestione Programmi MAPO -

          Versione: 6.16.2604.2715

          +

          Versione: 8.16.2606.0408


          Note di rilascio:
            diff --git a/MP.Prog/Resources/VersNum.txt b/MP.Prog/Resources/VersNum.txt index b53e4a5d..47fe7fc3 100644 --- a/MP.Prog/Resources/VersNum.txt +++ b/MP.Prog/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2604.2715 +8.16.2606.0408 diff --git a/MP.Prog/Resources/manifest.xml b/MP.Prog/Resources/manifest.xml index 9906d5bb..93ee4351 100644 --- a/MP.Prog/Resources/manifest.xml +++ b/MP.Prog/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2604.2715 + 8.16.2606.0408 https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/MP.Prog.zip https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/ChangeLog.html false diff --git a/MP.Prog/Startup.cs b/MP.Prog/Startup.cs index 8f941fab..0e2707af 100644 --- a/MP.Prog/Startup.cs +++ b/MP.Prog/Startup.cs @@ -88,9 +88,6 @@ namespace MP.Prog }); CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("it-IT"); - //// Registrazione Elmah: - //// https://github.com/ElmahCore/ElmahCore - //app.UseElmah(); // fix forwarders app.UseForwardedHeaders(new ForwardedHeadersOptions @@ -152,14 +149,6 @@ namespace MP.Prog o.SlidingExpiration = true; }); - //// Elmah - //services.AddElmah(); - //string elmaConn = "Data Source=SQL2016DEV;Initial Catalog=Elmah;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=SHERPA.BBM;"; - //services.AddElmah(options => - //{ - // options.ConnectionString = elmaConn; - //}); - #if false services.AddStackExchangeRedisCache(options => { diff --git a/MP.RIOC/MP.RIOC.csproj b/MP.RIOC/MP.RIOC.csproj index 4b9d8648..a506ab6c 100644 --- a/MP.RIOC/MP.RIOC.csproj +++ b/MP.RIOC/MP.RIOC.csproj @@ -5,7 +5,7 @@ enable enable MP.RIOC - 8.16.2605.1207 + 8.16.2606.408 @@ -17,6 +17,7 @@ + diff --git a/MP.RIOC/Program.cs b/MP.RIOC/Program.cs index a507237f..489b29dd 100644 --- a/MP.RIOC/Program.cs +++ b/MP.RIOC/Program.cs @@ -37,13 +37,16 @@ logger.Info("RedisScript Provider configured"); // Metodi principali x accesso dati var connStr = builder.Configuration.GetConnectionString("MP.Data") ?? throw new InvalidOperationException("ConnString 'MP.Data' mancante."); - -//builder.Services.AddMemoryCache(); - builder.Services.AddDbContextFactory(options => options.UseSqlServer(connStr) .EnableSensitiveDataLogging(false) // true solo in Sviluppo .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); +var connStrFL = builder.Configuration.GetConnectionString("MP.Flux") + ?? throw new InvalidOperationException("ConnString 'MP.Flux' mancante."); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStrFL) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); // MP.Data DbContext for Stats repositories string utilsConnString = builder.Configuration.GetConnectionString("MP.Utils") ?? "Server=localhost;Database=MoonPro_Utils; integrated security=True; MultipleActiveResultSets=True; App=MP.IOC;"; @@ -78,6 +81,9 @@ builder.Services.AddHttpForwarder(); var redisMux = ConnectionMultiplexer.Connect(confRedis); builder.Services.AddSingleton(redisMux); +// registrazione FusionCache +builder.Services.AddFusionCache(); + // Registrazione dei servizi custom builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/MP.RIOC/Properties/PublishProfiles/IIS01.pubxml b/MP.RIOC/Properties/PublishProfiles/IIS01.pubxml index 9278d2ad..6c359c50 100644 --- a/MP.RIOC/Properties/PublishProfiles/IIS01.pubxml +++ b/MP.RIOC/Properties/PublishProfiles/IIS01.pubxml @@ -1,32 +1,33 @@  - - MSDeploy - true - Release - Any CPU - https://iis01.egalware.com/MP/RIOC/ - false - b9188473-f4ae-4f9f-be2d-70edaace0db9 - false - https://iis01.egalware.com:8172/MsDeploy.axd - Default Web Site/MP/RIOC - - false - WMSVC - true - true - jenkins - <_SavePWD>true - <_TargetId>IISWebDeploy - net8.0 - win-x64 - - - - filePath - logs\\.*\.log$ - - + + MSDeploy + true + Release + Any CPU + https://iis01.egalware.com/MP/RIOC/ + false + b9188473-f4ae-4f9f-be2d-70edaace0db9 + false + https://iis01.egalware.com:8172/MsDeploy.axd + Default Web Site/MP/RIOC + + true + WMSVC + true + true + jenkins + <_SavePWD>true + <_TargetId>IISWebDeploy + net8.0 + win-x64 + true + + + + filePath + logs\\.*\.log$ + + \ No newline at end of file diff --git a/MP.RIOC/Resources/ChangeLog.html b/MP.RIOC/Resources/ChangeLog.html index ce196314..e25fa8ef 100644 --- a/MP.RIOC/Resources/ChangeLog.html +++ b/MP.RIOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-RIOC -

            Versione: 8.16.2605.1207

            +

            Versione: 8.16.2606.408


            Note di rilascio:
            • diff --git a/MP.RIOC/Resources/VersNum.txt b/MP.RIOC/Resources/VersNum.txt index 57e5daf4..988a0006 100644 --- a/MP.RIOC/Resources/VersNum.txt +++ b/MP.RIOC/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.1207 +8.16.2606.408 diff --git a/MP.RIOC/Resources/manifest.xml b/MP.RIOC/Resources/manifest.xml index a43e833c..ceddb51b 100644 --- a/MP.RIOC/Resources/manifest.xml +++ b/MP.RIOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.1207 + 8.16.2606.408 https://nexus.steamware.net/repository/SWS/MP-RIOC/stable/LAST/MP.RIOC.zip https://nexus.steamware.net/repository/SWS/MP-RIOC/stable/LAST/ChangeLog.html false diff --git a/MP.RIOC/appsettings.json b/MP.RIOC/appsettings.json index 590b8fb4..958cb8ba 100644 --- a/MP.RIOC/appsettings.json +++ b/MP.RIOC/appsettings.json @@ -3,7 +3,9 @@ "LogLevel": { "Default": "Information", "Yarp": "Debug", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Warning", + "Microsoft.EntityFrameworkCore.Database.Command": "Warning" } }, "AllowedHosts": "*", @@ -80,6 +82,7 @@ "ConnectionStrings": { "MP.Data": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; App=MP.IOC;", "MP.Utils": "Server=SQL2016DEV;Database=MoonPro_Utils; User ID=sa;Password=keyhammer16; integrated security=False; App=MP.RIOC;", + "MP.Flux": "Server=SQL2016DEV;Database=MoonPro_FluxData; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.RIOC;", "Redis": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=5,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false", "RedisAdmin": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=5,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true" } diff --git a/MP.SPEC/App.razor b/MP.SPEC/App.razor deleted file mode 100644 index 7431d6a1..00000000 --- a/MP.SPEC/App.razor +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Not found - -

              Sorry, there's nothing at this address.

              -
              -
              -
              -
              diff --git a/MP.SPEC/Components/App.razor b/MP.SPEC/Components/App.razor new file mode 100644 index 00000000..7c2bdacb --- /dev/null +++ b/MP.SPEC/Components/App.razor @@ -0,0 +1,43 @@ + + + + + + + @* *@ + @* *@ + + + + + + MP-SPEC + + + + + + + + @* *@ + + + + + + + + +
              + An error has occurred. + Reload + 🗙 +
              + + + + + + + + diff --git a/MP.SPEC/Components/AskCloseOdl.razor.cs b/MP.SPEC/Components/AskCloseOdl.razor.cs index 98fe22f4..62a98b32 100644 --- a/MP.SPEC/Components/AskCloseOdl.razor.cs +++ b/MP.SPEC/Components/AskCloseOdl.razor.cs @@ -55,8 +55,7 @@ namespace MP.SPEC.Components } // eseguo chiusura finale CurrAction.IsActive = false; - MDService.ActionSetReq(CurrAction); - await Task.Delay(1); + await MDService.ActionSetReqAsync(CurrAction); } protected async Task doConfirm() @@ -76,12 +75,12 @@ namespace MP.SPEC.Components { DateTime oggi = DateTime.Today; // recupero idxMaccSel x ODL... - var elencoOdl = await MDService.OdlListGetFilt(true, "*", "*", "*", "*", DateTime.Today.AddMonths(-1), DateTime.Today.AddDays(1)); + var elencoOdl = await MDService.OdlListGetFiltAsync(true, "*", "*", "*", "*", DateTime.Today.AddMonths(-1), DateTime.Today.AddDays(1)); var currOdl = elencoOdl.FirstOrDefault(x => x.IdxOdl == idxOdl); if (currOdl != null && currOdl.IdxOdl == idxOdl) { // effettua chiusura sul DB - fatto = await MDService.ODLClose(idxOdl, currOdl.IdxMacchina, 0, true); + fatto = await MDService.ODLCloseAsync(idxOdl, currOdl.IdxMacchina, 0, true); if (fatto) { Log.Info($"Effettuata chiusura ODL {idxOdl}"); @@ -103,8 +102,7 @@ namespace MP.SPEC.Components } } - MDService.ActionSetReq(CurrAction); - await Task.Delay(1); + await MDService.ActionSetReqAsync(CurrAction); // se fatto --> ricarico! if (fatto) { diff --git a/MP.SPEC/Components/CmpTop.razor.cs b/MP.SPEC/Components/CmpTop.razor.cs index c7d26602..8b2ee9b2 100644 --- a/MP.SPEC/Components/CmpTop.razor.cs +++ b/MP.SPEC/Components/CmpTop.razor.cs @@ -1,12 +1,9 @@ -using Amazon.Runtime.Internal.Endpoints.StandardLibrary; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.JSInterop; using MP.AppAuth.Services; using MP.SPEC.Data; using MP.SPEC.Extensions; -using System; namespace MP.SPEC.Components { @@ -55,7 +52,8 @@ namespace MP.SPEC.Components protected async Task FlushCache() { - await MDService.FlushRedisCache(); + await MDService.ForceFlushRedisCache(); + await MDService.ForceFlushFusionCacheAsync(); await ForceReload(); // rimando a pagina corrente NavManager.NavigateTo(NavManager.Uri, true); diff --git a/MP.SPEC/Components/DossiersFilter.razor b/MP.SPEC/Components/DossiersFilter.razor index 4c5528a4..93ef3275 100644 --- a/MP.SPEC/Components/DossiersFilter.razor +++ b/MP.SPEC/Components/DossiersFilter.razor @@ -5,13 +5,13 @@
              @**@ @if (selMacchina != "*") - { - - } - @if (selArticolo != "*") - { - - } + { + + } + @if (selArticolo != "*") + { + + }
              }
              @@ -34,7 +34,7 @@
              - @if (ListArticoli != null) { @@ -50,7 +50,7 @@
              - @if (ListMacchine != null) { @@ -67,14 +67,14 @@
              - +
              - +
              @@ -82,7 +82,7 @@
              - +
              diff --git a/MP.SPEC/Components/DossiersFilter.razor.cs b/MP.SPEC/Components/DossiersFilter.razor.cs index 32b021dc..a061c8c7 100644 --- a/MP.SPEC/Components/DossiersFilter.razor.cs +++ b/MP.SPEC/Components/DossiersFilter.razor.cs @@ -30,26 +30,11 @@ namespace MP.SPEC.Components { if (!SelFilterDossier.CodArticolo.Equals(value)) { - SelFilterDossier.CurrPage = 1; SelFilterDossier.CodArticolo = value; - StateHasChanged(); - Task.Delay(1); - reportChange(); } } } - private bool filtActive - { - get => selMacchina != "*" || selArticolo != "*"; - } - protected void resetMacchina() - { - selMacchina = "*"; - } - protected void resetArticolo() - { - selArticolo = "*"; - } + protected DateTime selDtMax { get @@ -62,7 +47,6 @@ namespace MP.SPEC.Components if (!SelFilterDossier.DtEnd.Equals(value)) { SelFilterDossier.DtEnd = value; - reportChange(); } } } @@ -79,7 +63,6 @@ namespace MP.SPEC.Components if (!SelFilterDossier.DtStart.Equals(value)) { SelFilterDossier.DtStart = value; - reportChange(); } } } @@ -94,11 +77,7 @@ namespace MP.SPEC.Components { if (!SelFilterDossier.IdxMacchina.Equals(value)) { - SelFilterDossier.CurrPage = 1; SelFilterDossier.IdxMacchina = value; - StateHasChanged(); - Task.Delay(1); - reportChange(); } } } @@ -115,7 +94,6 @@ namespace MP.SPEC.Components if (!SelFilterDossier.MaxRecord.Equals(value)) { SelFilterDossier.MaxRecord = value; - reportChange(); } } } @@ -128,15 +106,23 @@ namespace MP.SPEC.Components protected override async Task OnInitializedAsync() { - SelFilterDossier = new SelectDossierParams(); - SelFilterDossier.MaxRecord = 1000; DateTime dtEnd = SelFilterDossier.DtEnd; DateTime dtStart = dtEnd.Subtract(SelFilterDossier.DtStart).TotalDays < 15 ? SelFilterDossier.DtStart : dtEnd.AddDays(-14); - ListMacchine = await MDService.MacchineWithFlux(dtStart, dtEnd); - ListArticoli = await MDService.ArticleWithDossier(); + ListMacchine = await MDService.MacchineWithFluxAsync(dtStart, dtEnd); + ListArticoli = await MDService.ArticleWithDossierAsync(); await FilterChanged.InvokeAsync(SelFilterDossier); } + protected void resetArticolo() + { + selArticolo = "*"; + } + + protected void resetMacchina() + { + selMacchina = "*"; + } + protected void toggleParams() { showEditPar = !showEditPar; @@ -147,21 +133,28 @@ namespace MP.SPEC.Components #region Private Fields private List? ListArticoli = null; + private List? ListMacchine = null; #endregion Private Fields #region Private Properties + private bool filtActive + { + get => selMacchina != "*" || selArticolo != "*"; + } + private bool showEditPar { get; set; } = false; #endregion Private Properties #region Private Methods - private void reportChange() + private Task ReportChangeAsync() { - FilterChanged.InvokeAsync(SelFilterDossier); + SelFilterDossier.CurrPage = 1; + return FilterChanged.InvokeAsync(SelFilterDossier); } private void toggleShowParams() diff --git a/MP.SPEC/Components/FLStatusList.razor.cs b/MP.SPEC/Components/FLStatusList.razor.cs index c1493d3e..7f453aef 100644 --- a/MP.SPEC/Components/FLStatusList.razor.cs +++ b/MP.SPEC/Components/FLStatusList.razor.cs @@ -116,7 +116,7 @@ namespace MP.SPEC.Components { idxMaccLast = IdxMaccSel; lastPeriodo = CurrPeriodo; - ListComplete = await MDataServ.FluxLogPareto(IdxMaccSel, CurrPeriodo.Inizio, CurrPeriodo.Fine); + ListComplete = await MDataServ.FluxLogParetoAsync(IdxMaccSel, CurrPeriodo.Inizio, CurrPeriodo.Fine); TotalCount = ListComplete.Count; TotalRecords = ListComplete.Sum(x => x.Qty); FluxList = ListComplete.Select(x => x.CodFlux).ToList(); diff --git a/MP.SPEC/Shared/MainLayout.razor b/MP.SPEC/Components/Layout/MainLayout.razor similarity index 100% rename from MP.SPEC/Shared/MainLayout.razor rename to MP.SPEC/Components/Layout/MainLayout.razor diff --git a/MP.SPEC/Shared/MainLayout.razor.cs b/MP.SPEC/Components/Layout/MainLayout.razor.cs similarity index 90% rename from MP.SPEC/Shared/MainLayout.razor.cs rename to MP.SPEC/Components/Layout/MainLayout.razor.cs index dffbf458..725d3227 100644 --- a/MP.SPEC/Shared/MainLayout.razor.cs +++ b/MP.SPEC/Components/Layout/MainLayout.razor.cs @@ -1,4 +1,4 @@ -namespace MP.SPEC.Shared +namespace MP.SPEC.Components.Layout { public partial class MainLayout { diff --git a/MP.SPEC/Shared/MainLayout.razor.css b/MP.SPEC/Components/Layout/MainLayout.razor.css similarity index 100% rename from MP.SPEC/Shared/MainLayout.razor.css rename to MP.SPEC/Components/Layout/MainLayout.razor.css diff --git a/MP.SPEC/Shared/MainLayout.razor.less b/MP.SPEC/Components/Layout/MainLayout.razor.less similarity index 100% rename from MP.SPEC/Shared/MainLayout.razor.less rename to MP.SPEC/Components/Layout/MainLayout.razor.less diff --git a/MP.SPEC/Shared/MainLayout.razor.min.css b/MP.SPEC/Components/Layout/MainLayout.razor.min.css similarity index 100% rename from MP.SPEC/Shared/MainLayout.razor.min.css rename to MP.SPEC/Components/Layout/MainLayout.razor.min.css diff --git a/MP.SPEC/Shared/NavMenu.razor b/MP.SPEC/Components/Layout/NavMenu.razor similarity index 100% rename from MP.SPEC/Shared/NavMenu.razor rename to MP.SPEC/Components/Layout/NavMenu.razor diff --git a/MP.SPEC/Shared/NavMenu.razor.cs b/MP.SPEC/Components/Layout/NavMenu.razor.cs similarity index 93% rename from MP.SPEC/Shared/NavMenu.razor.cs rename to MP.SPEC/Components/Layout/NavMenu.razor.cs index 0d2208e9..1bc7153e 100644 --- a/MP.SPEC/Shared/NavMenu.razor.cs +++ b/MP.SPEC/Components/Layout/NavMenu.razor.cs @@ -1,8 +1,7 @@ using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc.RazorPages; using MP.SPEC.Data; -namespace MP.SPEC.Shared +namespace MP.SPEC.Components.Layout { public partial class NavMenu : IDisposable { @@ -62,9 +61,9 @@ namespace MP.SPEC.Shared return MsgService.HasRole(Ruolo); } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { - ElencoLink = MDService.ElencoLink(); + ElencoLink = await MDService.ElencoLinkAsync(); MService.EA_PageUpdated += OnPageUpdate; } diff --git a/MP.SPEC/Shared/NavMenu.razor.css b/MP.SPEC/Components/Layout/NavMenu.razor.css similarity index 100% rename from MP.SPEC/Shared/NavMenu.razor.css rename to MP.SPEC/Components/Layout/NavMenu.razor.css diff --git a/MP.SPEC/Components/ListDossiers.razor b/MP.SPEC/Components/ListDossiers.razor index 8b233bdc..ee07e0f6 100644 --- a/MP.SPEC/Components/ListDossiers.razor +++ b/MP.SPEC/Components/ListDossiers.razor @@ -79,8 +79,8 @@ else } - + @if (currRecordClone != null) { @@ -141,9 +141,10 @@ else
              - ARTICOLI - - + + @* + *@
              - -
              @@ -186,16 +185,9 @@ else
              } - - - - - - -
              @@ -269,7 +261,7 @@ else @if (isEditing == false) { - + } else { @@ -344,8 +336,3 @@ else } - - - - - diff --git a/MP.SPEC/Components/ListDossiers.razor.cs b/MP.SPEC/Components/ListDossiers.razor.cs index 1da69a82..63514f91 100644 --- a/MP.SPEC/Components/ListDossiers.razor.cs +++ b/MP.SPEC/Components/ListDossiers.razor.cs @@ -67,9 +67,8 @@ namespace MP.SPEC.Components public async Task flushCache() { - await Task.Delay(1); - await MDService.FlushRedisCache(); - await Task.Delay(1); + await MDService.ForceFlushRedisCache(); + await MDService.ForceFlushFusionCacheAsync(); // rimando a pagina corrente NavManager.NavigateTo(NavManager.Uri, true); } @@ -78,8 +77,8 @@ namespace MP.SPEC.Components #region Protected Fields - protected string selAzienda = "*"; protected string giacenzeConf = "false"; + protected string selAzienda = "*"; #endregion Protected Fields @@ -105,7 +104,7 @@ namespace MP.SPEC.Components await Task.Delay(1); if (currRecord != null) { - listaFlux = MDService.FluxLogDtoGetByFlux(currRecord.Valore); + listaFlux = MDService.FluxLogDtoConvert(currRecord.Valore); } StateHasChanged(); } @@ -146,16 +145,15 @@ namespace MP.SPEC.Components /// /// /// - protected async Task deleteRecord(DossierModel selRec) + protected async Task DoDelete(DossierModel selRec) { if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione Dossier: sei sicuro di voler procedere?")) return; - await Task.Delay(1); - var done = await MDService.DossiersDeleteRecord(selRec); + + var done = await MDService.DossiersDeleteRecordAsync(selRec); currRecord = null; await ReloadData(true); visualizzaFlux = true; - await Task.Delay(1); } protected async Task editRecord(FluxLogDTO selRec) @@ -222,20 +220,14 @@ namespace MP.SPEC.Components } } - //prtected bool hasLic - //{ - // get => selAzienda == "GIACOVELLI"; - //} - protected override async Task OnInitializedAsync() { - await MDService.ConfigResetCache(); - ListGruppiFase = MDService.ElencoGruppiFase(); - ListStati = await MDService.AnagStatiComm(); + await MDService.ConfigResetCacheAsync(); + ListGruppiFase = await MDService.ElencoGruppiFaseAsync(); + ListStati = await MDService.AnagStatiCommAsync(); selAzienda = await MDService.ConfigTryGetAsync("AZIENDA"); giacenzeConf = await MDService.ConfigTryGetAsync("SPEC_ShowGiacenze"); - ListArticoli = await MDService.ArticoliGetSearch(100000, selAzienda, ""); - ListMacchine = MDService.MacchineGetFilt("*"); + ListMacchine = await MDService.MacchineGetFiltAsync("*"); await ReloadData(true); } @@ -261,7 +253,7 @@ namespace MP.SPEC.Components { currRecord = selRec; await RecordSel.InvokeAsync(selRec); - listaFlux = MDService.FluxLogDtoGetByFlux(selRec.Valore); + listaFlux = MDService.FluxLogDtoConvert(selRec.Valore); await toggleTableFlux(); } @@ -271,7 +263,6 @@ namespace MP.SPEC.Components if (alert) { - await Task.Delay(1); if (currRecord != null) { // serializzo valore x flux log... @@ -279,11 +270,10 @@ namespace MP.SPEC.Components string newVal = JsonConvert.SerializeObject(updatedResult); currRecord.Valore = newVal; // METODO PER UPDATE FLUX - await MDService.DossiersUpdateValore(currRecord); + await MDService.DossiersUpdateValoreAsync(currRecord); currFluxLogDto = null; isEditing = false; - await Task.Delay(1); - StateHasChanged(); + await InvokeAsync(StateHasChanged); } return; } @@ -314,14 +304,19 @@ namespace MP.SPEC.Components private DossierModel? currRecordClone = null; - private List? ListArticoli; private List? ListGruppiFase; private List? ListMacchine; + private List? ListRecords; private List? ListStati; + /// + /// Ricerca articoli + /// + private string SearchArt = ""; + private List? SearchRecords; #endregion Private Fields @@ -346,6 +341,11 @@ namespace MP.SPEC.Components private List? listaFlux { get; set; } = null; + private int MaxRec + { + get => SelFilter.MaxRecord; + } + private int MaxRecord { get => SelFilter.MaxRecord; @@ -379,10 +379,6 @@ namespace MP.SPEC.Components { get => SelFilter.IdxMacchina; } - private int MaxRec - { - get => SelFilter.MaxRecord; - } private int totalCount { @@ -436,7 +432,7 @@ namespace MP.SPEC.Components private async Task ReloadData(bool setChanged) { isLoading = true; - SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelArticolo, SelDtStart, SelDtEnd, MaxRec); + SearchRecords = await MDService.DossiersGetLastFiltAsync(SelMacchina, SelArticolo, SelDtStart, SelDtEnd, MaxRec); totalCount = SearchRecords.Count; ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList(); await Task.Delay(1); diff --git a/MP.SPEC/Components/ListGiacenze.razor.cs b/MP.SPEC/Components/ListGiacenze.razor.cs index 24f37bbe..542e02c7 100644 --- a/MP.SPEC/Components/ListGiacenze.razor.cs +++ b/MP.SPEC/Components/ListGiacenze.razor.cs @@ -42,7 +42,7 @@ namespace MP.SPEC.Components protected override async Task OnParametersSetAsync() { - elencoGiacenze = await MDService.ListGiacenze(IdxOdl); + elencoGiacenze = await MDService.ListGiacenzeAsync(IdxOdl); } #endregion Protected Methods diff --git a/MP.SPEC/Components/ListODL.razor b/MP.SPEC/Components/ListODL.razor index 0922b913..c7f09dfa 100644 --- a/MP.SPEC/Components/ListODL.razor +++ b/MP.SPEC/Components/ListODL.razor @@ -11,7 +11,7 @@ else
              @if (showKitDetail) { - + } @if (currRecord != null && !showStats && isCurrOdl) { @@ -109,7 +109,7 @@ else @record.CodArticolo @if (CheckIsKit(record.CodArticolo)) { - + }
              @record.DescArticolo
              diff --git a/MP.SPEC/Components/ListODL.razor.cs b/MP.SPEC/Components/ListODL.razor.cs index f0cf41b7..42f4107d 100644 --- a/MP.SPEC/Components/ListODL.razor.cs +++ b/MP.SPEC/Components/ListODL.razor.cs @@ -1,8 +1,6 @@ using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.DataProtection; using Microsoft.JSInterop; using MP.Data.DbModels; -using MP.SPEC.Components; using MP.SPEC.Data; using MP.SPEC.Services; using NLog; @@ -111,7 +109,7 @@ namespace MP.SPEC.Components if (currRecord != null) { // effettua chiusura sul DB - await MDService.ODLClose(currRecord.IdxOdl, currRecord.IdxMacchina, 0, true); + await MDService.ODLCloseAsync(currRecord.IdxOdl, currRecord.IdxMacchina, 0, true); Log.Info($"Effettuata chiusura ODL {currRecord.IdxOdl}"); // RESETTO task x setComm, setArt, SetPzComm @@ -125,7 +123,7 @@ namespace MP.SPEC.Components // ricarica... await selRecord(null); } - await ReloadData(); + await ReloadDataAsync(); } /// @@ -153,18 +151,12 @@ namespace MP.SPEC.Components // ricarica... await selRecord(null); } - await ReloadData(); + await ReloadDataAsync(); } protected int getPodl(int idxOdl) { - int answ = 0; - var pOdlData = MDService.POdlGetByOdl(idxOdl); - if (pOdlData != null) - { - answ = pOdlData.IdxPromessa; - } - return answ; + return _podlLocalCache.TryGetValue(idxOdl, out var val) ? val : 0; } /// @@ -174,6 +166,7 @@ namespace MP.SPEC.Components /// protected bool HasFolderMan(string idxMacc) { +#if false bool answ = true; // cerco nella LUT if (MachHasFolderLut.ContainsKey(idxMacc)) @@ -190,14 +183,40 @@ namespace MP.SPEC.Components MachHasFolderLut.Add(idxMacc, answ); } } - return answ; + return answ; +#endif + return MachHasFolderLut.ContainsKey(idxMacc) ? MachHasFolderLut[idxMacc] : false; } - protected void KitToggleDetail(string? selCodArt) + + private async Task ReloadLutData() + { + if (SearchRecords != null) + { + foreach (var item in SearchRecords) + { + string rawVal = ""; + bool answ = false; + var machData = await MDService.MachIobConfAsync(item.IdxMacchina); + if (machData.ContainsKey(KeyFolderMan)) + { + rawVal = machData[KeyFolderMan]; + if (rawVal != null) + { + bool.TryParse((string)rawVal, out answ); + MachHasFolderLut.Add(item.IdxMacchina, answ); + } + } + } + } + } + + + protected async Task KitToggleDetailAsync(string? selCodArt) { if (!string.IsNullOrEmpty(selCodArt)) { - ListKitTemplate = MDService.TemplateKitFilt(selCodArt, ""); + ListKitTemplate = await MDService.TemplateKitFiltAsync(selCodArt, ""); } else { @@ -208,8 +227,8 @@ namespace MP.SPEC.Components protected override async Task OnInitializedAsync() { - ListStati = await MDService.AnagStatiComm(); - ListArtKit = MDService.ArticoliGetByTipo("KIT", "*"); + ListStati = await MDService.AnagStatiCommAsync(); + ListArtKit = await MDService.ArticoliGetByTipoAsync("KIT", "*"); string SPEC_PODL_gest = await MDService.ConfigTryGetAsync("SPEC_PODL_gest"); if (!string.IsNullOrEmpty(SPEC_PODL_gest)) { @@ -229,13 +248,13 @@ namespace MP.SPEC.Components protected override async Task OnParametersSetAsync() { - await ReloadData(); + await ReloadDataAsync(); } protected async Task resetSel() { await selRecord(null); - await ReloadData(); + await ReloadDataAsync(); } protected async Task selBrowseRecord(ODLExpModel? currRec) @@ -278,7 +297,7 @@ namespace MP.SPEC.Components protected async Task UpdateData() { await selRecord(null); - await ReloadData(); + await ReloadDataAsync(); } #endregion Protected Methods @@ -362,21 +381,52 @@ namespace MP.SPEC.Components #region Private Methods - private async Task ReloadData() + private async Task ReloadDataAsync() { isLoading = true; - SearchRecords = await MDService.OdlListGetFilt(currFilter.IsActive, currFilter.SearchVal, currFilter.CodFase, currFilter.CodReparto, currFilter.IdxMacchina, currFilter.DtStart, currFilter.DtEnd); + SearchRecords = await MDService.OdlListGetFiltAsync(currFilter.IsActive, currFilter.SearchVal, currFilter.CodFase, currFilter.CodReparto, currFilter.IdxMacchina, currFilter.DtStart, currFilter.DtEnd); + await ReloadPOdlData(); + await ReloadLutData(); totalCount = SearchRecords.Count; ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList(); isLoading = false; } + private Dictionary _podlLocalCache = new(); + private async Task ReloadPOdlData() + { + _podlLocalCache.Clear(); + if (SearchRecords != null) + { + var listIdx = SearchRecords.Select(x => x.IdxOdl).ToList(); + _podlLocalCache = await MDService.PODL_getDictOdlPodlAsync(listIdx); +#if false + // 1. Popolo la cache locale in parallelo sfruttando la velocità di FusionCache + var tasks = SearchRecords.Select(async odl => + { + int podl = 0; + var pOdlData = await MDService.POdlGetByOdlAsync(odl.IdxOdl); + if (pOdlData != null) + { + podl = pOdlData.IdxPromessa; + } + return (odl.IdxOdl, podl); + }); + + var infoSalvate = await Task.WhenAll(tasks); + + // 2. Trasformazione dei risultati in un dizionario per l'accesso immediato (O(1)) nell'HTML + _podlLocalCache = infoSalvate.ToDictionary(x => x.IdxOdl, x => x.podl); +#endif + } + } + private async Task reloadStatsData(ODLExpModel? currRec) { showStats = true; if (currRec != null) { - ListOdlStats = await MDService.StatOdl(currRec.IdxOdl); + ListOdlStats = await MDService.OdlStatsAsync(currRec.IdxOdl); } else { diff --git a/MP.SPEC/Components/ListOdlLotto.razor.cs b/MP.SPEC/Components/ListOdlLotto.razor.cs index dac4f566..b71caa97 100644 --- a/MP.SPEC/Components/ListOdlLotto.razor.cs +++ b/MP.SPEC/Components/ListOdlLotto.razor.cs @@ -18,7 +18,7 @@ namespace MP.SPEC.Components { if (!string.IsNullOrEmpty(BatchSel)) { - elencoODL = await MDService.OdlByBatch(BatchSel); + elencoODL = await MDService.OdlByBatchAsync(BatchSel); } else { diff --git a/MP.SPEC/Components/ListPARAMS.razor.cs b/MP.SPEC/Components/ListPARAMS.razor.cs index 4e254b81..f65ba554 100644 --- a/MP.SPEC/Components/ListPARAMS.razor.cs +++ b/MP.SPEC/Components/ListPARAMS.razor.cs @@ -108,7 +108,7 @@ namespace MP.SPEC.Components dataTo = (DateTime)SelDtMax; } - SearchRecords = await MDService.FluxLogGetLastFilt(dataTo, dataFrom, SelMacchina, SelFlux, MaxRecord, RefreshPeriod / 1000); + SearchRecords = await MDService.FluxLogGetLastFiltAsync(dataTo, dataFrom, SelMacchina, SelFlux, MaxRecord, RefreshPeriod / 1000); totalCount = SearchRecords.Count; ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList(); await Task.Delay(1); diff --git a/MP.SPEC/Components/ListPODL.razor b/MP.SPEC/Components/ListPODL.razor index a651fcdf..ac739a63 100644 --- a/MP.SPEC/Components/ListPODL.razor +++ b/MP.SPEC/Components/ListPODL.razor @@ -16,7 +16,7 @@ else
              @if (showKitDetail) { - + }
              @@ -28,6 +28,7 @@ else } + @if (!(showRecipeConf || showRecipeArch)) @@ -42,7 +43,7 @@ else @foreach (var record in ListRecords) { - + + - @foreach (var record in ListTK) + @if (ListTK == null) { - - - } + else + { + foreach (var record in ListTK) + { + + + + + + } + }
              CodKit Articolo Fase
              @if (!(showRecipeConf || showRecipeArch)) { @@ -127,12 +128,22 @@ else } + @if (record.IsKitParent) + { + P. + } + else if (record.IsKitChild) + { + .C + } +
              @record.CodArticolo @if (CheckIsKit(record.CodArticolo)) { - + }
              @record.DescArticolo
              diff --git a/MP.SPEC/Components/ListPODL.razor.cs b/MP.SPEC/Components/ListPODL.razor.cs index f11ff3d5..0dca5e88 100644 --- a/MP.SPEC/Components/ListPODL.razor.cs +++ b/MP.SPEC/Components/ListPODL.razor.cs @@ -34,20 +34,11 @@ namespace MP.SPEC.Components #region Public Methods - public string checkSelect(PODLExpModel record) + public string CheckSelect(PODLExpModel thisRec) { - string answ = ""; - if (currRecord != null) - { - try - { - answ = (currRecord.IdxPromessa == record.IdxPromessa) ? "table-info" : ""; - //answ = ((SelRecord.IdxMacchina == record.IdxMacchina) && (SelRecord.CodArticolo == record.CodArticolo) && (SelRecord.CodFase == record.CodFase)) ? "table-info" : ""; - } - catch - { } - } - return answ; + return currRecord?.IdxPromessa == thisRec?.IdxPromessa + ? "table-info" + : ""; } public void Dispose() @@ -133,22 +124,22 @@ namespace MP.SPEC.Components var done = await MDService.POdlDeleteRecord(selRec); await callSyncDb(selRec.IdxMacchina); currRecord = null; - await ReloadData(); + await ReloadDataAsync(); await Task.Delay(1); } - protected void doShowRecipeArch(PODLExpModel selRec) + protected async Task doShowRecipeArch(PODLExpModel selRec) { currRecord = selRec; - currRecipeArchPath = MDService.MacchineRecipeArchive(selRec.IdxMacchina); + currRecipeArchPath = await MDService.MacchineRecipeArchiveAsync(selRec.IdxMacchina); showRecipeArch = true; showRecipeConf = false; } - protected void doShowRecipeConf(PODLExpModel selRec) + protected async Task doShowRecipeConf(PODLExpModel selRec) { currRecord = selRec; - currRecipePath = MDService.MacchineRecipeConf(selRec.IdxMacchina); + currRecipePath = await MDService.MacchineRecipeConfAsync(selRec.IdxMacchina); showRecipeArch = false; showRecipeConf = true; } @@ -160,12 +151,12 @@ namespace MP.SPEC.Components await RecordEdit.InvokeAsync(selRec); } - protected void KitToggleDetail(PODLExpModel? recSel) + protected async Task KitToggleDetailAsync(PODLExpModel? recSel) { if (recSel != null) { - ListKitTemplate = MDService.TemplateKitFilt(recSel.CodArticolo, ""); - ListPOdlKit = MDService.POdlListByKitParent(recSel.IdxPromessa); + ListKitTemplate = await MDService.TemplateKitFiltAsync(recSel.CodArticolo, ""); + ListPOdlKit = await MDService.POdlListByKitParentAsync(recSel.IdxPromessa); } else { @@ -177,8 +168,70 @@ namespace MP.SPEC.Components protected override async Task OnInitializedAsync() { - ListStati = await MDService.AnagStatiComm(); - ListArtKit = MDService.ArticoliGetByTipo("KIT", "*"); + await ReloadBaseData(); + } + + private string? _lastPadCodXdl; + private bool _initialized; + + protected override async Task OnParametersSetAsync() + { + // esempio: verifica parametri minimi + if (string.IsNullOrEmpty(padCodXdl) || actFilter == null) + return; + + if (!_initialized || !lastFilter.Equals(actFilter) || _lastPadCodXdl != padCodXdl) + { + _initialized = true; + + lastFilter = actFilter.clone(); + _lastPadCodXdl = padCodXdl; + + await ReloadDataAsync(); + } + } + + protected async void OnSeachUpdated() + { + await InvokeAsync(() => + { + PagerResetReq.InvokeAsync(true); + Task task = UpdateData(); + StateHasChanged(); + }); + } + + protected bool POdlDelEnabled(int idxOdl) + { + return idxOdl == 0; + } + + /// + /// Caricamento dati di base + /// + /// + protected async Task ReloadBaseData() + { + ListRecords = null; + isLoading = true; + + var list = await MDService.MachineWithOdlAsync(); + _odlCurrSet = list.ToHashSet(); + + var machines = await MDService.MacchineGetFiltAsync("*"); + + _machinesWithConf = machines + .Where(x => !string.IsNullOrEmpty(x.RecipePath)) + .Select(x => x.IdxMacchina) + .ToHashSet(); + + _machinesWithArch = machines + .Where(x => !string.IsNullOrEmpty(x.RecipeArchivePath)) + .Select(x => x.IdxMacchina) + .ToHashSet(); + + ListStati = await MDService.AnagStatiCommAsync(); + ListArtKit = await MDService.ArticoliGetByTipoAsync("KIT", "*"); string strMachRecipe = await MDService.ConfigTryGetAsync("MachineWithRecipe"); if (!string.IsNullOrEmpty(strMachRecipe)) { @@ -201,42 +254,50 @@ namespace MP.SPEC.Components } } - protected override async Task OnParametersSetAsync() + protected async Task ReloadDataAsync() { - if (!lastFilter.Equals(actFilter)) - { - lastFilter = actFilter.clone(); - await ReloadData(); - } - } - - protected async void OnSeachUpdated() - { - await InvokeAsync(() => - { - PagerResetReq.InvokeAsync(true); - Task task = UpdateData(); - StateHasChanged(); - }); - } - - protected bool POdlDelEnabled(int idxOdl) - { - return idxOdl == 0; - } - - protected async Task ReloadData() - { - ListRecords = null; isLoading = true; - SearchRecords = await MDService.POdlListGetFiltAsync(hasOdl, StatoSel, macchina, reparto, selDtStart, selDtEnd); - if (totalCount != SearchRecords.Count) + ListRecords = null; + + // ✅ lancia in parallelo + var odlTask = UpdateOdlList(); + + Task> searchTask; + + if (actFilter.ShowKit) { - totalCount = SearchRecords.Count; + searchTask = MDService.POdlListGetFiltAsync(hasOdl, StatoSel, macchina, reparto, selDtStart, selDtEnd); } - ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList(); - await Task.Delay(1); - await InvokeAsync(() => StateHasChanged()); + else + { + searchTask = MDService.POdlToKitListGetFiltAsync(hasOdl, StatoSel, macchina, reparto, selDtStart, selDtEnd); + } + + // ✅ aspetta tutto insieme + await Task.WhenAll(odlTask, searchTask); + var rawList = searchTask.Result; + // se abilitata ricerca filtro ulteriormente.. + if (string.IsNullOrEmpty(actFilter.SearchVal)) + { + SearchRecords = rawList; + } + else + { + SearchRecords = rawList + .Where(x => + x.CodArticolo.Contains(actFilter.SearchVal, StringComparison.InvariantCulture) + || x.CodFase.Contains(actFilter.SearchVal, StringComparison.InvariantCulture) + || x.DescArticolo.Contains(actFilter.SearchVal, StringComparison.InvariantCulture) + ).ToList(); + } + + totalCount = SearchRecords.Count; + + ListRecords = SearchRecords + .Skip(numRecord * (currPage - 1)) + .Take(numRecord) + .ToList(); + isLoading = false; } @@ -248,7 +309,7 @@ namespace MP.SPEC.Components showRecipeConf = false; if (forceUpdate) { - await ReloadData(); + await ReloadDataAsync(); } await RecordEdit.InvokeAsync(null); } @@ -279,7 +340,8 @@ namespace MP.SPEC.Components if (fatto) { var currPOdl = await MDService.POdlGetByKey(selRec.IdxPromessa); - var newOdl = await MDService.OdlGetByKey(currPOdl.IdxOdl); + var newOdl = await MDService.OdlByKeyAsync(currPOdl.IdxOdl); + //var newOdl = await MDService.OdlGetByKey(currPOdl.IdxOdl); // registro evento... idxEvento = 2; @@ -299,18 +361,20 @@ namespace MP.SPEC.Components string odlPad = newOdl.IdxOdl.ToString(padCodXdl); await callTask2Exe(selRec.IdxMacchina, "setComm", $"ODL{odlPad}"); await callTask2Exe(selRec.IdxMacchina, "setPzComm", $"{newOdl.NumPezzi}"); + await Task.Delay(1); // chiamo task x IOB await callForceUpdate(selRec.IdxMacchina); - await Task.Delay(1); - await callForceUpdate(selRec.IdxMacchina); + //await Task.Delay(1); + //await callForceUpdate(selRec.IdxMacchina); await Task.Delay(1); await callSyncDb(selRec.IdxMacchina); - await Task.Delay(1); // svuoto memorie pagina... - await MDService.FlushRedisCache(); + await MDService.ForceFlushRedisCache(); // svuoto cache MpIoNsCache - await MDService.FlushMpIoOdlCache(); + await MDService.FlushRedisCacheMpIoOdl(); + // svuoto altra cache + await MDService.ForceFlushFusionCacheAsync(); // ricarico pagina! NavManager.NavigateTo(NavManager.Uri, true); @@ -322,7 +386,7 @@ namespace MP.SPEC.Components protected async Task UpdateData() { currRecord = null; - await ReloadData(); + await ReloadDataAsync(); } #endregion Protected Methods @@ -330,6 +394,9 @@ namespace MP.SPEC.Components #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); + private HashSet _machinesWithArch = new(); + private HashSet _machinesWithConf = new(); + private HashSet _odlCurrSet = new(); private string currRecipeArchPath = ""; /// @@ -535,24 +602,22 @@ namespace MP.SPEC.Components } /// - /// verifica se sia avviabile ODL x idxMaccSel + /// Verifica se sia avviabile ODL x idxMaccSel /// /// /// private bool canStartOdl(string idxMacchina) { - // controllo se lista scaduta... - bool answ = false; - DateTime adesso = DateTime.Now; - if (adesso > odlCurrExp || odlCurrList == null || odlCurrList.Count == 0) - { - odlCurrList = MDService.OdlGetCurrent(); - odlCurrExp = adesso.AddSeconds(2); - } - answ = !odlCurrList.Contains(idxMacchina); - return answ; + return !_odlCurrSet.Contains(idxMacchina); } + private async Task UpdateOdlList() + { + var list = await MDService.MachineWithOdlAsync(); + _odlCurrSet = list.ToHashSet(); + } + + /// /// Verifica se la idxMaccSel abbia associata un path x ricette (elenco) /// @@ -560,8 +625,7 @@ namespace MP.SPEC.Components /// private bool machineHasRecipeArch(string idxMacchina) { - var recipeArchive = MDService.MacchineRecipeArchive(idxMacchina); - return !string.IsNullOrEmpty(recipeArchive); + return _machinesWithArch.Contains(idxMacchina); } /// @@ -571,8 +635,7 @@ namespace MP.SPEC.Components /// private bool machineHasRecipeConf(string idxMacchina) { - var recipePath = MDService.MacchineRecipeConf(idxMacchina); - return !string.IsNullOrEmpty(recipePath); + return _machinesWithConf.Contains(idxMacchina); } /// @@ -587,7 +650,8 @@ namespace MP.SPEC.Components // se manca codart calcolo... if (string.IsNullOrEmpty(codArticolo)) { - var currOdl = await MDService.OdlGetByKey(idxODL); + var currOdl = await MDService.OdlByKeyAsync(idxODL); + //var currOdl = await MDService.OdlGetByKey(idxODL); if (currOdl != null) { codArticolo = currOdl.CodArticolo; diff --git a/MP.SPEC/Components/ODLPlot.razor.cs b/MP.SPEC/Components/ODLPlot.razor.cs index 9e51d6e7..6a2fbafc 100644 --- a/MP.SPEC/Components/ODLPlot.razor.cs +++ b/MP.SPEC/Components/ODLPlot.razor.cs @@ -64,7 +64,7 @@ namespace MP.SPEC.Components Data.Clear(); Labels.Clear(); colors.Clear(); - ListRecords = await MDService.StatOdl(SelectedOdl); + ListRecords = await MDService.OdlStatsAsync(SelectedOdl); // se hideSpenta --> filtro stato 11 = spenta... if (hideSpenta) { diff --git a/MP.SPEC/Components/ParamsFilter.razor.cs b/MP.SPEC/Components/ParamsFilter.razor.cs index 6bb8c6e4..8b3c784d 100644 --- a/MP.SPEC/Components/ParamsFilter.razor.cs +++ b/MP.SPEC/Components/ParamsFilter.razor.cs @@ -109,7 +109,7 @@ namespace MP.SPEC.Components SelFilter.CurrPage = 1; SelFilter.IdxMacchina = value; SelFilter.CodFlux = "*"; - ListFlux = MDService.ParametriGetFilt(selMacchina).Result; + ListFlux = MDService.ParametriGetFiltAsync(selMacchina).Result; StateHasChanged(); Task.Delay(1); reportChange(); @@ -171,7 +171,7 @@ namespace MP.SPEC.Components protected override async Task OnInitializedAsync() { SelFilter = new SelectFluxParams(); - await MDService.ConfigResetCache(); + await MDService.ConfigResetCacheAsync(); var result = await MDService.ConfigTryGetAsync("SPEC_ParamTempoAgg"); if (result != null) { @@ -181,8 +181,8 @@ namespace MP.SPEC.Components setDtSnap(); DateTime dtStart = SelFilter.dtMin != null ? (DateTime)SelFilter.dtMin : DateTime.Now.AddMonths(-1); DateTime dtEnd = SelFilter.dtMax != null ? (DateTime)SelFilter.dtMax : DateTime.Today.AddDays(1); - ListMacchine = await MDService.MacchineWithFlux(dtStart, dtEnd); - ListFlux = await MDService.ParametriGetFilt(selMacchina); + ListMacchine = await MDService.MacchineWithFluxAsync(dtStart, dtEnd); + ListFlux = await MDService.ParametriGetFiltAsync(selMacchina); var configData = await MDService.ConfigGetAllAsync(); var currRec = configData.FirstOrDefault(x => x.Chiave == "numOreAnticipoSnapshot"); diff --git a/MP.SPEC/Components/ProdKit/GestKitPodl.razor.cs b/MP.SPEC/Components/ProdKit/GestKitPodl.razor.cs index bac741bc..e15fd13e 100644 --- a/MP.SPEC/Components/ProdKit/GestKitPodl.razor.cs +++ b/MP.SPEC/Components/ProdKit/GestKitPodl.razor.cs @@ -101,8 +101,7 @@ namespace MP.SPEC.Components.ProdKit if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione PODL + Istanze KIT: sei sicuro di voler procedere?")) return; - // da provare... - var done = MDService.PodlIstKitDelete(selRec.IdxPromessa); + var done = await MDService.PodlIstKitDeleteAsync(selRec.IdxPromessa); ReloadData(); await EC_ListUpdated.InvokeAsync(true); } @@ -115,22 +114,22 @@ namespace MP.SPEC.Components.ProdKit } } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { numRecord = 5; // gestione di base dei KIT - string rawVal = MDService.ConfigTryGet("OptAdmKitEnabled"); + string rawVal = await MDService.ConfigTryGetAsync("OptAdmKitEnabled"); if (!string.IsNullOrEmpty(rawVal)) { bool.TryParse(rawVal, out OptAdmKitEnabled); } // conf variabili decodifica - regExp_KO = MDService.ConfigTryGet("regExp_KO"); - regExp_OK = MDService.ConfigTryGet("regExp_OK"); - regExp_KitStart = MDService.ConfigTryGet("regExp_KitStart"); - regExp_KitSave = MDService.ConfigTryGet("regExp_KitSave"); + regExp_KO = await MDService.ConfigTryGetAsync("regExp_KO"); + regExp_OK = await MDService.ConfigTryGetAsync("regExp_OK"); + regExp_KitStart = await MDService.ConfigTryGetAsync("regExp_KitStart"); + regExp_KitSave = await MDService.ConfigTryGetAsync("regExp_KitSave"); // altre variabili - rawVal = MDService.ConfigTryGet("SPEC_nArtSearch"); + rawVal = await MDService.ConfigTryGetAsync("SPEC_nArtSearch"); if (!string.IsNullOrEmpty(rawVal)) { int.TryParse(rawVal, out minChar); @@ -301,7 +300,7 @@ namespace MP.SPEC.Components.ProdKit { isLoading = true; // reset preliminare... - ListRecordsPODL = new List(); + ListRecordsPODL?.Clear(); var filtRecordsPODL = PodlRecords .Where(x => !string.IsNullOrEmpty(x.KeyRichiesta) && x.KeyRichiesta.StartsWith("KIT")) diff --git a/MP.SPEC/Components/ProdKit/KitComposer.razor.cs b/MP.SPEC/Components/ProdKit/KitComposer.razor.cs index c27d4ea9..dd153f37 100644 --- a/MP.SPEC/Components/ProdKit/KitComposer.razor.cs +++ b/MP.SPEC/Components/ProdKit/KitComposer.razor.cs @@ -10,10 +10,10 @@ namespace MP.SPEC.Components.ProdKit #region Public Properties [Parameter] - public EventCallback EC_ListUpdated { get; set; } + public EventCallback EC_ListCleared { get; set; } [Parameter] - public EventCallback EC_ListCleared { get; set; } + public EventCallback EC_ListUpdated { get; set; } [Parameter] public string KeyFilt { get; set; } = ""; @@ -42,7 +42,7 @@ namespace MP.SPEC.Components.ProdKit // elimino TUTTO... DateTime dtLimit = DateTime.Now;//.AddHours(-1); - var done = MDService.WipKitDeleteOlder(dtLimit); + var done = await MDService.WipKitDeleteOlderAsync(dtLimit); await EC_ListCleared.InvokeAsync(false); } @@ -51,18 +51,18 @@ namespace MP.SPEC.Components.ProdKit if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione riga KIT: sei sicuro di voler procedere?")) return; - var done = MDService.WipKitDelete(rec2del); + var done = await MDService.WipKitDeleteAsync(rec2del); await EC_ListUpdated.InvokeAsync(false); } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { // calcolo codice temporaneo utente...da apertura KIT if (string.IsNullOrEmpty(KeyFilt)) { // elimino dati + vecchi di 2h... DateTime dtLimit = DateTime.Now.AddHours(-2); - var done = MDService.WipKitDeleteOlder(dtLimit); + var done = await MDService.WipKitDeleteOlderAsync(dtLimit); } } @@ -75,7 +75,6 @@ namespace MP.SPEC.Components.ProdKit #region Private Fields - private PODLExpModel? currRec = null; private List ListRecords = new List(); #endregion Private Fields diff --git a/MP.SPEC/Components/ProdKit/KitDetailModal.razor b/MP.SPEC/Components/ProdKit/KitDetailModal.razor index 25fc0836..1c815937 100644 --- a/MP.SPEC/Components/ProdKit/KitDetailModal.razor +++ b/MP.SPEC/Components/ProdKit/KitDetailModal.razor @@ -80,20 +80,31 @@
              - @record.CodArtParent - - @record.CodArtChild - -
              @record.Qty
              +
              +
              No data found
              + @record.CodArtParent + + @record.CodArtChild + +
              @record.Qty
              +
              } diff --git a/MP.SPEC/Components/ProdKit/KitPodlMan.razor.cs b/MP.SPEC/Components/ProdKit/KitPodlMan.razor.cs index 5f8d0254..0bb9c05f 100644 --- a/MP.SPEC/Components/ProdKit/KitPodlMan.razor.cs +++ b/MP.SPEC/Components/ProdKit/KitPodlMan.razor.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; -using MP.Data; using MP.Data.DbModels; using MP.SPEC.Data; using MP.SPEC.Services; @@ -12,6 +11,9 @@ namespace MP.SPEC.Components.ProdKit { #region Public Properties + [Parameter] + public SelectXdlParams ActFilter { get; set; } = new SelectXdlParams(); + [Parameter] public EventCallback EC_RecordSel { get; set; } @@ -22,10 +24,11 @@ namespace MP.SPEC.Components.ProdKit public EventCallback PagerResetReq { get; set; } [Parameter] - public EventCallback UpdateRecordCount { get; set; } + public List AllRecords { get; set; } = null!; + private List SelRecords = new(); [Parameter] - public SelectXdlParams ActFilter { get; set; } = new SelectXdlParams(); + public EventCallback UpdateRecordCount { get; set; } #endregion Public Properties @@ -49,7 +52,6 @@ namespace MP.SPEC.Components.ProdKit public void Dispose() { currRecord = null; - SearchRecords = null; ListRecords = null; GC.Collect(); } @@ -88,6 +90,11 @@ namespace MP.SPEC.Components.ProdKit get => string.IsNullOrEmpty(SearchVal) ? "btn-secondary" : "btn-primary"; } + protected string sSearchtCss + { + get => string.IsNullOrEmpty(searchVal) ? "btn-secondary" : "btn-primary"; + } + #endregion Protected Properties #region Protected Methods @@ -110,7 +117,7 @@ namespace MP.SPEC.Components.ProdKit if (!lastFilter.Equals(ActFilter) || true) { lastFilter = ActFilter.clone(); - await ReloadData(); + await ReloadDataAsync(); } } @@ -124,15 +131,17 @@ namespace MP.SPEC.Components.ProdKit }); } - protected async Task ReloadData() + protected async Task ReloadDataAsync() { ListRecords = null; isLoading = true; - SearchRecords = await MDService.POdlToKitListGetFiltAsync(hasOdl, StatoSel, macchina, reparto, selDtStart, selDtEnd); +#if false + AllRecords = await MDService.POdlToKitListGetFiltAsync(hasOdl, StatoSel, macchina, reparto, selDtStart, selDtEnd); +#endif // rivedere filtro FixMe ToDo!!! // filtro tenendo SOLO se hanno keyRichiesta CodExt + ATTIVI + NON KIT | Hard Coded... - SearchRecords = SearchRecords + SelRecords = AllRecords .Where(x => !string.IsNullOrEmpty(x.KeyRichiesta) && x.Attivabile && !x.KeyRichiesta.StartsWith("KIT")) .ToList(); @@ -152,7 +161,7 @@ namespace MP.SPEC.Components.ProdKit currPage = 1; if (forceUpdate) { - await ReloadData(); + await ReloadDataAsync(); } } @@ -179,7 +188,7 @@ namespace MP.SPEC.Components.ProdKit protected async Task UpdateData() { currRecord = null; - await ReloadData(); + await ReloadDataAsync(); } #endregion Protected Methods @@ -197,15 +206,8 @@ namespace MP.SPEC.Components.ProdKit ///
    private List odlCurrList = new List(); - private List? SearchRecords; - private string searchVal = ""; - protected string sSearchtCss - { - get => string.IsNullOrEmpty(searchVal) ? "btn-secondary" : "btn-primary"; - } - #endregion Private Fields #region Private Properties @@ -298,9 +300,9 @@ namespace MP.SPEC.Components.ProdKit private void UpdateTable() { totalCount = 0; - if (SearchRecords != null) + if (SelRecords != null) { - var filtRec = new List(SearchRecords); + var filtRec = new List(SelRecords); // se ho ricerca filtro! if (!string.IsNullOrEmpty(searchVal)) { @@ -310,7 +312,7 @@ namespace MP.SPEC.Components.ProdKit { int.TryParse(searchVal.Replace("PODL", ""), out idxPodl); } - filtRec = SearchRecords + filtRec = AllRecords .Where(x => (x.KeyRichiesta.Contains(searchVal, StringComparison.InvariantCultureIgnoreCase) || x.KeyBCode.Contains(searchVal, StringComparison.InvariantCultureIgnoreCase) || (x.IdxPromessa == idxPodl && idxPodl > 0)) diff --git a/MP.SPEC/Components/ProdKit/KitVerify.razor b/MP.SPEC/Components/ProdKit/KitVerify.razor index 96e5f8ba..6ead57b4 100644 --- a/MP.SPEC/Components/ProdKit/KitVerify.razor +++ b/MP.SPEC/Components/ProdKit/KitVerify.razor @@ -16,7 +16,7 @@ { @if (doShowDetail) { - + } @@ -33,7 +33,7 @@ { diff --git a/MP.SPEC/Components/ProdKit/KitVerify.razor.cs b/MP.SPEC/Components/ProdKit/KitVerify.razor.cs index 13868a07..aecb9913 100644 --- a/MP.SPEC/Components/ProdKit/KitVerify.razor.cs +++ b/MP.SPEC/Components/ProdKit/KitVerify.razor.cs @@ -41,17 +41,17 @@ namespace MP.SPEC.Components.ProdKit #region Protected Methods - protected void KitToggleDetail(TksScoreModel? currRec) + protected async Task KitToggleDetailAsync(TksScoreModel? currRec) { CodArtParent = currRec != null ? currRec.CodArtParent : ""; if (!string.IsNullOrEmpty(CodArtParent)) { - ListKitTemplate = MDService.TemplateKitFilt(CodArtParent, ""); + ListKitTemplate = await MDService.TemplateKitFiltAsync(CodArtParent, ""); totalKitCount = ListKitTemplate.Count; ListRecKitPODL = PodlRecords - .Where(x => !string.IsNullOrEmpty(x.KeyRichiesta) + .Where(x => !string.IsNullOrEmpty(x.KeyRichiesta) && x.KeyRichiesta.StartsWith("KIT") - && x.CodArticolo==CodArtParent) + && x.CodArticolo == CodArtParent) .ToList(); } else @@ -99,12 +99,9 @@ namespace MP.SPEC.Components.ProdKit return; // eseguo stored... - bool fatto = MDService.IstKitInsertByWKS(currRec.CodArtParent, KeyFilt); - if (fatto) - { - // segnalo update - await EC_KitCreated.InvokeAsync(true); - } + bool fatto = await MDService.IstKitInsertByWKSAsync(currRec.CodArtParent, KeyFilt); + // segnalo update + await EC_KitCreated.InvokeAsync(fatto); } private void ReloadData() diff --git a/MP.SPEC/Components/ProdKit/Manager.razor b/MP.SPEC/Components/ProdKit/Manager.razor index 68957397..98156c3c 100644 --- a/MP.SPEC/Components/ProdKit/Manager.razor +++ b/MP.SPEC/Components/ProdKit/Manager.razor @@ -10,13 +10,13 @@ @if (DoAddNew) {
    - +
    - +
    }
    diff --git a/MP.SPEC/Components/ProdKit/Manager.razor.cs b/MP.SPEC/Components/ProdKit/Manager.razor.cs index 283763bf..f42c073f 100644 --- a/MP.SPEC/Components/ProdKit/Manager.razor.cs +++ b/MP.SPEC/Components/ProdKit/Manager.razor.cs @@ -2,8 +2,6 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using MP.Data.DbModels; using MP.SPEC.Data; -using System; -using System.Reflection.PortableExecutable; namespace MP.SPEC.Components.ProdKit { @@ -42,7 +40,7 @@ namespace MP.SPEC.Components.ProdKit isLoading = false; if (string.IsNullOrEmpty(padCodXdl)) { - padCodXdl = MDService.ConfigTryGet("padCodXdl"); + padCodXdl = await MDService.ConfigTryGetAsync("padCodXdl"); } currPodlRec = null; // recupero user... @@ -70,10 +68,9 @@ namespace MP.SPEC.Components.ProdKit DateTime oggi = DateTime.Today; } - protected override void OnParametersSet() + protected override async Task OnParametersSetAsync() { - //base.OnParametersSet(); - ReloadData(); + await ReloadDataAsync(); } /// @@ -97,7 +94,7 @@ namespace MP.SPEC.Components.ProdKit Qta = selRec.NumPezzi, DataIns = DateTime.Now }; - bool fatto = MDService.WipKitUpsert(newRec); + bool fatto = await MDService.WipKitUpsertAsync(newRec); // se non gi impostato riporto impostazione filtro con macchina e gruppo ricevuto... ActFilt.IdxMacchina = selRec.IdxMacchina; ActFilt.CodReparto = selRec.CodGruppo; @@ -105,10 +102,10 @@ namespace MP.SPEC.Components.ProdKit } currPodlRec = selRec; isComposing = true; - await EC_IsComposing.InvokeAsync(true); + await EC_IsComposing.InvokeAsync(isComposing); // rileggo - ReloadData(); + await ReloadDataAsync(); } } @@ -132,6 +129,7 @@ namespace MP.SPEC.Components.ProdKit private List listPOdlCheck = new List(); private List listTSM = new List(); private List listWSM = new List(); + private List listPOdl2Kit = new List(); private string padCodXdl = "00000"; private string userName = ""; private string userNameFull = ""; @@ -164,16 +162,16 @@ namespace MP.SPEC.Components.ProdKit { calcKitCode(); } - ReloadData(); + await ReloadDataAsync(); isComposing = false; - await EC_IsComposing.InvokeAsync(false); + await EC_IsComposing.InvokeAsync(isComposing); } private async Task SetHasOdl(bool setHasOdl) { ActFilt.HasOdl = setHasOdl; await EC_FiltUpdated.InvokeAsync(ActFilt); - ReloadData(); + await ReloadDataAsync(); } private async Task ForceReset() @@ -186,13 +184,14 @@ namespace MP.SPEC.Components.ProdKit await EC_FiltUpdated.InvokeAsync(ActFilt); } - private void ReloadData() + private async Task ReloadDataAsync() { listPOdlCheck = new List(); - listPOdlAct = MDService.POdlListGetFilt(ActFilt.HasOdl, ActFilt.CodFase, ActFilt.IdxMacchina, ActFilt.CodReparto, ActFilt.DtStart, ActFilt.DtEnd); - listWSM = MDService.WipKitFilt(keyFilt); - listTSM = MDService.TksScore(keyFilt, 1000, true); - listIKP = MDService.IstKitFilt("", ""); + listPOdlAct = await MDService.POdlListGetFiltAsync(ActFilt.HasOdl, ActFilt.CodFase, ActFilt.IdxMacchina, ActFilt.CodReparto, ActFilt.DtStart, ActFilt.DtEnd); + listPOdl2Kit = await MDService.POdlToKitListGetFiltAsync(ActFilt.HasOdl, ActFilt.CodFase, ActFilt.IdxMacchina, ActFilt.CodReparto, ActFilt.DtStart, ActFilt.DtEnd); + listWSM = await MDService.WipKitFiltAsync(keyFilt); + listTSM = await MDService.TksScoreAsync(keyFilt, 1000, true); + listIKP = await MDService.IstKitFiltAsync("", ""); // verifico se ho score 100%... var recMaxScore = listTSM .Where(x => x.TotalScore == 1) @@ -202,7 +201,7 @@ namespace MP.SPEC.Components.ProdKit // continuo con PODL if (!string.IsNullOrEmpty(codArtKit)) { - listPOdlCheck = MDService.ListPODL_ByCodArt(codArtKit, true); + listPOdlCheck = await MDService.ListPODL_ByCodArtAsync(codArtKit, true); } isLoading = false; } diff --git a/MP.SPEC/Components/Reparti/ListMacchine.razor.cs b/MP.SPEC/Components/Reparti/ListMacchine.razor.cs index f8a2d32c..cd163788 100644 --- a/MP.SPEC/Components/Reparti/ListMacchine.razor.cs +++ b/MP.SPEC/Components/Reparti/ListMacchine.razor.cs @@ -100,7 +100,7 @@ namespace MP.SPEC.Components.Reparti CodGruppo = CodGruppoCurr, IdxMacchina = currRec.IdxMacchina }; - MDService.Grp2MaccInsert(rec2del); + await MDService.Grp2MaccInsertAsync(rec2del); await EC_RecChange.InvokeAsync(false); } @@ -115,7 +115,7 @@ namespace MP.SPEC.Components.Reparti CodGruppo = CodGruppoCurr, IdxMacchina = currRec.IdxMacchina }; - MDService.Grp2MaccDelete(rec2del); + await MDService.Grp2MaccDeleteAsync(rec2del); await EC_RecChange.InvokeAsync(false); } diff --git a/MP.SPEC/Components/Reparti/ListOperatori.razor b/MP.SPEC/Components/Reparti/ListOperatori.razor index 959835cb..93bfcd3d 100644 --- a/MP.SPEC/Components/Reparti/ListOperatori.razor +++ b/MP.SPEC/Components/Reparti/ListOperatori.razor @@ -5,7 +5,10 @@

    Operatori

    - + @if (AddEnabled) + { + + }
    @@ -33,25 +36,51 @@
    - + @record.CodArtParent @record.ChildFound / @numRecWsm
    + - + @if (DelEnabled) + { + + } + @if (StaChgEnab) + { + + } - @foreach (var record in ListRecords) + @foreach (var item in ListRecords) { - + - - - + @if (DelEnabled) + { + + } + @if (StaChgEnab) + { + + } } diff --git a/MP.SPEC/Components/Reparti/ListOperatori.razor.cs b/MP.SPEC/Components/Reparti/ListOperatori.razor.cs index eab82552..73f18c0b 100644 --- a/MP.SPEC/Components/Reparti/ListOperatori.razor.cs +++ b/MP.SPEC/Components/Reparti/ListOperatori.razor.cs @@ -9,6 +9,9 @@ namespace MP.SPEC.Components.Reparti { #region Public Properties + [Parameter] + public bool AddEnabled { get; set; } = true; + [Parameter] public List? AllRecords { get; set; } = null; @@ -18,9 +21,18 @@ namespace MP.SPEC.Components.Reparti [Parameter] public List? CurrRecords { get; set; } = null; + [Parameter] + public bool DelEnabled { get; set; } = true; + [Parameter] public EventCallback EC_RecChange { get; set; } + [Parameter] + public EventCallback EC_RecSel { get; set; } + + [Parameter] + public bool StaChgEnab { get; set; } = false; + #endregion Public Properties #region Protected Properties @@ -37,7 +49,7 @@ namespace MP.SPEC.Components.Reparti protected override void OnParametersSet() { - numRecord = 10; + //numRecord = 10; UpdateTable(); } @@ -62,12 +74,12 @@ namespace MP.SPEC.Components.Reparti private int currPage = 1; - private AnagOperatoriModel? EditRecord = null; - private bool isLoading = false; private List? ListAvail; + private List? ListRecords; + private int numRecord = 5; private int totalCount = 0; @@ -95,6 +107,18 @@ namespace MP.SPEC.Components.Reparti #region Private Methods + private string cssCol(AnagOperatoriModel currRec) + { + return !currRec.isEnabled ? "opacity-75" : ""; + } + + private string cssRow(AnagOperatoriModel currRec) + { + string answ = selRec != null && currRec.MatrOpr == selRec.MatrOpr ? "table-info " : ""; + answ += !currRec.isEnabled ? "text-secondary disabled text-decoration-line-through" : ""; + return answ; + } + private async Task DoAdd(AnagOperatoriModel currRec) { // eliminazione dal gruppo @@ -103,7 +127,7 @@ namespace MP.SPEC.Components.Reparti CodGruppo = CodGruppoCurr, MatrOpr = currRec.MatrOpr }; - MDService.Grp2OperInsert(rec2del); + await MDService.Grp2OperInsertAsync(rec2del); await EC_RecChange.InvokeAsync(false); } @@ -118,10 +142,23 @@ namespace MP.SPEC.Components.Reparti CodGruppo = CodGruppoCurr, MatrOpr = currRec.MatrOpr }; - MDService.Grp2OperDelete(rec2del); + await MDService.Grp2OperDeleteAsync(rec2del); await EC_RecChange.InvokeAsync(false); } + private AnagOperatoriModel? selRec = null; + + private async Task DoSelect(AnagOperatoriModel sRec) + { + selRec = sRec; + await EC_RecSel.InvokeAsync(sRec); + } + private async Task DoReset() + { + selRec = null; + await EC_RecSel.InvokeAsync(null); + } + private async Task ReportUpdate(bool force) { AddNewEnabled = false; @@ -133,6 +170,17 @@ namespace MP.SPEC.Components.Reparti AddNewEnabled = !AddNewEnabled; } + private async Task ToggleStatusOpr(AnagOperatoriModel updRec) + { + string azione = updRec.isEnabled ? "disabilitarlo" : "abilitarlo"; + if (!await JSRuntime.InvokeAsync("confirm", $"Sicuro di voler modificare l'operatore per {azione}?")) + return; + + updRec.isEnabled = !updRec.isEnabled; + await MDService.OperatoriUpsertAsync(updRec); + await EC_RecChange.InvokeAsync(true); + } + private void UpdateTable() { ListRecords = new(); diff --git a/MP.SPEC/Components/Reparti/ListReparti.razor b/MP.SPEC/Components/Reparti/ListReparti.razor index 05f03dfe..b8a1b5f6 100644 --- a/MP.SPEC/Components/Reparti/ListReparti.razor +++ b/MP.SPEC/Components/Reparti/ListReparti.razor @@ -5,7 +5,7 @@

    Elenco Reparti

    - @if (SelRecord == null && IsSuperAdmin) + @if (SelRecord == null && IsSuperAdmin && EditEnabled) { } @@ -95,17 +95,20 @@ {
    @if (SelRecord == null) @@ -122,13 +125,16 @@ } diff --git a/MP.SPEC/Components/Reparti/ListReparti.razor.cs b/MP.SPEC/Components/Reparti/ListReparti.razor.cs index f95b835b..3f65ced9 100644 --- a/MP.SPEC/Components/Reparti/ListReparti.razor.cs +++ b/MP.SPEC/Components/Reparti/ListReparti.razor.cs @@ -1,10 +1,9 @@ using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.DataProtection; using Microsoft.JSInterop; +using MP.AppAuth.Services; using MP.Core.DTO; using MP.Data.DbModels; using MP.SPEC.Data; -using MP.AppAuth.Services; namespace MP.SPEC.Components.Reparti { @@ -15,6 +14,12 @@ namespace MP.SPEC.Components.Reparti [Parameter] public List? AllRecords { get; set; } = null; + [Parameter] + public string CodGruppoSel { get; set; } = null!; + + [Parameter] + public bool EditEnabled { get; set; } = true; + [Parameter] public EventCallback EC_RecordSel { get; set; } @@ -25,11 +30,6 @@ namespace MP.SPEC.Components.Reparti #region Protected Properties - protected bool IsSuperAdmin - { - get => HasRole(AppAuthService.RoleSuperAdmin); - } - [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; @@ -63,6 +63,11 @@ namespace MP.SPEC.Components.Reparti protected override void OnParametersSet() { isLoading = true; + // verifico se ho gruppo sel... + if (!string.IsNullOrEmpty(CodGruppoSel) && AllRecords != null && AllRecords.Any()) + { + SelRecord = AllRecords.FirstOrDefault(x => x.CodGruppo == CodGruppoSel); + } UpdateTable(); isLoading = false; } @@ -117,6 +122,11 @@ namespace MP.SPEC.Components.Reparti get => EditRec == null ? "Aggiungi Reparto" : "Chiudi/Annulla"; } + private bool IsSuperAdmin + { + get => HasRole(AppAuthService.RoleSuperAdmin); + } + #endregion Private Properties #region Private Methods @@ -157,7 +167,7 @@ namespace MP.SPEC.Components.Reparti SelEnabled = selRec.SelEnabled, TipoGruppo = selRec.TipoGruppo }; - MDService.AnagGruppiDelete(rec2Del); + await MDService.AnagGruppiDeleteAsync(rec2Del); EditRec = null; await EC_RecordUpdated.InvokeAsync(true); } @@ -176,6 +186,7 @@ namespace MP.SPEC.Components.Reparti private async Task DoSelect(RepartiDTO currRec) { // seleziona + EditRec = null; SelRecord = currRec; await EC_RecordSel.InvokeAsync(currRec.CodGruppo); } @@ -183,7 +194,7 @@ namespace MP.SPEC.Components.Reparti private async Task DoUpdate(AnagGruppiModel UpdRec) { // salvo... - MDService.AnagGruppiUpsert(UpdRec); + await MDService.AnagGruppiUpsertAsync(UpdRec); EditRec = null; await EC_RecordUpdated.InvokeAsync(true); } @@ -192,6 +203,7 @@ namespace MP.SPEC.Components.Reparti { SelRecord = null; EditRec = null; + UpdateTable(); await EC_RecordSel.InvokeAsync(""); } diff --git a/MP.SPEC/Components/Routes.razor b/MP.SPEC/Components/Routes.razor new file mode 100644 index 00000000..37c2f803 --- /dev/null +++ b/MP.SPEC/Components/Routes.razor @@ -0,0 +1,12 @@ + + + + + + + Not found + +

    Sorry, there's nothing at this address.

    +
    +
    +
    diff --git a/MP.SPEC/Components/ScratchPodlKit.razor b/MP.SPEC/Components/ScratchPodlKit.razor index 97b46602..49004db1 100644 --- a/MP.SPEC/Components/ScratchPodlKit.razor +++ b/MP.SPEC/Components/ScratchPodlKit.razor @@ -12,7 +12,7 @@
    - +
    diff --git a/MP.SPEC/Components/ScratchPodlKit.razor.cs b/MP.SPEC/Components/ScratchPodlKit.razor.cs index e51d9229..d4cb17ef 100644 --- a/MP.SPEC/Components/ScratchPodlKit.razor.cs +++ b/MP.SPEC/Components/ScratchPodlKit.razor.cs @@ -46,13 +46,17 @@ namespace MP.SPEC.Components if (sCodComm != value) { sCodComm = value; - currPage = 1; - ListRecords = null; - ReloadData(); } } } + private async Task ResetDataAsync() + { + currPage = 1; + ListRecords = null; + await ReloadDataAsync(); + } + protected string sParentCss { get => string.IsNullOrEmpty(sCodComm) ? "btn-secondary" : "btn-primary"; @@ -92,8 +96,7 @@ namespace MP.SPEC.Components protected async Task DoCancel() { EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } /// @@ -106,11 +109,9 @@ namespace MP.SPEC.Components if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione riga Istanza KIT: sei sicuro di voler procedere?")) return; - await Task.Delay(1); - var done = await MDService.IstKitDelete(selRec); + var done = await MDService.IstKitDeleteAsync(selRec); EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } protected async Task DoUpdate(IstanzeKitModel selRec) @@ -118,49 +119,42 @@ namespace MP.SPEC.Components if (!await JSRuntime.InvokeAsync("confirm", "Confermi di voler salvare le modifiche?")) return; - await Task.Delay(1); - var done = await MDService.IstKitUpsert(selRec); + var done = await MDService.IstKitUpsertAsync(selRec); EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } - - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { numRecord = 10; // gestione di base dei KIT - string rawVal = MDService.ConfigTryGet("OptAdmKitEnabled"); + string rawVal = await MDService.ConfigTryGetAsync("OptAdmKitEnabled"); if (!string.IsNullOrEmpty(rawVal)) { bool.TryParse(rawVal, out OptAdmKitEnabled); } // conf variabili decodifica - regExp_KO = MDService.ConfigTryGet("regExp_KO"); - regExp_OK = MDService.ConfigTryGet("regExp_OK"); - regExp_KitStart = MDService.ConfigTryGet("regExp_KitStart"); - regExp_KitSave = MDService.ConfigTryGet("regExp_KitSave"); + regExp_KO = await MDService.ConfigTryGetAsync("regExp_KO"); + regExp_OK = await MDService.ConfigTryGetAsync("regExp_OK"); + regExp_KitStart = await MDService.ConfigTryGetAsync("regExp_KitStart"); + regExp_KitSave = await MDService.ConfigTryGetAsync("regExp_KitSave"); // altre variabili - rawVal = MDService.ConfigTryGet("SPEC_nArtSearch"); + rawVal = await MDService.ConfigTryGetAsync("SPEC_nArtSearch"); if (!string.IsNullOrEmpty(rawVal)) { int.TryParse(rawVal, out minChar); } } - protected override void OnParametersSet() + protected override async Task OnParametersSetAsync() { - ReloadData(); + await ReloadDataAsync(); } - protected void ResetData() - { - EditRecord = null; - } - protected void ResetParent() + protected async Task ResetParent() { SearchComm = ""; - ReloadData(); + await ResetDataAsync(); } protected void ResetSel() @@ -184,10 +178,10 @@ namespace MP.SPEC.Components numRecord = newNum; } - protected void UpdateData() + protected async Task UpdateData() { EditRecord = null; - ReloadData(); + await ResetDataAsync(); } #endregion Protected Methods @@ -242,7 +236,7 @@ namespace MP.SPEC.Components if (_currPage != value) { _currPage = value; - ReloadData(); + UpdateTable(); } } } @@ -257,7 +251,7 @@ namespace MP.SPEC.Components if (_numRecord != value) { _numRecord = value; - ReloadData(); + UpdateTable(); } } } @@ -270,17 +264,22 @@ namespace MP.SPEC.Components #region Private Methods - private void ReloadData() + private async Task ReloadDataAsync() { isLoading = true; - SearchRecords = MDService.IstKitFilt("", ""); + SearchRecords = await MDService.IstKitFiltAsync("", ""); totalCount = SearchRecords.Count; // conto i kit = distinct... kitCount = SearchRecords.GroupBy(x => x.CodArtParent).Count(); - ListRecords = SearchRecords + UpdateTable(); + } + + private void UpdateTable() + { + ListRecords = SearchRecords? .Skip(numRecord * (currPage - 1)) .Take(numRecord) - .ToList(); + .ToList() ?? new(); isLoading = false; } diff --git a/MP.SPEC/Components/SelArticolo.razor b/MP.SPEC/Components/SelArticolo.razor new file mode 100644 index 00000000..996f21b6 --- /dev/null +++ b/MP.SPEC/Components/SelArticolo.razor @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/MP.SPEC/Components/SelArticolo.razor.cs b/MP.SPEC/Components/SelArticolo.razor.cs new file mode 100644 index 00000000..e7293b35 --- /dev/null +++ b/MP.SPEC/Components/SelArticolo.razor.cs @@ -0,0 +1,79 @@ +using Microsoft.AspNetCore.Components; +using MP.Data.DbModels; +using MP.SPEC.Data; + +namespace MP.SPEC.Components +{ + public partial class SelArticolo + { + #region Public Properties + + [Parameter] + public string SearchVal { get; set; } = ""; + + [Parameter] + public string SelAzienda { get; set; } = "*"; + + [Parameter] + public string Value { get; set; } = null!; + + [Parameter] + public EventCallback ValueChanged { get; set; } + + #endregion Public Properties + + #region Protected Properties + + [Inject] + protected MpDataService MDService { get; set; } = null!; + + #endregion Protected Properties + + #region Protected Methods + + protected override async Task OnInitializedAsync() + { + await CaricaArticoli(); + } + + protected override async Task OnParametersSetAsync() + { + if (SearchVal != _oldSearchVal || SelAzienda != _oldSelAzienda) + { + _oldSearchVal = SearchVal; + _oldSelAzienda = SelAzienda; + + await CaricaArticoli(); + } + } + + #endregion Protected Methods + + #region Private Fields + + // Variabili di appoggio per tracciare il cambio dei filtri + private string _oldSearchVal = string.Empty; + + private string _oldSelAzienda = string.Empty; + private List? ListArticoli; + private int maxNum = 100; + + #endregion Private Fields + + #region Private Methods + + private async Task CaricaArticoli() + { + ListArticoli = await MDService.ArticoliGetSearchAsync(maxNum, "*", SelAzienda, SearchVal); + } + + private async Task OnSelectionChanged(ChangeEventArgs e) + { + Value = e.Value?.ToString(); + // Notifica il componente padre della variazione + await ValueChanged.InvokeAsync(Value); + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/MP.SPEC/Components/SelectCodArt.razor.cs b/MP.SPEC/Components/SelectCodArt.razor.cs index 29b051aa..36cb41db 100644 --- a/MP.SPEC/Components/SelectCodArt.razor.cs +++ b/MP.SPEC/Components/SelectCodArt.razor.cs @@ -108,7 +108,7 @@ namespace MP.SPEC.Components if (!ListArtDisabled) { Log.Debug("START GetArticoli"); - var rawData = await MDataService.ArticoliGetSearch(10000, "*", searchVal); + var rawData = await MDataService.ArticoliGetSearch(10000, "*", "*", searchVal); // trasformo! if (rawData != null) { diff --git a/MP.SPEC/Controllers/RecipeArchiveController.cs b/MP.SPEC/Controllers/RecipeArchiveController.cs index ca7352ce..31114e5c 100644 --- a/MP.SPEC/Controllers/RecipeArchiveController.cs +++ b/MP.SPEC/Controllers/RecipeArchiveController.cs @@ -28,7 +28,7 @@ namespace MP.SPEC.Controllers public async Task GetByPODL(string idxMacc, int idxPODL) { string answ = ""; - string archPath = DService.MacchineRecipeArchive(idxMacc); + string archPath = await DService.MacchineRecipeArchiveAsync(idxMacc); var podlData = await DService.POdlGetByKey(idxPODL); if (podlData != null) { @@ -43,10 +43,10 @@ namespace MP.SPEC.Controllers } [HttpGet("GetFile")] - public string GetFile(string idxMacc, string fileName) + public async Task GetFile(string idxMacc, string fileName) { string answ = ""; - string archPath = DService.MacchineRecipeArchive(idxMacc); + string archPath = await DService.MacchineRecipeArchiveAsync(idxMacc); if (!string.IsNullOrEmpty(archPath)) { string fullPath = Path.Combine(archPath, fileName); diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs index c0b1514c..8ddbce9d 100644 --- a/MP.SPEC/Data/MpDataService.cs +++ b/MP.SPEC/Data/MpDataService.cs @@ -1,22 +1,23 @@ -using DnsClient.Protocol; -using EgwCoreLib.Utils; +using EgwCoreLib.Utils; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; -using MP.Core.Conf; using MP.Core.DTO; using MP.Core.Objects; using MP.Data; using MP.Data.Controllers; using MP.Data.DbModels; using MP.Data.MgModels; +using MP.Data.Repository.Anag; +using MP.Data.Repository.Dossier; +using MP.Data.Repository.FluxLog; +using MP.Data.Repository.Production; +using MP.Data.Repository.System; using MP.Data.Services; -using MP.SPEC.Components.ProdKit; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System.Data; using System.Diagnostics; -using ZXing; +using ZiggyCreatures.Caching.Fusion; namespace MP.SPEC.Data { @@ -24,43 +25,59 @@ namespace MP.SPEC.Data { #region Public Constructors - public MpDataService(IConfiguration configuration) - { - // fix oggetto configurazion - _configuration = configuration; - // Verifica conf trace... - traceEnabled = _configuration.GetValue("Otel:EnableTracing", false); - Log.Info($"MpDataService | INIT | Trace enabled: {traceEnabled}"); + private readonly IAnagRepository _anagRepository; + private readonly ISystemRepository _systemRepository; + private readonly IDossierRepository _dossierRepository; + private readonly IFluxLogRepository _fluxLogRepository; + private readonly IProductionRepository _productionRepository; + public MpDataService( + IConnectionMultiplexer connMPlex, + IConfiguration configuration, + IFusionCache cache, + IAnagRepository anagRepository, + ISystemRepository systemRepository, + IDossierRepository dossierRepository, + IFluxLogRepository fluxLogRepository, + IProductionRepository productionRepository) + { + // salvataggio oggetti + _configuration = configuration; + redisConn = connMPlex; + redisDb = redisConn.GetDatabase(); + +#if false // setup compoenti REDIS redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis") ?? "localhost:6379"); redisConnAdmin = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("RedisAdmin") ?? "localhost:6379"); - redisDb = redisConn.GetDatabase(); - // leggo cache lungo periodo + redisDb = redisConn.GetDatabase(); +#endif + // leggo cache lungo/cordo periodo + int.TryParse(_configuration.GetValue("ServerConf:redisShortTimeCache"), out redisShortTimeCache); int.TryParse(_configuration.GetValue("ServerConf:redisLongTimeCache"), out redisLongTimeCache); // setup MsgPipe BroadastMsgPipe = new MessagePipe(redisConn, Constants.BROADCAST_M_PIPE); Log.Info("MpDataService | Redis OK"); - // conf DB - string connStr = _configuration.GetConnectionString("MP.Data") ?? ""; - if (string.IsNullOrEmpty(connStr)) - { - Log.Error("DbController: ConnString empty!"); - } - else - { - dbController = new MpSpecController(configuration); - Log.Info("DbController OK"); - } + _cache = cache; + _anagRepository = anagRepository; + _systemRepository = systemRepository; + _dossierRepository = dossierRepository; + _fluxLogRepository = fluxLogRepository; + _productionRepository = productionRepository; + // Verifica conf trace... + traceEnabled = _configuration.GetValue("Otel:EnableTracing", false); + slowLogThresh = _configuration.GetValue("ServerConf:slowLogThresh", 1); + Log.Info($"MpDataService | INIT | Trace enabled: {traceEnabled}"); + // setup compoenti REDIS // conf x lettura dati da area REDIS di MP-IO MpIoNS = _configuration.GetValue("ServerConf:MpIoNS") ?? ""; // conf mongo... - connStr = _configuration.GetConnectionString("mdbConnString") ?? ""; - if (string.IsNullOrEmpty(connStr)) + string mongoConnStr = _configuration.GetConnectionString("mdbConnString") ?? ""; + if (string.IsNullOrEmpty(mongoConnStr)) { Log.Error("MongoController: ConnString empty!"); } @@ -72,22 +89,6 @@ namespace MP.SPEC.Data Log.Info("MpDataService | INIT completed"); } - /// - /// Helper trace messaggio log (SE abilitato) - /// - /// - private void LogTrace(string traceMsg, NLog.LogLevel? reqLevel = null) - { - if (!traceEnabled) - return; - - reqLevel ??= NLog.LogLevel.Debug; - - // Loggo! - Log.Log(reqLevel, traceMsg); - } - private bool traceEnabled = false; - #endregion Public Constructors #region Public Events @@ -101,15 +102,16 @@ namespace MP.SPEC.Data #region Public Properties - public static MpSpecController dbController { get; set; } = null!; - public static MpMongoController mongoController { get; set; } = null!; - public MessagePipe BroadastMsgPipe { get; set; } = null!; /// - /// Dizionario dei tag configurati per IOB + /// Expiry DateTime x refresh pagina parametri /// - public Dictionary> currTagConf { get; set; } = new Dictionary>(); + public DateTime DtParamExpiry + { + get => _dtParamExpiry; + set => _dtParamExpiry = value; + } #endregion Public Properties @@ -136,7 +138,7 @@ namespace MP.SPEC.Data } activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ActionGetReq Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"ActionGetReq | {source} | {activity?.Duration.TotalMilliseconds}ms"); return result; } @@ -145,18 +147,18 @@ namespace MP.SPEC.Data /// /// /// - public bool ActionSetReq(DisplayAction? act2save) + public async Task ActionSetReqAsync(DisplayAction? act2save) { - using var activity = ActivitySource.StartActivity("ActionSetReq"); + using var activity = ActivitySource.StartActivity("ActionSetReqAsync"); string source = "REDIS"; bool fatto = false; // cerco in redis... string rawData = JsonConvert.SerializeObject(act2save); // invio broadcast + salvo in redis - BroadastMsgPipe.saveAndSendMessage(Utils.redisActionReq, rawData); + await BroadastMsgPipe.SaveAndSendMessageAsync(Utils.redisActionReq, rawData); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ActionSetReq {source} send to broadcast + Write cache: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"ActionSetReqAsync {source} send to broadcast + Write cache: {activity?.Duration.TotalMilliseconds}ms"); return fatto; } @@ -164,15 +166,15 @@ namespace MP.SPEC.Data /// Stacca un nuovo counter x il tipo richiesto /// /// - public AnagCountersModel AnagCountersGetNext(string cntType) + public async Task AnagCountersGetNextAsync(string cntType) { - using var activity = ActivitySource.StartActivity("AnagCountersGetNext"); + using var activity = ActivitySource.StartActivity("AnagCountersGetNextAsync"); AnagCountersModel result = new AnagCountersModel(); string source = "DB"; - result = dbController.AnagCountersGetNext(cntType); + result = await _anagRepository.AnagCountersGetNextAsync(cntType); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"AnagCountersGetNext | {source} | {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"AnagCountersGetNextAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); return result; } @@ -180,87 +182,35 @@ namespace MP.SPEC.Data /// Elenco EVENTI validi x ogni macchina secondo conf standard macchina /// /// - public List AnagEventiGeneral() + public async Task> AnagEventiGeneralAsync() { - using var activity = ActivitySource.StartActivity("AnagEventiGeneral"); - string source = "DB"; - List? result = new List(); - // cerco in redisConn... - string currKey = $"{Utils.redisEventList}:VSEB:GENERAL"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.AnagEventiGeneral(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"AnagEventiGeneral | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco EVENTI validi x macchina - /// - /// - public List AnagEventiGetByMacch(string IdxMacch) - { - using var activity = ActivitySource.StartActivity("AnagEventiGetByMacch"); - string source = "DB"; - List? result = new List(); - // cerco in redisConn... - string currKey = $"{Utils.redisEventList}:VSEB:{IdxMacch}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.AnagEventiGetByMacc(IdxMacch); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"AnagEventiGetByMacch | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "AnagEventiGeneralAsync", + cacheKey: $"{Utils.redisEventList}:VSEB:GENERAL", + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + { + return await _anagRepository.AnagEventiGeneralAsync() ?? new List(); + }, + tagList: [Utils.redisEventList] + ); } /// /// Delete record AnagraficaGruppi /// /// - public bool AnagGruppiDelete(AnagGruppiModel updRec) + public async Task AnagGruppiDeleteAsync(AnagGruppiModel updRec) { - using var activity = ActivitySource.StartActivity("AnagGruppiDelete"); + using var activity = ActivitySource.StartActivity("AnagGruppiDeleteAsync"); bool result = false; - result = dbController.AnagGruppiDelete(updRec); + string source = "DB"; + result = await _anagRepository.AnagGruppiDeleteAsync(updRec); // elimino cache redis... - string pattern = $"{Utils.redisAnagGruppi}:*"; - bool answ = ExecFlushRedisPattern(pattern); - activity?.SetTag("data.source", "DB+REDIS"); + await FlushFusionCacheAsync(Utils.redisAnagGruppi); + activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"AnagGruppiDelete | CodGruppo {updRec.CodGruppo} | {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"AnagGruppiDeleteAsync | CodGruppo {updRec.CodGruppo} | {source}{activity?.Duration.TotalMilliseconds}ms"); return result; } @@ -269,148 +219,81 @@ namespace MP.SPEC.Data /// /// /// - public bool AnagGruppiUpsert(AnagGruppiModel UpdRec) + public async Task AnagGruppiUpsertAsync(AnagGruppiModel UpdRec) { - using var activity = ActivitySource.StartActivity("AnagGruppiUpsert"); + using var activity = ActivitySource.StartActivity("AnagGruppiUpsertAsync"); bool result = false; - result = dbController.AnagGruppiUpsert(UpdRec); + string source = "DB"; + result = await _anagRepository.AnagGruppiUpsertAsync(UpdRec); // elimino cache redis... - string pattern = $"{Utils.redisAnagGruppi}:*"; - bool answ = ExecFlushRedisPattern(pattern); - activity?.SetTag("data.source", "DB+REDIS"); + await FlushFusionCacheAsync(Utils.redisAnagGruppi); + activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"AnagGruppiUpsert | CodGruppo {UpdRec.CodGruppo} | {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"AnagGruppiUpsertAsync | CodGruppo {UpdRec.CodGruppo} | {source} | {activity?.Duration.TotalMilliseconds}ms"); return result; } + public async Task> AnagStatiCommAsync() + { + return await GetOrFetchAsync( + operationName: "AnagStatiCommAsync", + cacheKey: Utils.redisStatoCom, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + await _anagRepository.AnagStatiCommAsync() ?? new List(), + tagList: [Utils.redisStatoCom] + ); + } + /// - /// Elenco Gruppi + /// Restituisce elenco tipi articolo livello anagrafica /// /// - public async Task> AnagKeyValGetAll() + public async Task> AnagTipoArtLvAsync() { - // nuovo oggetto span activity - using var activity = ActivitySource.StartActivity("AnagKeyValGetAll"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisAKVKey); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.AnagKeyValGetAll()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"AnagKeyValGetAll Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - public async Task> AnagStatiComm() - { - using var activity = ActivitySource.StartActivity("AnagStatiComm"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisStatoCom); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.AnagStatiComm()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Utils.redisStatoCom, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"AnagStatiComm Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - public async Task> AnagTipoArtLV() - { - using var activity = ActivitySource.StartActivity("AnagStatiComm"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisTipoArt); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.AnagTipoArtLV()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Utils.redisTipoArt, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"AnagTipoArtLV Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "AnagTipoArtLvAsync", + cacheKey: Utils.redisTipoArt, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _anagRepository.AnagTipoArtLvAsync() ?? new List(), + tagList: [Utils.redisTipoArt] + ); } /// - /// Elenco Codice articolo con dati dossier gestiti + /// Elenco codice articoli che abbiano dati Dossier /// /// - public async Task> ArticleWithDossier() + public async Task> ArticleWithDossierAsync() { - using var activity = ActivitySource.StartActivity("ArticleWithDossier"); - List? result = new List(); - string source = "DB"; - string currKey = Utils.redisArtByDossier; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ArticleWithDossier()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ArticleWithDossier | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "ArticleWithDossierAsync", + cacheKey: Utils.redisArtByDossier, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _dossierRepository.ArticleWithDossierAsync() ?? new List(), + tagList: [Utils.redisArtByDossier] + ); + } + + /// + /// Conteggio articoli data ricerca + /// + /// + /// + /// + /// + public async Task ArticoliCountSearchAsync(string tipo = "*", string azienda = "*", string searchVal = "") + { + string sKey = string.IsNullOrWhiteSpace(tipo) ? "ALL" : tipo.Trim(); + string redisKey = $"{Utils.redisArtList}:{azienda}:{sKey}:{searchVal}:Count"; + return await GetOrFetchAsync( + operationName: "ArticoliCountSearchAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + await _anagRepository.ArticoliCountSearchAsync(tipo, azienda, searchVal), + tagList: [Utils.redisArtList, $"{Utils.redisArtList}:CountSearch"] + ); } /// @@ -420,13 +303,13 @@ namespace MP.SPEC.Data /// public async Task ArticoliDeleteRecord(AnagArticoliModel currRec) { - using var activity = ActivitySource.StartActivity("ArticoliDeleteRecord"); - string source = "DB+REDIS"; - bool fatto = await dbController.ArticoliDeleteRecord(currRec); - await resetCacheArticoli(); + using var activity = ActivitySource.StartActivity("ArticoliDeleteRecordAsync"); + string source = "DB"; + bool fatto = await _anagRepository.ArticoliDeleteRecordAsync(currRec); + await FlushFusionCacheArticoli(); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ArticoliDeleteRecord | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"ArticoliDeleteRecordAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); return fatto; } @@ -436,36 +319,18 @@ namespace MP.SPEC.Data /// /// /// - public List ArticoliGetByTipo(string tipo, string azienda = "*") + public async Task> ArticoliGetByTipoAsync(string tipo, string azienda = "*") { - using var activity = ActivitySource.StartActivity("ArticoliGetByTipo"); - List? result = new List(); - string source = "DB"; - string sKey = string.IsNullOrEmpty(tipo) ? "ALL" : tipo; - string currKey = $"{Utils.redisArtList}:{azienda}:Tipo:{sKey}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.ArticoliGetByTipo(tipo, azienda); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ArticoliGetByTipo | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + string sKey = string.IsNullOrWhiteSpace(tipo) ? "ALL" : tipo.Trim(); + string redisKey = $"{Utils.redisArtList}:{azienda}:{sKey}"; + return await GetOrFetchAsync( + operationName: "ArticoliGetByTipoAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + await _anagRepository.ArticoliGetByTipoAsync(tipo, azienda) ?? new List(), + tagList: [Utils.redisArtList, $"{Utils.redisArtList}:Tipo"] + ); } /// @@ -474,36 +339,36 @@ namespace MP.SPEC.Data /// /// /// - public async Task> ArticoliGetSearch(int numRecord, string azienda, string searchVal) + public async Task> ArticoliGetSearchAsync(int numRecord, string tipoArt, string azienda, string searchVal) { - using var activity = ActivitySource.StartActivity("ArticoliGetSearch"); - List? result = new List(); - string source = "DB"; - string sKey = string.IsNullOrEmpty(searchVal) ? "***" : searchVal; - string currKey = $"{Utils.redisArtList}:{azienda}:{sKey}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ArticoliGetSearch | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + string sKey = string.IsNullOrWhiteSpace(searchVal) ? "***" : searchVal.Trim(); + string redisKey = $"{Utils.redisArtList}:{tipoArt}:{azienda}:{sKey}:{numRecord}"; + + return await GetOrFetchAsync( + operationName: "ArticoliGetSearchAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + await _anagRepository.ArticoliGetSearchAsync(numRecord, tipoArt, azienda, searchVal) ?? new List(), + tagList: [Utils.redisArtList, $"{Utils.redisArtList}:Search"] + ); + } + + /// + /// Elenco articoli contenuti in Kit (come child), non eliminabli + /// + /// + public async Task> ArticoliInKitAsync() + { + string redisKey = $"{Utils.redisArtList}:InKit"; + return await GetOrFetchAsync( + operationName: "ArticoliInKitAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + await _anagRepository.ArticoliInKitAsync() ?? new List(), + tagList: [Utils.redisArtList, $"{Utils.redisArtList}:InKit"] + ); } /// @@ -514,12 +379,12 @@ namespace MP.SPEC.Data public async Task ArticoliUpdateRecord(AnagArticoliModel currRec) { using var activity = ActivitySource.StartActivity("ArticoliUpdateRecord"); - string source = "DB+REDIS"; - bool fatto = await dbController.ArticoliUpdateRecord(currRec); - await resetCacheArticoli(); + string source = "DB"; + bool fatto = await _anagRepository.ArticoliUpdateRecord(currRec); + await FlushFusionCacheArticoli(); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ArticoliUpdateRecord | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"ArticoliUpdateRecord | {source} | {activity?.Duration.TotalMilliseconds}ms"); return fatto; } @@ -532,67 +397,47 @@ namespace MP.SPEC.Data public bool ArticoloDelEnabled(object CodArt) { using var activity = ActivitySource.StartActivity("ArticoloDelEnabled"); - string source = "DB"; - bool answ = false; string codArticolo = $"{CodArt}"; - int cacheCheckArtUsato = 1; - int.TryParse(_configuration.GetValue("ServerConf:cacheCheckArtUsato"), out cacheCheckArtUsato); - TimeSpan TTLCache = getRandTOut(cacheCheckArtUsato); - // cerco in cache redis... - string redKeyArtUsed = $"{Utils.redKeyArtUsed}:{codArticolo}"; - string redKeyTabCheckArt = Utils.redKeyTabCheckArt; - var rawData = redisDb.StringGet(redKeyArtUsed); - if (!string.IsNullOrEmpty(rawData)) + + int numUsed = _listCodArtUsed.Count; + int numUnused = _listCodArtNotUsed.Count; + bool usato = true; + string source = "MEMORY"; + // 1. Controllo immediato sulla cache locale (HashSet) x eventuale refresh + if (DateTime.Now >= _artCacheExpiry || (numUsed + numUnused) <= 0) { - bool.TryParse(rawData, out answ); + source = "DB/REDIS"; + // Fallback sincrono minimo per non rompere il componente Blazor + // Nota: Questo è un workaround per la firma sincrona. + var task = EnsureArtCacheLoadedAsync(false); + task.Wait(); + + // rileggo + numUsed = _listCodArtUsed.Count; + numUnused = _listCodArtNotUsed.Count; + } + + // verifico quale sia l'elenco + if (numUsed > 0) + { + usato = _listCodArtUsed.Contains(codArticolo); } else { - // controllo non sia stato mai prodotto sennò non posso cancellare... - try - { - // cerco in cache se ci sia la tabella con gli articoli impiegati... - var rawTable = redisDb.StringGet(redKeyTabCheckArt); - List? artList = new List(); - if (!string.IsNullOrEmpty(rawTable)) - { - artList = JsonConvert.DeserializeObject>($"{rawTable}"); - } - // rileggo... - if (artList == null || artList.Count == 0) - { - artList = new List(); - var tabArticoli = dbController.ArticoliGetUsed(); - var codList = tabArticoli.Select(x => x.CodArticolo); - foreach (string cod in codList) - { - artList.Add(cod); - } - // SE fosse vuoto aggiungo comunque il cado "ND"... - if (artList.Count == 0) - { - artList.Add("ND"); - } - // salvo - rawTable = JsonConvert.SerializeObject(artList); - redisDb.StringSet(redKeyTabCheckArt, rawTable, TTLCache); - } - // cerco nella tabella: se ci fosse --> disabilitato delete - bool usato = false; - if (artList != null && artList.Count > 0) - { - usato = artList.Contains(codArticolo); - } - answ = !usato; - redisDb.StringSet(redKeyArtUsed, $"{answ}", TTLCache); - } - catch - { } + usato = !_listCodArtNotUsed.Contains(codArticolo); + } + // verifico infine anche che NON sia nell'elenco degli articoli in KIT + if (!usato) + { + usato = _listCodArtInKit.Contains(CodArt); } activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ArticoloDelEnabled | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"ArticoloDelEnabled | Cod: {codArticolo} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + } + return !usato; } public string CalcRecipe(RecipeModel currRecipe) @@ -603,120 +448,33 @@ namespace MP.SPEC.Data return result; } - /// - /// Recupero tab config in modalità Sincrona - /// - /// - public List ConfigGetAll() - { - using var activity = ActivitySource.StartActivity("ConfigGetAll"); - string source = "REDIS"; - List? result = new List(); - // cerco in redis... - RedisValue rawData = redisDb.StringGet(Utils.redisConfKey); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - } - else - { - source = "DB"; - result = dbController.ConfigGetAll(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ConfigGetAll Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - /// /// Recupero tab config in modalità Asincrona /// /// public async Task> ConfigGetAllAsync() { - using var activity = ActivitySource.StartActivity("ConfigGetAllAsync"); - string source = "REDIS"; - List? result = new List(); - // cerco in redis... - RedisValue rawData = await redisDb.StringGetAsync(Utils.redisConfKey); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ConfigGetAll()); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ConfigGetAllAsync Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "ConfigGetAllAsync", + cacheKey: Utils.redisConfAll, + expiration: GetRandTOut(redisLongTimeCache * 2), + fetchFunc: async () => await _systemRepository.ConfigGetAllAsync() ?? new List(), + tagList: [Utils.redisConfAll] + ); } /// /// Reset dati cache config /// /// - public async Task ConfigResetCache() + public async Task ConfigResetCacheAsync() { - using var activity = ActivitySource.StartActivity("ConfigResetCache"); + using var activity = ActivitySource.StartActivity("ConfigResetCacheAsync"); string source = "REDIS"; - await redisDb.StringSetAsync(Utils.redisConfKey, ""); + await FlushFusionCacheConfig(); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ConfigResetCache Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - } - - /// - /// Restituisce valore della stringa (SE disponibile) - /// - /// - /// - public string ConfigTryGet(string keyName) - { - string answ = ""; - using var activity = ActivitySource.StartActivity("ConfigTryGet"); - string source = "DB+REDIS"; - // preselezione valori - if (configData == null || configData.Count == 0) - { - configData = ConfigGetAll(); - } - var currRec = configData.FirstOrDefault(x => x.Chiave == keyName); - - // se non trovato provo a ricaricare.. - if (currRec == null) - { - configData = ConfigGetAll(); - currRec = configData.FirstOrDefault(x => x.Chiave == keyName); - } - // verifico se ci sia il dato... - if (currRec != null) - { - answ = currRec.Valore; - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ConfigTryGet Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; + LogTrace($"ConfigResetCacheAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); } /// @@ -726,45 +484,35 @@ namespace MP.SPEC.Data /// public async Task ConfigTryGetAsync(string keyName) { - string answ = ""; using var activity = ActivitySource.StartActivity("ConfigTryGetAsync"); - string source = "DB+REDIS"; - // preselezione valori - if (configData == null || configData.Count == 0) - { - configData = await ConfigGetAllAsync(); - } - var currRec = configData.FirstOrDefault(x => x.Chiave == keyName); + string source = "MEMORY"; + + await EnsureConfigLoadedAsync(); + + _configData.TryGetValue(keyName, out var value); - // se non trovato provo a ricaricare.. - if (currRec != null) - { - configData = await ConfigGetAllAsync(); - currRec = configData.FirstOrDefault(x => x.Chiave == keyName); - } - // verifico se ci sia il dato... - if (currRec != null) - { - answ = currRec.Valore; - } activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ConfigTryGetAsync Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"ConfigTryGetAsync | {keyName} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + } + return value ?? ""; } /// /// Update chiave config /// /// - public bool ConfigUpdate(ConfigModel updRec) + public async Task ConfigUpdateAsync(ConfigModel updRec) { - using var activity = ActivitySource.StartActivity("ConfigUpdate"); + using var activity = ActivitySource.StartActivity("ConfigUpdateAsync"); string source = "DB"; - var updRes = dbController.ConfigUpdate(updRec); + var updRes = await _systemRepository.ConfigUpdateAsync(updRec); + await FlushFusionCacheConfig(); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ConfigUpdate Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"ConfigUpdateAsync Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); return updRes; } @@ -772,9 +520,9 @@ namespace MP.SPEC.Data /// Restituisce le statistiche di DB maintenance eseguite /// /// - public Dictionary DbDedupStats() + public async Task> DbDedupStatsAsync() { - using var activity = ActivitySource.StartActivity("DbDedupStats"); + using var activity = ActivitySource.StartActivity("DbDedupStatsAsync"); string source = "REDIS"; Dictionary actStats = new Dictionary(); string currKey = $"{Utils.redisStatsDbMaint}"; @@ -790,7 +538,7 @@ namespace MP.SPEC.Data } activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"DbDedupStats Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"DbDedupStatsAsync Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); return actStats; } @@ -800,9 +548,8 @@ namespace MP.SPEC.Data public void Dispose() { // Clear database controller - dbController.Dispose(); mongoController.Dispose(); - redisConn.Dispose(); + //redisConn.Dispose(); } /// @@ -810,17 +557,16 @@ namespace MP.SPEC.Data /// /// record dossier da eliminare /// - public async Task DossiersDeleteRecord(DossierModel selRecord) + public async Task DossiersDeleteRecordAsync(DossierModel selRecord) { - using var activity = ActivitySource.StartActivity("DossiersDeleteRecord"); + using var activity = ActivitySource.StartActivity("DossiersDeleteRecordAsync"); bool result = false; - result = await dbController.DossiersDeleteRecord(selRecord); - // elimino cache redis... - RedisValue pattern = new RedisValue($"{Utils.redisDossByMac}:*"); - bool answ = await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", "DB+REDIS"); + result = await _dossierRepository.DossiersDeleteRecordAsync(selRecord); + // elimino cache... + await FlushFusionCacheAsync(Utils.redisDossByMac); + activity?.SetTag("data.source", "DB"); activity?.Stop(); - LogTrace($"DossiersDeleteRecord | IdxMacchina {selRecord.IdxMacchina} | DtRif {selRecord.DtRif} | IdxODL {selRecord.IdxODL} | {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"DossiersDeleteRecordAsync | IdxMacchina {selRecord.IdxMacchina} | DtRif {selRecord.DtRif} | IdxODL {selRecord.IdxODL} | {activity?.Duration.TotalMilliseconds}ms"); return result; } @@ -833,35 +579,16 @@ namespace MP.SPEC.Data /// Data Massima per estrazione records /// Num Max records da recuperare /// - public async Task> DossiersGetLastFilt(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec) + public async Task> DossiersGetLastFiltAsync(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd, int MaxRec) { - using var activity = ActivitySource.StartActivity("DossiersGetLastFiltAsync"); - List? result = new List(); - string source = "DB"; string currKey = $"{Utils.redisDossByMac}:{IdxMacchina}:{CodArticolo}:{DtStart:yyyyMMddHHmm}:{DtEnd:yyyyMMddHHmm}:{MaxRec}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await dbController.DossiersGetLastFiltAsync(IdxMacchina, CodArticolo, DtStart, DtEnd, MaxRec); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"DossiersGetLastFiltAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "DossiersGetLastFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache * 5), + fetchFunc: async () => await _dossierRepository.DossiersGetLastFiltAsync(IdxMacchina, CodArticolo, DtStart, DtEnd, MaxRec) ?? new List(), + tagList: [Utils.redisDossByMac] + ); } /// @@ -871,13 +598,14 @@ namespace MP.SPEC.Data /// public async Task DossiersInsert(DossierModel currDoss) { - using var activity = ActivitySource.StartActivity("DossiersInsert"); + using var activity = ActivitySource.StartActivity("DossiersInsertAsync"); string source = "DB"; // aggiorno record sul DB - bool answ = await dbController.DossiersInsert(currDoss); + bool answ = await _dossierRepository.DossiersInsertAsync(currDoss); + answ = await FlushFusionCacheAsync(Utils.redisDossByMac); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"DossiersInsert | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"DossiersInsertAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } @@ -890,18 +618,17 @@ namespace MP.SPEC.Data /// public async Task DossiersTakeParamsSnapshotLast(string IdxMacchina, DateTime dtMin, DateTime dtMax) { - using var activity = ActivitySource.StartActivity("DossiersUpdateValore"); - string source = "DB+REDIS"; + using var activity = ActivitySource.StartActivity("DossiersUpdateValoreAsync"); + string source = "DB"; bool answ = false; Log.Info($"Richiesta snapshot per idxMaccSel {IdxMacchina} | periodo {dtMin} --> {dtMax}"); // chiamo stored x salvare parametri - dbController.DossiersTakeParamsSnapshotLast(IdxMacchina, dtMin, dtMax); - // elimino cache redis... - RedisValue pattern = new RedisValue($"{Utils.redisDossByMac}:*"); - answ = await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", "DB+REDIS"); + await _dossierRepository.DossiersTakeParamsSnapshotLastAsync(IdxMacchina, dtMin, dtMax); + // elimino cache... + answ = await FlushFusionCacheAsync(Utils.redisDossByMac); + activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"DossiersTakeParamsSnapshotLast | Svuotata cache dossier | {pattern} | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"DossiersTakeParamsSnapshotLastAsync | Svuotata cache dossier | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } @@ -910,124 +637,131 @@ namespace MP.SPEC.Data /// /// /// - public async Task DossiersUpdateValore(DossierModel currDoss) + public async Task DossiersUpdateValoreAsync(DossierModel currDoss) { - using var activity = ActivitySource.StartActivity("DossiersUpdateValore"); + using var activity = ActivitySource.StartActivity("DossiersUpdateValoreAsync"); string source = "DB"; // aggiorno record sul DB - bool answ = await dbController.DossiersUpdateValore(currDoss); + bool answ = await _dossierRepository.DossiersUpdateValoreAsync(currDoss); + answ = await FlushFusionCacheAsync(Utils.redisDossByMac); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"DossiersUpdateValore | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"DossiersUpdateValoreAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } /// - /// Restitusice elenco aziende + /// Restituisce elenco aziende /// /// - public List ElencoAziende() + public async Task> ElencoAziendeAsync() { - using var activity = ActivitySource.StartActivity("ElencoAziende"); - string source = "DB"; - var listAz = dbController.AnagGruppiAziende(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ElencoAziende | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return listAz; + return await GetOrFetchAsync( + operationName: "ElencoAziendeAsync", + cacheKey: $"{Utils.redisAnagGruppi}:Aziende", + expiration: GetRandTOut(redisLongTimeCache * 2), + fetchFunc: async () => + await _anagRepository.AnagGruppiAziendeAsync() ?? new List(), + tagList: [Utils.redisAnagGruppi, $"{Utils.redisAnagGruppi}:Aziende"] + ); } /// - /// Restitusice elenco Fasi + /// Restituisce elenco Fasi /// /// - public List ElencoGruppiFase() + public async Task> ElencoGruppiFaseAsync() { - using var activity = ActivitySource.StartActivity("ElencoGruppiFase"); - List result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisAnagGruppi}:FASE"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - var rawResult = JsonConvert.DeserializeObject>($"{rawData}"); - if (rawResult != null) - { - result = rawResult; - } - source = "REDIS"; - } - else - { - result = dbController.AnagGruppiFase(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ElencoGruppiFase | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "ElencoGruppiFaseAsync", + cacheKey: $"{Utils.redisAnagGruppi}:FASE", + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _anagRepository.AnagGruppiFaseAsync() ?? new List(), + tagList: [Utils.redisAnagGruppi] + ); } /// - /// Elenco link validi + /// Elenco link validi per il menu /// /// - public List ElencoLink() + public async Task> ElencoLinkAsync() { - using var activity = ActivitySource.StartActivity("ElencoLink"); - string source = "DB"; - var linkList = dbController.ElencoLink(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ElencoLink | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return linkList; + return await GetOrFetchAsync( + operationName: "ElencoLinkAsync", + cacheKey: Utils.redisLinkMenu, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _systemRepository.ElencoLinkAsync() ?? new List(), + tagList: [Utils.redisLinkMenu] + ); } /// /// Restitusice elenco Reparti /// /// - public List ElencoRepartiDTO() + public async Task> ElencoRepartiDtoAsync() { - using var activity = ActivitySource.StartActivity("ElencoRepartiDTO"); - List result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisAnagGruppi}:REPARTO"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) + return await GetOrFetchAsync( + operationName: "ElencoRepartiDtoAsync", + cacheKey: $"{Utils.redisAnagGruppi}:REPARTO", + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _anagRepository.AnagGruppiRepartoDtoAsync() ?? new(), + tagList: [Utils.redisAnagGruppi] + ); + } + /// + /// Restitusice elenco Reparti + /// + /// + public async Task> GruppiRepartoDtoByOperAsync(int matrOpr) + { + return await GetOrFetchAsync( + operationName: "ElencoRepartiDtoAsync", + cacheKey: $"{Utils.redisAnagGruppiOpr}:{matrOpr}", + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _anagRepository.GruppiRepartoDtoByOperAsync(matrOpr) ?? new(), + tagList: [Utils.redisAnagGruppiOpr] + ); + } + + /// + /// Caricamento asincrono della cache degli articoli (Used/Unused) + /// + public async Task EnsureArtCacheLoadedAsync(bool forceReload) + { + if (!forceReload && (DateTime.Now < _artCacheExpiry && (_listCodArtUsed.Count > 0 || _listCodArtNotUsed.Count > 0))) + return; + + try { - var rawResult = JsonConvert.DeserializeObject>($"{rawData}"); - if (rawResult != null) + // verifico quale sia il set + piccolo + int totalCount = await _anagRepository.ArticoliCountAsync(); + int usedCount = await _anagRepository.ArticoliCountUsedAsync(); + + if (usedCount <= (totalCount - usedCount)) { - result = rawResult; + var usedList = await _anagRepository.ArticoliGetUsedAsync(); + _listCodArtUsed = new HashSet(usedList.Select(x => x.CodArticolo)); + _listCodArtNotUsed.Clear(); } - source = "REDIS"; + else + { + var unusedList = await _anagRepository.ArticoliGetUnusedAsync(); + _listCodArtNotUsed = new HashSet(unusedList.Select(x => x.CodArticolo)); + _listCodArtUsed.Clear(); + } + // calcolo anche elenco articoli impiegati in istanzanKIT + var listInKit = await _anagRepository.ArticoliInKitAsync(); + _listCodArtInKit = new HashSet(listInKit.Select(x => x.CodArticolo)); + + _artCacheExpiry = DateTime.Now.AddMinutes(15); // TTL ragionevole per la cache locale } - else + catch (Exception ex) { - result = dbController.AnagGruppiRepartoDTO(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); + Log.Error($"Errore nel caricamento cache articoli: {ex.Message}"); + _artCacheExpiry = DateTime.Now.AddSeconds(1); // Retry breve in caso di errore } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ElencoRepartiDTO | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; } /// @@ -1037,70 +771,1365 @@ namespace MP.SPEC.Data /// public async Task EvListInsert(EventListModel newRec) { - using var activity = ActivitySource.StartActivity("EvListInsert"); + using var activity = ActivitySource.StartActivity("EvListInsertAsync"); string source = "DB"; - var result = await dbController.EvListInsert(newRec); + var result = await _systemRepository.EvListInsertAsync(newRec); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"EvListInsert | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"EvListInsertAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); return result; } /// - /// Esegue flush memoria redis dato keyVal + /// Flush cache relativa a MP-IO x dati ODL /// - /// /// - public bool ExecFlushRedisPattern(string pat2Flush) + public async Task FlushRedisCacheMpIoOdl() { - using var activity = ActivitySource.StartActivity("ExecFlushRedisPattern"); + using var activity = ActivitySource.StartActivity("FlushRedisCacheMpIoOdl"); string source = "REDIS"; - bool answ = false; - var masterEndpoint = redisConn.GetEndPoints() - .Where(ep => redisConn.GetServer(ep).IsConnected && !redisConn.GetServer(ep).IsReplica) - .FirstOrDefault(); + // svuoto dalla cache REDIS del server IO... + bool ok01 = await ResetIoCache("CurrODL"); + bool ok02 = await ResetIoCache("CurrOdlRow"); + bool ok03 = await ResetIoCache("CurrStatoMacc"); + bool ok04 = await ResetIoCache("DtMac"); + activity?.SetTag("data.source", "REDIS"); + activity?.Stop(); + LogTrace($"FlushRedisCacheMpIoOdl | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return ok01 && ok02 && ok03 && ok04; + } - // sepattern è "*" elimino intero DB... - if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null)) - { - redisConn.GetServer(masterEndpoint).FlushDatabase(database: redisDb.Database); - } - else - { - var server = redisConn.GetServer(masterEndpoint); - var keys = server.Keys(database: redisDb.Database, pattern: pat2Flush, pageSize: 1000); - var batch = new List(); - foreach (var key in keys) - { - batch.Add(key); - - // Flush in batches of 1000 - if (batch.Count >= 1000) - { - foreach (var item in batch) - redisDb.KeyDelete(item); - - batch.Clear(); - } - } - - // Flush remaining keys - foreach (var item in batch) - redisDb.KeyDelete(item); - } - answ = true; + /// + /// Funzione di Data Reduction x FluxLog + /// + /// Macchina + /// Elenco FL da processare + /// Periodo + /// modalità sel valore + /// intervallo di analisi + /// max num per intervallo + /// + public async Task FluxLogDataRedux(string idxMaccSel, List fluxList, DtUtils.Periodo currPeriodo, Enums.ValSelection valMode, Enums.DataInterval intReq, int maxItem) + { + using var activity = ActivitySource.StartActivity("FluxLogDataReduxAsync"); + string source = "DB"; + List procStats = await _fluxLogRepository.FluxLogDataReduxAsync(idxMaccSel, fluxList, currPeriodo, valMode, intReq, maxItem); + // effettuo merge statistiche... + await ProcDedupStatMergeAsync(procStats); + // svuoto cache + await FlushFusionCacheFluxLog(); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ExecFlushRedisPattern | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"FluxLogDataReduxAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + } + + /// + /// Helper conversione valore raw in List di FluxLogDTO + /// + /// + /// + public List FluxLogDtoConvert(string Valore) + { + List answ = new List(); + DossierFluxLogDTO? result = JsonConvert.DeserializeObject(Valore); + if (result != null) + { + if (result.ODL != null) + { + answ = result + .ODL + .OrderBy(x => x.CodFlux) + .ToList(); + // inizializzo SE necessario + foreach (var item in answ) + { + item.ValoreEdit = String.IsNullOrEmpty(item.ValoreEdit) ? item.Valore : item.ValoreEdit; + } + } + } return answ; } + /// + /// Elenco FluxLog in modalità filtro + /// + /// Data massima x eventi + /// Data minima x eventi + /// * = tutte, altrimenti solo x una data idxMaccSel + /// *=tutti, altrimenti solo selezionato + /// numero massimo record da restituire + /// durata cache in secondi + /// + public async Task> FluxLogGetLastFiltAsync(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec, double redisCacheSec) + { + string currKey = $"{Utils.redisFluxLogFilt}:{IdxMacchina}:{CodFlux}:{MaxRec}:{DtMax:yyyyMMddHHmm}:{DtMin:yyyyMMddHHmm}"; + + return await GetOrFetchAsync( + operationName: "FluxLogGetLastFiltAsync", + cacheKey: currKey, + expiration: TimeSpan.FromSeconds(redisCacheSec), + fetchFunc: async () => await _fluxLogRepository.FluxLogGetLastFiltAsync(DtMax, DtMin, IdxMacchina, CodFlux, MaxRec) ?? new List(), + tagList: [Utils.redisFluxLogFilt] + ); + } + + /// + /// Elenco FluxLog in modalità Pareto + /// + /// + public async Task> FluxLogParetoAsync(string idxMacchina, DateTime dtFrom, DateTime dtTo) + { + string redKey = $"{Utils.redisParetoFLKey}:{idxMacchina}:{dtFrom:yyyyMMdd}:{dtTo:yyyyMMdd}"; + return await GetOrFetchAsync( + operationName: "FluxLogParetoAsync", + cacheKey: redKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _fluxLogRepository.FluxLogParetoAsync(idxMacchina, dtFrom, dtTo) ?? new List(), + tagList: [Utils.redisParetoFLKey] + ); + } + + /// + /// Stored manutenzione del DB + /// + /// Esegue realmente il task + /// Aggiornamento statistiche + /// Salvataggio + /// def: 1000 + /// def: 10 + /// def: 50 + /// + public async Task ForceDbMaintAsync(bool doExec = true, bool doUpdStat = true, bool doSave = true, int minPgCnt = 1000, int minAvgFrag = 10, int maxAvgFragReb = 50) + { + using var activity = ActivitySource.StartActivity("ForceDbMaintAsync"); + string source = "DB"; + await _systemRepository.ForceDbMaintAsync(doExec, doUpdStat, doSave, minPgCnt, minAvgFrag, maxAvgFragReb); + // svuoto cache + await FlushFusionCacheFluxLog(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"ForceDbMaintAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + // registro statistiche esecuzione + await RecDbMaintStatAsync(activity?.Duration ?? TimeSpan.FromSeconds(1)); + } + + /// + /// Cancellazione FusionCache (totale) - wrapper public + /// + /// + public Task ForceFlushFusionCacheAsync() + { + return FlushFusionCacheAsync(); + } + + /// + /// Cancellazione RedisCache forzata + /// + /// + public async Task ForceFlushRedisCache() + { + using var activity = ActivitySource.StartActivity("ForceFlushRedisCache"); + string source = "FUSION"; + // valutare se tenere + RedisValue pattern = Utils.RedValue("*"); + await ExecFlushRedisPatternAsync(pattern); + // pulisco fusionlog cache... + bool answ = await FlushFusionCacheAsync(); + activity?.Stop(); + LogTrace($"FlushCache | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return answ; + } + + /// + /// Eliminazione di un record macchina dal gruppo + /// + /// + /// + public async Task Grp2MaccDeleteAsync(Gruppi2MaccModel rec2del) + { + using var activity = ActivitySource.StartActivity("Grp2MaccDeleteAsync"); + bool result = false; + result = await _productionRepository.Grp2MaccDeleteAsync(rec2del); + // elimino cache redis... + await FlushFusionCacheMacGrp(); + activity?.SetTag("data.source", "DB"); + activity?.Stop(); + LogTrace($"Grp2MaccDeleteAsync | CodGruppo {rec2del.CodGruppo} | IdxMacc {rec2del.IdxMacchina} | {activity?.Duration.TotalMilliseconds}ms"); + return result; + } + + /// + /// Insert di un record macchina + /// + /// + /// + public async Task Grp2MaccInsertAsync(Gruppi2MaccModel upsRec) + { + using var activity = ActivitySource.StartActivity("Grp2MaccInsertAsync"); + bool result = false; + result = await _productionRepository.Grp2MaccInsertAsync(upsRec); + // elimino cache redis... + await FlushFusionCacheMacGrp(); + activity?.SetTag("data.source", "DB"); + activity?.Stop(); + LogTrace($"Grp2MaccInsertAsync | CodGruppo {upsRec.CodGruppo} | IdxMacc {upsRec.IdxMacchina} | {activity?.Duration.TotalMilliseconds}ms"); + return result; + } + + /// + /// Eliminazione di un record operatore dal gruppo + /// + /// + /// + public async Task Grp2OperDeleteAsync(Gruppi2OperModel rec2del) + { + using var activity = ActivitySource.StartActivity("Grp2OperDeleteAsync"); + bool result = false; + result = await _productionRepository.Grp2OperDeleteAsync(rec2del); + // elimino cache redis... + await FlushFusionCacheOprGrp(); + activity?.SetTag("data.source", "DB"); + activity?.Stop(); + LogTrace($"Grp2OperDeleteAsync | CodGruppo {rec2del.CodGruppo} | MatrOpr {rec2del.MatrOpr} | {activity?.Duration.TotalMilliseconds}ms"); + return result; + } + + /// + /// Insert di un record operatore + /// + /// + /// + public async Task Grp2OperInsertAsync(Gruppi2OperModel upsRec) + { + using var activity = ActivitySource.StartActivity("Grp2OperInsertAsync"); + bool result = false; + result = await _productionRepository.Grp2OperInsertAsync(upsRec); + // elimino cache redis... + await FlushFusionCacheOprGrp(); + activity?.SetTag("data.source", "DB"); + activity?.Stop(); + LogTrace($"Grp2OperInsertAsync | CodGruppo {upsRec.CodGruppo} | MatrOpr {upsRec.MatrOpr} | {activity?.Duration.TotalMilliseconds}ms"); + return result; + } + + /// + /// Init ricetta + /// + /// + /// + /// + /// + public RecipeModel InitRecipe(string confPath, int idxPODL, Dictionary CalcArgs) + { + return mongoController.InitRecipe(confPath, idxPODL, CalcArgs); + } + + /// + /// Elimina record + svuotamento cache + /// + /// + public async Task IstKitDeleteAsync(IstanzeKitModel currRecord) + { + using var activity = ActivitySource.StartActivity("IstKitDeleteAsync"); + string source = "DB"; + // salvo + bool fatto = await _productionRepository.IstKitDeleteAsync(currRecord); + // svuoto cache + await FlushFusionCacheKit(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"IstKitDeleteAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elenco Istanze KIT da ricerca + /// + /// + /// + /// + public async Task> IstKitFiltAsync(string keyKit, string keyExtOrd) + { + string currKey = $"{Utils.redisKitInst}:{keyKit}:{keyExtOrd}"; + return await GetOrFetchAsync( + operationName: "IstKitFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.IstKitFiltAsync(keyKit, keyExtOrd) ?? new List(), + tagList: [Utils.redisKitInst] + ); + } + + /// + /// Effettua creazione istanza KIT + /// + /// Articolo KIT (fittizio) + /// Chiave x filtro conf su tab WKS + public async Task IstKitInsertByWKSAsync(string CodArtParent, string KeyFilt) + { + using var activity = ActivitySource.StartActivity("IstKitInsertByWKSAsync"); + string source = "DB"; + // salvo + bool fatto = await _productionRepository.IstKitInsertByWKSAsync(CodArtParent, KeyFilt); + // svuoto cache + await FlushFusionCacheKit(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"IstKitInsertByWKSAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Esegue salvataggio record + svuotamento cache + /// + /// + public async Task IstKitUpsertAsync(IstanzeKitModel currRecord) + { + using var activity = ActivitySource.StartActivity("IstKitUpsertAsync"); + string source = "DB"; + // salvo + bool fatto = await _productionRepository.IstKitUpsertAsync(currRecord); + // svuoto cache + await FlushFusionCacheKit(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"IstKitUpsertAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elenco giacenze filtrate x IdxOdl + /// + /// id odl da cercare + /// + public async Task> ListGiacenzeAsync(int IdxOdl) + { + string currKey = $"{Utils.redisGiacenzaList}:{IdxOdl}"; + return await GetOrFetchAsync( + operationName: "ListGiacenzeAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _productionRepository.ListGiacenzeAsync(IdxOdl) ?? new List(), + tagList: [Utils.redisGiacenzaList] + ); + } + + /// + /// Recupero elenco PODL filtrati + /// + /// + /// True = aperti (=senza ODL) + /// + public async Task> ListPODL_ByCodArtAsync(string CodArticolo, bool OnlyAvail) + { + string avType = OnlyAvail ? "Avail" : "ALL"; + string currKey = $"{Utils.redisPOdlByCodArt}:{CodArticolo}:{avType}"; + return await GetOrFetchAsync( + operationName: "ListPODL_ByCodArtAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.ListPODL_ByCodArtAsync(CodArticolo, OnlyAvail) ?? new(), + tagList: [Utils.redisPOdlByCodArt] + ); + } + + /// + /// Elenco di tutte le macchine filtrate x gruppo + /// + /// + /// + public async Task> MacchineGetFiltAsync(string codGruppo) + { + string keyGrp = codGruppo != "*" ? codGruppo : "ALL"; + string redisKey = $"{Utils.redisMacList}:{keyGrp}"; + + return await GetOrFetchAsync( + operationName: "MacchineGetFiltAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + await _productionRepository.MacchineGetFiltAsync(codGruppo) + ?? new List(), + tagList: [Utils.redisMacList] + ); + } + + /// + /// Verifica se la idxMaccSel abbia un codice PATH ricette associato + /// + /// + /// + public async Task MacchineRecipeArchiveAsync(string idxMacchina) + { + string currKey = $"{Utils.redisMacRecipePath}:{idxMacchina}"; + return await GetOrFetchAsync( + operationName: "MacchineRecipeArchiveAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + { + var machineList = await MacchineGetFiltAsync("*"); + var currMach = machineList.FirstOrDefault(x => x.IdxMacchina == idxMacchina); + return currMach?.RecipeArchivePath ?? ""; + }, + tagList: [Utils.redisMacRecipePath] + ); + } + + /// + /// Verifica se la idxMaccSel abbia un codice CONF ricetta associato + /// + /// + /// + public async Task MacchineRecipeConfAsync(string idxMacchina) + { + string currKey = $"{Utils.redisMacRecipeConf}:{idxMacchina}"; + return await GetOrFetchAsync( + operationName: "MacchineRecipeConfAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => + { + var machineList = await MacchineGetFiltAsync("*"); + var currMach = machineList.FirstOrDefault(x => x.IdxMacchina == idxMacchina); + return currMach?.RecipePath ?? ""; + }, + tagList: [Utils.redisMacRecipeConf] + ); + } + + /// + /// Elenco id Macchine che abbiano dati FLuxLog, nel periodo indicato + /// + /// + /// + /// + public async Task> MacchineWithFluxAsync(DateTime dtStart, DateTime dtEnd) + { + string currKey = $"{Utils.redisMacByFlux}:{dtStart:yyyyMMddHHmm}:{dtEnd:yyyyMMddHHmm}"; + return await GetOrFetchAsync( + operationName: "MacchineWithFluxAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.MacchineWithFluxAsync(dtStart, dtEnd) ?? new List(), + tagList: [Utils.redisMacByFlux] + ); + } + + public async Task> MachineWithOdlAsync() + { + string redisKey = Utils.redisOdlCurrByMac; + + return await GetOrFetchAsync( + operationName: "MachineWithOdlAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => + { + var rawData = await _productionRepository.OdlGetCurrentAsync(); + var dbResult = rawData + .Select(x => x.IdxMacchina) + .Distinct() + .ToList(); + + return dbResult ?? new List(); + }, + tagList: [Utils.redisOdlCurrByMac] + ); + } + + /// + /// Recupero info Machine-IOB x TAB (da info registrate IOB-WIN --> MP-IO) + /// + /// + /// + public async Task> MachIobConfAsync(string IdxMacchina) + { + string redisKey = Utils.redisIobConf; + return await GetOrFetchAsync( + operationName: "MachIobConfAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => + { + Dictionary result = new Dictionary(); + // cerco in redis... + string currKey = RedHashMpIO($"IOB:{IdxMacchina}:MachIobConfAsync"); + if (await redisDb.KeyExistsAsync(currKey)) + { + result = (await redisDb.HashGetAllAsync(currKey)) + .ToDictionary(x => $"{x.Name}", x => $"{x.Value}"); + } + return result; + }, + tagList: [Utils.redisIobConf] + ); + } + + /// + /// Elenco MSE stato amcchine + /// + /// Force refresh from DB + /// + public async Task> MseGetAllAsync(bool forceDb = false) + { + using var activity = ActivitySource.StartActivity("MseGetAllAsync"); + if (forceDb) + { + await _cache.RemoveAsync(Constants.redisMseKey); + } + return await GetOrFetchAsync( + operationName: "MseGetAllAsync", + cacheKey: Constants.redisMseKey, + expiration: TimeSpan.FromSeconds(1), + fetchFunc: async () => await _productionRepository.MseGetAllAsync(2000) ?? new(), + tagList: [Constants.redisMseKey] + ); + } + + /// + /// Invio notifica rilettura (con parametro) + /// + /// + public void NotifyReloadRequest(string message) + { + if (ReloadRequest != null) + { + // messaggio + ReloadEventArgs rea = new ReloadEventArgs(message); + ReloadRequest.Invoke(this, rea); + } + } + + /// + /// Elenco ODL dato batch selezionato + /// + /// Batch richiesto + /// + public async Task> OdlByBatchAsync(string BatchSel) + { + return await GetOrFetchAsync( + operationName: "OdlByBatchAsync", + cacheKey: Utils.redisOdlByBatch, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.OdlByBatchAsync(BatchSel), + tagList: [Utils.redisOdlByBatch] + ); + } + + /// + /// ODL da chiave + /// + /// + /// + public async Task OdlByKeyAsync(int IdxOdl) + { + string currKey = $"{Utils.redisOdlByKey}:{IdxOdl}"; + return await GetOrFetchAsync( + operationName: "OdlByKeyAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.OdlByKeyAsync(IdxOdl), + tagList: [Utils.redisOdlByKey] + ); + } + + /// + /// Effettua chiusura dell'ODL indicato, andand + /// + /// idx odl da chiudere + /// idx idxMaccSel + /// matricola operatore + /// indica se confermare i pezzi priam di chiudere ODL + public async Task ODLCloseAsync(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi) + { + using var activity = ActivitySource.StartActivity("ODLCloseAsync"); + string source = "DB"; + bool fatto = false; + + await EnsureConfigLoadedAsync(); + bool confRett = false; + _configData.TryGetValue("confRett", out var value); + if (!string.IsNullOrEmpty(value)) + { + bool.TryParse(value, out confRett); + } + int modoConfProd = 0; + _configData.TryGetValue("modoConfProd", out var vModo); + if (!string.IsNullOrEmpty(value)) + { + int.TryParse(vModo, out modoConfProd); + } + // chiamo metodo conferma! + fatto = await _productionRepository.ODLCloseAsync(idxOdl, idxMacchina, matrOpr, confPezzi, confRett, modoConfProd); + + await FlushFusionCacheAsync(Utils.redisOdlByKey); + + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"ODLCloseAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato) + /// + /// Stato ODL: true=in corso/completato + /// Cod articolo + /// KeyRich (parziale) da cercare (es cod stato x yacht) + /// Reparto selezionato + /// Macchina selezionata + /// Data inizio + /// Data fine + /// + public async Task> OdlListGetFiltAsync(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) + { + string currKey = $"{Utils.redisOdlList}:{inCorso}:{codArt}:{keyRichPart}:{Reparto}:{IdxMacchina}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; + return await GetOrFetchAsync( + operationName: "OdlListGetFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _productionRepository.ListODLFiltAsync(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate) ?? new(), + tagList: [Utils.redisOdlList] + ); + } + + /// + /// Statistiche ODL calcolate (da stored stp_STAT_ODL) + /// + /// + public async Task> OdlStatsAsync(int IdxOdl) + { + string currKey = $"{Utils.redisOdlStats}:{IdxOdl}"; + + return await GetOrFetchAsync( + operationName: "OdlStatsAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _productionRepository.OdlGetStatAsync(IdxOdl) ?? new(), + tagList: [Utils.redisOdlStats] + ); + } + + /// + /// Elenco operatori filtrati x gruppo + /// + /// + /// + public async Task> OperatoriGetFiltAsync(string codGruppo) + { + string keyGrp = codGruppo != "*" ? codGruppo : "ALL"; + string currKey = $"{Utils.redisOprList}:{keyGrp}"; + + return await GetOrFetchAsync( + operationName: "OperatoriGetFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.OperatoriGetFiltAsync(codGruppo) ?? new List(), + tagList: [Utils.redisOprList] + ); + } + + /// + /// Aggiornamento operatori su DB + invalidata cache + /// + /// + /// + public async Task OperatoriUpsertAsync(AnagOperatoriModel updRec) + { + using var activity = ActivitySource.StartActivity("OperatoriUpsertAsync"); + string source = "DB"; + bool fatto = false; + // salvo + fatto = await _productionRepository.OperatoriUpsertAsync(updRec); + await FlushFusionCacheAsync(Utils.redisOprList); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"OperatoriUpsertAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elenco di tutti i parametri filtrati x idxMaccSel + /// + /// * = tutte, altrimenti solo x una data idxMaccSel + /// + public async Task> ParametriGetFiltAsync(string IdxMacchina) + { + string currKey = $"{Utils.redisFluxByMac}:{IdxMacchina}"; + return await GetOrFetchAsync( + operationName: "ParametriGetFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _productionRepository.ParametriGetFiltAsync(IdxMacchina) ?? new(), + tagList: [Utils.redisFluxByMac] + ); + } + + /// + /// Restituisce dizionario ODL/PODL data lista IdxOdl + /// + /// + /// + public async Task> PODL_getDictOdlPodlAsync(List idxOdlList) + { + if (idxOdlList == null || !idxOdlList.Any()) + return new Dictionary(); + + var distinctIds = idxOdlList.Distinct().ToList(); + + var resultDictionary = new Dictionary(); + var missingIds = new List(); + + // STEP 1: Controllo rapido in FusionCache (L1/Memory cache) + foreach (var id in distinctIds) + { + var cacheKey = $"val:{id}"; + var cachedValue = await _cache.TryGetAsync(cacheKey); + + if (cachedValue.HasValue) + { + resultDictionary[id] = cachedValue.Value; + } + else + { + // ID non presente in cache, andrà cercato tramite il servizio EF + missingIds.Add(id); + } + } + + // STEP 2: Se ci sono cache miss, interroghiamo il servizio EF Core + if (missingIds.Any()) + { + // Riceviamo direttamente un Dictionary ottimizzato da EF Core + Dictionary dbResults = await _productionRepository.PODL_getDictOdlPodlAsync(missingIds); + + // STEP 3: Scriviamo i risultati in cache e li uniamo al dizionario finale + foreach (var kvp in dbResults) + { + var id = kvp.Key; + var targetValue = kvp.Value; + + resultDictionary[id] = targetValue; + + // Salvataggio atomico e globale su FusionCache + var cacheKey = $"val:{id}"; + await _cache.SetAsync(cacheKey, targetValue, TimeSpan.FromMinutes(30)); + } + + // STEP 4 [Altamente Consigliato]: Cache Penetration Protection + // Se un ID era tra i "missing" ma NON è presente nei risultati del DB, significa che non esiste. + // Salviamo un valore sentinella (es. 0 o -1) per evitare di ricontrollare il DB al prossimo giro. + foreach (var id in missingIds) + { + if (!dbResults.ContainsKey(id)) + { + resultDictionary[id] = 0; // Imposta un default per l'output corrente + + var cacheKey = $"val:{id}"; + await _cache.SetAsync(cacheKey, 0, TimeSpan.FromMinutes(2)); // Scadenza breve per i record inesistenti + } + } + } + + return resultDictionary; + } + + /// + /// Eliminazione record selezionato + /// + /// + /// + public async Task POdlDeleteRecord(PODLExpModel currRec) + { + using var activity = ActivitySource.StartActivity("POdlDeleteRecord"); + string source = "DB+REDIS"; + var dbResult = await _productionRepository.PODLDeleteRecordAsync(currRec); + // elimino cache redis... + await FlushFusionCachePOdl(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"POdlDeleteRecord | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return dbResult; + } + + /// + /// Avvio fase setup per il record selezionato + /// + /// + /// + public async Task POdlDoSetup(PODLExpModel currRec) + { + using var activity = ActivitySource.StartActivity("POdlDoSetup"); + string source = "DB+REDIS"; + var dbResult = await _productionRepository.PODL_startSetup(currRec, 0, 1, 1, "", DateTime.Now); + // elimino cache redis... + await FlushFusionCachePOdl(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"POdlDoSetup | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return dbResult; + } + + /// + /// Recupero PODL da chiave + /// + /// + /// + public async Task POdlGetByKey(int idxPODL) + { + string currKey = $"{Utils.redisPOdlByPOdl}:{idxPODL}"; + return await GetOrFetchAsync( + operationName: "POdlGetByKey", + cacheKey: currKey, + expiration: TimeSpan.FromMinutes(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.PODL_getByKeyAsync(idxPODL) ?? new(), + tagList: [Utils.redisPOdlByPOdl] + ); + } + + /// + /// Recupero PODL da IdxODL + /// + /// + /// + public async Task POdlGetByOdlAsync(int idxODL) + { + string currKey = $"{Utils.redisPOdlByOdl}:{idxODL}"; + return await GetOrFetchAsync( + operationName: "POdlGetByOdlAsync", + cacheKey: currKey, + expiration: TimeSpan.FromMinutes(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.PODL_getByOdlAsync(idxODL) ?? new(), + tagList: [Utils.redisPOdlByOdl] + ); + } + + /// + /// Effettua il task di eliminazione PODL KIT + istanze + riattivazione PODL originali disattivate tramite stored + /// + /// IdxPODL parent + public async Task PodlIstKitDeleteAsync(int IdxPODL) + { + using var activity = ActivitySource.StartActivity("PodlIstKitDeleteAsync"); + bool fatto = false; + // salvo + fatto = await _productionRepository.PodlIstKitDeleteAsync(IdxPODL); + // svuoto cache + await FlushFusionCachePOdl(); + activity?.SetTag("data.source", "DB"); + return fatto; + } + + /// + /// Elenco PODL in un istanza KIT dall'ID del parent + /// + /// IDX PODL parent + /// + public async Task> POdlListByKitParentAsync(int IdxPodlParent) + { + string currKey = $"{Utils.redisPOdlList}_kit:ByParent:{IdxPodlParent}"; + return await GetOrFetchAsync( + operationName: "POdlListByKitParentAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _productionRepository.ListPODL_ByKitParentAsync(IdxPodlParent) ?? new(), + tagList: [Utils.redisPOdlList] + ); + } + + /// + /// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato) + /// + /// Solo lanciati (1) o ancora disponibili (0) + /// KeyRich (parziale) da cercare (es cod stato x yacht) + /// Macchina + /// Gruppo + /// Data inizio + /// Data fine + /// + public async Task> POdlListGetFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) + { + string currKey = $"{Utils.redisPOdlList}:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; + return await GetOrFetchAsync( + operationName: "POdlListGetFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisShortTimeCache), + fetchFunc: async () => await _productionRepository.ListPODLFiltAsync(lanciato, keyRichPart, idxMacchina, codGruppo, startDate, endDate) ?? new List(), + tagList: [Utils.redisPOdlList] + ); + } + + /// + /// Elenco PODL per composizione KIT (Async) non avviati filtrati x articolo, KeyRich (che contiene stato) + /// + /// Solo lanciati (1) o ancora disponibili (0) + /// KeyRich (parziale) da cercare (es cod stato x yacht) + /// Macchina + /// Gruppo + /// Data inizio + /// Data fine + /// + public async Task> POdlToKitListGetFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) + { + string redisKey = $"{Utils.redisPOdlList}_kit:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; + + return await GetOrFetchAsync( + operationName: "POdlToKitListGetFiltAsync", + cacheKey: redisKey, + expiration: GetRandTOut(redisShortTimeCache * 5), + fetchFunc: async () => + await _productionRepository.ListPODL_KitFiltAsync( + lanciato, + keyRichPart, + idxMacchina, + codGruppo, + startDate, + endDate + ) ?? new List(), + tagList: [Utils.redisPOdlList, $"{Utils.redisPOdlList}_kit"] + ); + } + + /// + /// Chiamata salvataggio ricetta + refresh REDIS + /// + /// + /// + /// + public async Task POdlUpdateRecipe(int idxPODL, string recipeName) + { + using var activity = ActivitySource.StartActivity("POdlUpdateRecipe"); + string source = "DB"; + bool answ = false; + answ = await _productionRepository.PODL_updateRecipe(idxPODL, recipeName); + // reset redis... + await FlushFusionCachePOdl(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"POdlUpdateRecipe | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return answ; + } + + /// + /// Aggiornamento record selezionato + /// + /// + /// + public async Task POdlUpdateRecord(PODLModel currRec) + { + using var activity = ActivitySource.StartActivity("POdlUpdateRecord"); + string source = "DB"; + var dbResult = await _productionRepository.PODLUpdateRecordAsync(currRec); + // elimino cache redis... + await FlushFusionCachePOdl(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"POdlUpdateRecord | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return dbResult; + } + + /// + /// Restituisce le statistiche di processo correnti x depluplica FluxLog + /// + /// + public async Task> ProcFLStatsAsync() + { + using var activity = ActivitySource.StartActivity("ProcFLStatsAsync"); + string source = "REDIS"; + List actStats = new List(); + string currKey = $"{Utils.redisStatsProcFL}"; + // recupero i record statistiche correnti + RedisValue rawData = await redisDb.StringGetAsync(currKey); + if (rawData.HasValue) + { + var rawStats = JsonConvert.DeserializeObject>($"{rawData}"); + if (rawStats != null) + { + actStats = rawStats; + } + } + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"ProcFLStatsAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return actStats; + } + + /// + /// Ricerca ricetta su MongoDB dato PODL + /// + /// + /// + public async Task RecipeGetByPODL(int idxPODL) + { + RecipeModel? result = null; + using var activity = ActivitySource.StartActivity("RecipeGetByPODL"); + string source = "MongoDB"; + result = await mongoController.RecipeGetByPODL(idxPODL); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"RecipeGetByPODL | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return result; + } + + /// + /// Salva ricetta su MongoDB + /// + /// + /// + public async Task RecipeSetByPODL(RecipeModel currRecord) + { + using var activity = ActivitySource.StartActivity("RecipeSetByPODL"); + string source = "MONGO"; + bool answ = false; + answ = await mongoController.RecipeSetByPODL(currRecord); + await FlushFusionCachePOdl(); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"RecipeSetByPODL | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return answ; + } + + /// + /// Reset della cache IO post operazioni come setup ODL... + /// + /// Indirizzo base da cui rimuovere memoria cache + /// + public async Task ResetIoCache(string baseMem) + { + using var activity = ActivitySource.StartActivity("ResetIoCache"); + string source = "REDIS"; + // patterna a partire da cache IO... + RedisValue pattern = new RedisValue($"{MpIoNS}:*"); + if (!string.IsNullOrEmpty(baseMem)) + { + pattern = new RedisValue($"{MpIoNS}:{baseMem}:*"); + } + bool answ = await ExecFlushRedisPatternAsync(pattern); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"ResetIoCache | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return answ; + } + + /// + /// Stato macchina + /// + /// + /// + public async Task StatoMacchinaAsync(string idxMacchina) + { + string currKey = $"{Utils.redisStatoMacch}:{idxMacchina}"; + + return await GetOrFetchAsync( + operationName: "StatoMacchinaAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.StatoMacchinaAsync(idxMacchina) ?? new(), + tagList: [Utils.redisStatoMacch] + ); + } + + /// + /// Elimina record + svuotamento cache + /// + /// + public async Task TemplateKitDeleteAsync(TemplateKitModel currRecord) + { + using var activity = ActivitySource.StartActivity("TemplateKitDeleteAsync"); + string source = "DB"; + bool fatto = false; + // salvo + fatto = await _productionRepository.TemplateKitDeleteAsync(currRecord); + await FlushFusionCacheAsync(Utils.redisKitTempl); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"TemplateKitDeleteAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elenco Template KIT da ricerca + /// + /// Codice articolo padre + /// Codice articolo figlio + /// + public async Task> TemplateKitFiltAsync(string codParent, string codChild) + { + string currKey = $"{Utils.redisKitTempl}:{codParent}:{codChild}"; + + return await GetOrFetchAsync( + operationName: "TemplateKitFiltAsync", + cacheKey: currKey, + expiration: GetRandTOut(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.TemplateKitFiltAsync(codParent, codChild) ?? new List(), + tagList: [Utils.redisKitTempl] + ); + } + + /// + /// Esegue salvataggio record + svuotamento cache + /// + /// + /// + public async Task TemplateKitUpsertAsync(TemplateKitModel currRecord, string codAzienda) + { + using var activity = ActivitySource.StartActivity("TemplateKitUpsertAsync"); + string source = "DB"; + bool fatto = false; + // salvo + fatto = await _productionRepository.TemplateKitUpsertAsync(currRecord, codAzienda); + await FlushFusionCacheAsync(Utils.redisKitTempl); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"TemplateKitUpsertAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Punteggio compatibilità KIT per KeyFilt indicato + /// + /// + /// + /// + /// + public async Task> TksScoreAsync(string KeyFilt, int MaxResult, bool ForceDb) + { + string currKey = $"{Utils.redisKitScore}:{KeyFilt}:{MaxResult}"; + + if (ForceDb) + { + // Se ForceDb è true, saltiamo il GetOrFetchAsync per forzare il fetch dal DB + // e aggiornare la cache. + var result = await _productionRepository.TksScoreAsync(KeyFilt, MaxResult) ?? new List(); + await _cache.SetAsync(currKey, result, TimeSpan.FromMinutes(redisLongTimeCache), tags: [Utils.redisKitScore]); + return result; + } + + return await GetOrFetchAsync( + operationName: "TksScoreAsync", + cacheKey: currKey, + expiration: TimeSpan.FromMinutes(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.TksScoreAsync(KeyFilt, MaxResult) ?? new List(), + tagList: [Utils.redisKitScore] + ); + } + + /// + /// Esegue traduzione dato vocabolario da Lingua + Lemma + /// + /// + /// + /// + public string Traduci(string lemma, string lingua) + { + if (string.IsNullOrWhiteSpace(lemma)) return string.Empty; + if (string.IsNullOrWhiteSpace(lingua)) return lemma; + + string linguaKey = lingua.ToLowerInvariant().Trim(); + string cacheKey = $"vocab:{linguaKey}"; + + // FusionCache gestisce il lock e recupera l'intero dizionario della lingua. + // Se è in L1 (Memory), restituisce l'oggetto C# istantaneamente. + // Se non c'è, passa a L2 (Redis) o invoca la factory per caricarlo. + var dizionarioLingua = _cache.GetOrSet>( + cacheKey, + _ => _anagRepository.VocabolarioGetLang(linguaKey), + options => options + .SetDuration(TimeSpan.FromHours(8)) // Durata logica della cache + .SetFailSafe(true, TimeSpan.FromHours(1)) // Se Redis/DB è giù, usa i vecchi dati L1 + ); + + // Ricerca O(1) nel dizionario in memoria + if (dizionarioLingua != null && dizionarioLingua.TryGetValue(lemma, out var traduzione)) + { + return traduzione; + } + + // Fallback: se la parola non è censita, restituisce il lemma originale + return lemma; + } + + /// + /// Elimina record + svuotamento cache + /// + /// + public async Task WipKitDeleteAsync(WipSetupKitModel currRecord) + { + using var activity = ActivitySource.StartActivity("WipKitDeleteAsync"); + string source = "DB"; + bool fatto = false; + // salvo + fatto = await _productionRepository.WipKitDeleteAsync(currRecord); + // svuoto cache + await FlushFusionCacheAsync(Utils.redisKitWip); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"WipKitDeleteAsync Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elimina i record più vecchi della data-ora indicata + /// + /// + public async Task WipKitDeleteOlderAsync(DateTime DateLimit) + { + using var activity = ActivitySource.StartActivity("WipKitDeleteOlderAsync"); + string source = "DB"; + bool fatto = false; + // salvo + fatto = await _productionRepository.WipKitDeleteOlderAsync(DateLimit); + // svuoto cache KitWip + await FlushFusionCacheAsync(Utils.redisKitWip); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"WipKitDeleteOlderAsync Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + /// + /// Elenco Template KIT da ricerca + /// + /// + /// + public async Task> WipKitFiltAsync(string KeyFilt) + { + string currKey = $"{Utils.redisKitWip}:{KeyFilt}"; + return await GetOrFetchAsync( + operationName: "WipKitFiltAsync", + cacheKey: currKey, + expiration: TimeSpan.FromMinutes(redisLongTimeCache), + fetchFunc: async () => await _productionRepository.WipKitFiltAsync(KeyFilt) ?? new List(), + tagList: [Utils.redisKitWip] + ); + } + + /// + /// Esegue salvataggio record + svuotamento cache + /// + /// + public async Task WipKitUpsertAsync(WipSetupKitModel currRecord) + { + using var activity = ActivitySource.StartActivity("WipKitUpsertAsync"); + string source = "DB"; + bool fatto = false; + // salvo + fatto = await _productionRepository.WipKitUpsertAsync(currRecord); + // svuoto cache KitWip + await FlushFusionCacheAsync(Utils.redisKitWip); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"WipKitUpsertAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return fatto; + } + + #endregion Public Methods + + #region Private Fields + + /// + /// Oggetto per collezione dati Activity (span in Uptrace) + /// + private static readonly ActivitySource ActivitySource = new ActivitySource("MP.DATA.Tracer"); + + private static IConfiguration _configuration = null!; + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + private readonly IFusionCache _cache; + + private DateTime _artCacheExpiry = DateTime.MinValue; + + private Dictionary _configData = new(); + + private DateTime _dtParamExpiry = DateTime.Now; + + /// + /// Elenco CodArticolo usati in istanza KIT (per verifica eliminabilità) + /// + private HashSet _listCodArtInKit = new(); + + /// + /// Elenco CodArticolo NON usati (per verifica eliminabilità) + /// + private HashSet _listCodArtNotUsed = new(); + + /// + /// Elenco CodArticolo usati (per verifica eliminabilità) + /// + private HashSet _listCodArtUsed = new(); + + private string MpIoNS = ""; + + private Random rand = new Random(); + + /// + /// Oggetto per connessione a REDIS + /// + private IConnectionMultiplexer redisConn = null!; + + /// + /// Oggetto per connessione a REDIS modalità admin (ex flux dati) + /// + private ConnectionMultiplexer redisConnAdmin = null!; + + /// + /// Oggetto DB redis da impiegare x chiamate R/W + /// + private IDatabase redisDb = null!; + + /// + /// Durata cache Lunga standard (300 sec) + /// + private int redisLongTimeCache = 300; + + /// + /// Durata cache Breve standard (5 sec) + /// + private int redisShortTimeCache = 5; + + /// + /// Soglia minima (ms) per log timing in console + /// + private double slowLogThresh = 0; + + private bool traceEnabled = false; + + #endregion Private Fields + + #region Private Properties + + private static MpSpecController dbController { get; set; } = null!; + + private static MpMongoController mongoController { get; set; } = null!; + + #endregion Private Properties + + #region Private Methods + + /// + /// Verifica caricamento dizionario ConfigData + /// + /// + private async Task EnsureConfigLoadedAsync() + { + if (_configData.Count == 0) + { + var list = await ConfigGetAllAsync(); + + _configData = list + .GroupBy(x => x.Chiave) + .ToDictionary(g => g.Key, g => g.First().Valore); + } + } + /// /// Esegue flush memoria redis dato keyVal, async /// /// /// - public async Task ExecFlushRedisPatternAsync(RedisValue pat2Flush) + private async Task ExecFlushRedisPatternAsync(RedisValue pat2Flush) { bool answ = false; using var activity = ActivitySource.StartActivity("ExecFlushRedisPatternAsync"); @@ -1141,2033 +2170,227 @@ namespace MP.SPEC.Data return answ; } - /// - /// Imposta in redis la scadenza della pagina x il reload - /// - /// - /// - public DateTime ExpiryReloadParamGet() + private async Task FlushFusionCacheArticoli() { - using var activity = ActivitySource.StartActivity("ExpiryReloadParamGet"); - string source = "REDIS"; - DateTime dtRif = DateTime.Now; - string currKey = $"{Utils.redisParamPageExp}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - dtRif = JsonConvert.DeserializeObject($"{rawData}"); - } + using var activity = ActivitySource.StartActivity("FlushFusionCacheArticoli"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List() { Utils.redisArtList, Utils.redisArtByDossier }); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ExpiryReloadParamGet | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return dtRif; - } - - /// - /// Imposta in redis la scadenza della pagina x il reload - /// - /// - /// - public bool ExpiryReloadParamSet(DateTime expTime) - { - using var activity = ActivitySource.StartActivity("ExpiryReloadParamSet"); - string source = "REDIS"; - bool fatto = false; - string currKey = $"{Utils.redisParamPageExp}"; - string rawData = JsonConvert.SerializeObject(expTime); - fatto = redisDb.StringSet(currKey, rawData); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ExpiryReloadParamSet | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - public async Task FlushCacheFluxLog() - { - using var activity = ActivitySource.StartActivity("FlushCacheFluxLog"); - string source = "REDIS"; - bool answ = false; - RedisValue pattern = new RedisValue($"{Utils.redisParetoFLKey}:*"); - answ = await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"FlushCacheFluxLog | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"FlushFusionCacheArticoli | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } /// - /// Flush cache relativa a MP-IO x dati ODL + /// Cancellazione FusionCache (totale) /// /// - public async Task FlushMpIoOdlCache() + private async Task FlushFusionCacheAsync() { - using var activity = ActivitySource.StartActivity("FlushMpIoOdlCache"); - string source = "REDIS"; - // svuoto dalla cache REDIS del server IO... - bool ok01 = await ResetIoCache("CurrODL"); - bool ok02 = await ResetIoCache("CurrOdlRow"); - bool ok03 = await ResetIoCache("CurrStatoMacc"); - bool ok04 = await ResetIoCache("DtMac"); - activity?.SetTag("data.source", "REDIS"); - activity?.Stop(); - LogTrace($"FlushMpIoOdlCache | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return ok01 && ok02 && ok03 && ok04; + await _cache.ClearAsync(allowFailSafe: false); + _configData.Clear(); + _artCacheExpiry = DateTime.Now.AddHours(-1); + return true; } - public async Task FlushRedisCache() + /// + /// Cancellazione FusionCache dato singolo tag + /// + /// + private async Task FlushFusionCacheAsync(string tag) { - using var activity = ActivitySource.StartActivity("FlushRedisCache"); - string source = "REDIS"; - RedisValue pattern = Utils.RedValue("*"); - bool answ = await ExecFlushRedisPatternAsync(pattern); - // rileggo vocabolario.,.. - ObjVocabolario = VocabolarioGetAll(); + if (string.IsNullOrWhiteSpace(tag)) return false; + + await _cache.RemoveByTagAsync(tag); + _configData.Clear(); + return true; + } + + /// + /// Cancellazione FusionCache dato elenco tags + /// + /// + private async Task FlushFusionCacheAsync(List listTags) + { + if (listTags == null || listTags.Count == 0) return false; + + // Generiamo i Task di rimozione ed eseguiamoli in parallelo su Redis/L1 + var tasks = listTags + .Where(tag => !string.IsNullOrWhiteSpace(tag)) + .Select(tag => _cache.RemoveByTagAsync(tag).AsTask()); + + await Task.WhenAll(tasks); + + _configData.Clear(); + return true; + } + + private async Task FlushFusionCacheConfig() + { + using var activity = ActivitySource.StartActivity("FlushFusionCacheConfig"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List() { Utils.redisConfKey }); + activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"FlushRedisCache | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"FlushFusionCacheConfig | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } - public async Task FlushRedisKey(string redKey) + private async Task FlushFusionCacheFluxLog() { - using var activity = ActivitySource.StartActivity("FlushRedisKey"); - string source = "REDIS"; - RedisValue pattern = Utils.RedValue(redKey); - bool answ = await ExecFlushRedisPatternAsync(pattern); + using var activity = ActivitySource.StartActivity("FlushFusionCacheFluxLog"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List() { Utils.redisFluxLogFilt, Utils.redisParetoFLKey }); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"FlushRedisKey | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + LogTrace($"FlushFusionCacheFluxLog | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return answ; + } + + private async Task FlushFusionCacheKit() + { + using var activity = ActivitySource.StartActivity("FlushFusionCacheKit"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List() { Utils.redisPOdlList, Utils.redisKitInst, Utils.redisKitWip, Utils.redisKitScore, Utils.redisPOdlByCodArt }); + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"FlushFusionCacheKit | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } /// - /// Funzione di Data Reduction x FluxLog + /// Reset macchine e gruppi /// - /// Macchina - /// Elenco FL da processare - /// Periodo - /// modalità sel valore - /// intervallo di analisi - /// max num per intervallo - /// - public async Task FluxLogDataRedux(string idxMaccSel, List fluxList, DtUtils.Periodo currPeriodo, Enums.ValSelection valMode, Enums.DataInterval intReq, int maxItem) + private async Task FlushFusionCacheMacGrp() { - using var activity = ActivitySource.StartActivity("FluxLogDataRedux"); - string source = "DB+REDIS"; - List procStats = await dbController.FluxLogDataRedux(idxMaccSel, fluxList, currPeriodo, valMode, intReq, maxItem); - // effettuo merge statistiche... - ProcDedupStatMerge(procStats); - // svuoto cache - await FlushCacheFluxLog(); + using var activity = ActivitySource.StartActivity("FlushFusionCacheMacGrp"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List { Utils.redisAnagGruppi, Utils.redisMacList }); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"FluxLogDataRedux | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - } - - public List FluxLogDtoGetByFlux(string Valore) - { - List answ = new List(); - DossierFluxLogDTO? result = JsonConvert.DeserializeObject(Valore); - if (result != null) - { - if (result.ODL != null) - { - answ = result - .ODL - .OrderBy(x => x.CodFlux) - .ToList(); - // inizializzo SE necessario - foreach (var item in answ) - { - item.ValoreEdit = String.IsNullOrEmpty(item.ValoreEdit) ? item.Valore : item.ValoreEdit; - } - } - } + LogTrace($"FlushFusionCacheMacGrp | {source} | {activity?.Duration.TotalMilliseconds}ms"); return answ; } /// - /// Elenco ultimi n record flux log dato idxMaccSel e flusso (ordinato x data registrazione) + /// Reset cache operatori e gruppi /// - /// Data massima x eventi - /// Data minima x eventi - /// * = tutte, altrimenti solo x una data idxMaccSel - /// *=tutti, altrimenti solo selezionato - /// numero massimo record da restituire - /// - public async Task> FluxLogGetLastFilt(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec, double redisCacheSec) + private async Task FlushFusionCacheOprGrp() { - using var activity = ActivitySource.StartActivity("FluxLogGetLastFilt"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisFluxLogFilt}:{IdxMacchina}:{CodFlux}:{MaxRec}:{DtMax:yyyyMMddHHmm}:{DtMin:yyyyMMddHHmm}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.FluxLogGetLastFilt(DtMax, DtMin, IdxMacchina, CodFlux, MaxRec)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - if (string.IsNullOrEmpty(canCacheParametri)) - { - canCacheParametri = await ConfigTryGetAsync("SPEC_ParametriEnableRedisCache"); - } - if (canCacheParametri != "false") - { - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisCacheSec)); - } - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"FluxLogGetLastFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco Gruppi - /// - /// - public async Task> FluxLogPareto(string idxMacchina, DateTime dtFrom, DateTime dtTo) - { - using var activity = ActivitySource.StartActivity("FluxLogPareto"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - string redKey = $"{Utils.redisParetoFLKey}:{idxMacchina}:{dtFrom:yyyyMMdd}:{dtTo:yyyyMMdd}"; - RedisValue rawData = await redisDb.StringGetAsync(redKey); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.FluxLogPareto(idxMacchina, dtFrom, dtTo)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(redKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"FluxLogPareto | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Stored manutenzione del DB - /// - /// Esegue realmente il task - /// Aggiornamento statistiche - /// Salvataggio - /// def: 1000 - /// def: 10 - /// def: 50 - /// - public async Task ForceDbMaint(bool doExec = true, bool doUpdStat = true, bool doSave = true, int minPgCnt = 1000, int minAvgFrag = 10, int maxAvgFragReb = 50) - { - using var activity = ActivitySource.StartActivity("ForceDbMaint"); - string source = "DB+REDIS"; - await dbController.ForceDbMaint(doExec, doUpdStat, doSave, minPgCnt, minAvgFrag, maxAvgFragReb); - // svuoto cache - await FlushCacheFluxLog(); + using var activity = ActivitySource.StartActivity("FlushFusionCacheOprGrp"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List { Utils.redisAnagGruppi, Utils.redisOprList }); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ForceDbMaint | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - // registro statistiche esecuzione - RecDbMaintStat(activity?.Duration ?? TimeSpan.FromSeconds(1)); + LogTrace($"FlushFusionCacheOprGrp | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return answ; } - /// - /// Eliminazione di un record macchina dal gruppo - /// - /// - /// - public bool Grp2MaccDelete(Gruppi2MaccModel rec2del) + private async Task FlushFusionCachePOdl() { - using var activity = ActivitySource.StartActivity("Grp2MaccDelete"); - bool result = false; - result = dbController.Grp2MaccDelete(rec2del); - // elimino cache redis... - ResetMacGrpCache(); - activity?.SetTag("data.source", "DB+REDIS"); - activity?.Stop(); - LogTrace($"Grp2MaccDelete | CodGruppo {rec2del.CodGruppo} | IdxMacc {rec2del.IdxMacchina} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Insert di un record macchina - /// - /// - /// - public bool Grp2MaccInsert(Gruppi2MaccModel upsRec) - { - using var activity = ActivitySource.StartActivity("Grp2MaccInsert"); - bool result = false; - result = dbController.Grp2MaccInsert(upsRec); - // elimino cache redis... - ResetMacGrpCache(); - activity?.SetTag("data.source", "DB+REDIS"); - activity?.Stop(); - LogTrace($"Grp2MaccInsert | CodGruppo {upsRec.CodGruppo} | IdxMacc {upsRec.IdxMacchina} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Eliminazione di un record operatore dal gruppo - /// - /// - /// - public bool Grp2OperDelete(Gruppi2OperModel rec2del) - { - using var activity = ActivitySource.StartActivity("Grp2OperDelete"); - bool result = false; - result = dbController.Grp2OperDelete(rec2del); - // elimino cache redis... - ResetOprGrpCache(); - activity?.SetTag("data.source", "DB+REDIS"); - activity?.Stop(); - LogTrace($"Grp2OperDelete | CodGruppo {rec2del.CodGruppo} | MatrOpr {rec2del.MatrOpr} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Insert di un record operatore - /// - /// - /// - public bool Grp2OperInsert(Gruppi2OperModel upsRec) - { - using var activity = ActivitySource.StartActivity("Grp2OperInsert"); - bool result = false; - result = dbController.Grp2OperInsert(upsRec); - // elimino cache redis... - ResetOprGrpCache(); - activity?.SetTag("data.source", "DB+REDIS"); - activity?.Stop(); - LogTrace($"Grp2OperInsert | CodGruppo {upsRec.CodGruppo} | MatrOpr {upsRec.MatrOpr} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Init ricetta - /// - /// - /// - /// - /// - public RecipeModel InitRecipe(string confPath, int idxPODL, Dictionary CalcArgs) - { - return mongoController.InitRecipe(confPath, idxPODL, CalcArgs); - } - - /// - /// Recupero info IOB x TAB (da info registrate IOB-WIN--> MP-IO) - /// - /// - /// - public async Task IobInfo(string IdxMacchina) - { - using var activity = ActivitySource.StartActivity("IobInfo"); - string source = "DB"; - IOB_data? result = new IOB_data(); - // cerco in redis... - string currKey = redHashMpIO($"hM2IOB:{IdxMacchina}"); - RedisValue rawData = await redisDb.StringGetAsync(currKey); - //if (!string.IsNullOrEmpty($"{rawData}")) - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject($"{rawData}"); - source = "REDIS"; - } - else - { - Log.Error($"Errore: non trovato valore valido in REDIS | key: {currKey}"); - Log.Info($"REDIS | conf: {redisConn.Configuration}"); - Log.Info($" --> Valore trovato:{Environment.NewLine}{rawData}"); - } - if (result == null) - { - result = new IOB_data(); - LogTrace($"Init valore default | IdxMacchina: {IdxMacchina}"); - } + using var activity = ActivitySource.StartActivity("FlushFusionCachePOdl"); + string source = "FUSION"; + bool answ = await FlushFusionCacheAsync(new List() { Utils.redisXdlData, Utils.redisPOdlByOdl, Utils.redisPOdlByPOdl, Utils.redisPOdlList }); activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"IobInfo per {IdxMacchina} | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; + LogTrace($"FlushFusionCachePOdl | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return answ; } /// - /// Elimina record + svuotamento cache + /// Implementa gestione FusionCache+ tracking attività + /// - recupero cache da memoria o da obj esterno + cache memoria + /// - recupero da fetchFunc se mancasse + store in cache L1/L2 /// - /// - public async Task IstKitDelete(IstanzeKitModel currRecord) - { - using var activity = ActivitySource.StartActivity("IstKitDelete"); - string source = "DB+REDIS"; - bool fatto = false; - // salvo - fatto = dbController.IstKitDelete(currRecord); - // svuoto cache - RedisValue pattern = $"{Utils.redisKitInst}:*"; - await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"IstKitDelete | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Elenco Istanze KIT da ricerca - /// - /// - /// + /// + /// + /// + /// /// - public List IstKitFilt(string keyKit, string keyExtOrd) + private async Task GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tagList) { - using var activity = ActivitySource.StartActivity("IstKitFilt"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - string currKey = $"{Utils.redisKitInst}:{keyKit}:{keyExtOrd}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) + using var activity = ActivitySource.StartActivity(operationName); + string source; + var tryGet = await _cache.TryGetAsync(cacheKey); + if (tryGet.HasValue) { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.IstKitFilt(keyKit, keyExtOrd); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromMinutes(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"IstKitFilt | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } + source = "MEMORY"; + var result = tryGet.Value!; - /// - /// Effettua creazione istanza KIT - /// - /// Articolo KIT (fittizio) - /// Chiave x filtro conf su tab WKS - public bool IstKitInsertByWKS(string CodArtParent, string KeyFilt) - { - bool fatto = false; - using var activity = ActivitySource.StartActivity("IstKitInsertByWKS"); - string source = "DB+REDIS"; - // salvo - fatto = dbController.IstKitInsertByWKS(CodArtParent, KeyFilt); - // svuoto cache - ExecFlushRedisPattern($"{Utils.redisKit}:*"); - //ExecFlushRedisPattern((RedisValue)$"{Utils.redisKitInst}:*"); - //ExecFlushRedisPattern((RedisValue)$"{Utils.redisKitScore}:*"); - //ExecFlushRedisPattern((RedisValue)$"{Utils.redisKitTempl}:*"); - //ExecFlushRedisPattern((RedisValue)$"{Utils.redisKitWip}:*"); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"IstKitInsertByWKS | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Esegue salvataggio record + svuotamento cache - /// - /// - public async Task IstKitUpsert(IstanzeKitModel currRecord) - { - using var activity = ActivitySource.StartActivity("IstKitUpsert"); - string source = "DB+REDIS"; - bool fatto = false; - // salvo - fatto = dbController.IstKitUpsert(currRecord); - // svuoto cache - RedisValue pattern = $"{Utils.redisKitInst}:*"; - await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"IstKitUpsert | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// - /// id odl da cercare - /// - public async Task> ListGiacenze(int IdxOdl) - { - using var activity = ActivitySource.StartActivity("ListGiacenze"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisGiacenzaList}:{IdxOdl}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ListGiacenze(IdxOdl)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ListGiacenze | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Recupero elenco PODL filtrati - /// - /// - /// True = aperti (=senza ODL) - /// - public List ListPODL_ByCodArt(string CodArticolo, bool OnlyAvail) - { - List result = new List(); - if (!string.IsNullOrEmpty(CodArticolo)) - { - using var activity = ActivitySource.StartActivity("ListPODL_ByCodArt"); - string source = "DB"; - string avType = OnlyAvail ? "Avail" : "ALL"; - string currKey = $"{Utils.redisPOdlByCodArt}:{CodArticolo}:{avType}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue && rawData.Length() > 2) - { - var rawResult = JsonConvert.DeserializeObject>($"{rawData}"); - if (rawResult != null) - { - result = rawResult; - source = "REDIS"; - } - } - else - { - result = dbController.ListPODL_ByCodArt(CodArticolo, OnlyAvail); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); activity?.Stop(); - Log.Trace($"ListPODL_ByCodArt | {source} | {activity?.Duration.TotalMilliseconds}ms"); - } - else - { - Log.Debug("Errore CodArt vuoto"); - } - return result; - } - - /// - /// Elenco di tutte le macchine filtrate x gruppo - /// - /// - /// - public List MacchineGetFilt(string codGruppo) - { - using var activity = ActivitySource.StartActivity("MacchineGetFilt"); - List? result = new List(); - string source = "DB"; - string keyGrp = codGruppo != "*" ? codGruppo : "ALL"; - string currKey = $"{Utils.redisMacList}:{keyGrp}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.MacchineGetFilt(codGruppo); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", 1); - activity?.Stop(); - LogTrace($"MacchineGetAll | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Verifica se la idxMaccSel abbia un codice PATH ricette associato - /// - /// - /// - public string MacchineRecipeArchive(string idxMacchina) - { - using var activity = ActivitySource.StartActivity("MacchineRecipeArchive"); - string? result = ""; - string source = "DB"; - string currKey = $"{Utils.redisMacRecipePath}:{idxMacchina}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject($"{rawData}"); - source = "REDIS"; - } - else - { - //recupero elenco macchine... - var machineList = MacchineGetFilt("*"); - var currMach = machineList.Where(x => x.IdxMacchina == idxMacchina).FirstOrDefault(); - result = currMach != null ? currMach.RecipeArchivePath : null; - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", 1); - activity?.Stop(); - LogTrace($"MacchineRecipeArchive | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result ?? ""; - } - - /// - /// Verifica se la idxMaccSel abbia un codice CONF ricetta associato - /// - /// - /// - public string MacchineRecipeConf(string idxMacchina) - { - using var activity = ActivitySource.StartActivity("MacchineRecipeConf"); - string? result = ""; - string source = "DB"; - string currKey = $"{Utils.redisMacRecipeConf}:{idxMacchina}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject($"{rawData}"); - source = "REDIS"; - } - else - { - //recupero elenco macchine... - var machineList = MacchineGetFilt("*"); - var currMach = machineList.Where(x => x.IdxMacchina == idxMacchina).FirstOrDefault(); - result = currMach != null ? currMach.RecipePath : null; - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", 1); - activity?.Stop(); - LogTrace($"MacchineRecipeConf | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result ?? ""; - } - - /// - /// Elenco id Macchine che abbiano dati FLuxLog, nel periodo indicato - /// - /// - /// - /// - public async Task> MacchineWithFlux(DateTime dtStart, DateTime dtEnd) - { - using var activity = ActivitySource.StartActivity("MacchineWithFlux"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisMacByFlux}:{dtStart:yyyyMMddHHmm}:{dtEnd:yyyyMMddHHmm}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await dbController.MacchineWithFlux(dtStart, dtEnd); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"MacchineWithFlux | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Recupero info Machine-IOB x TAB (da info registrate IOB-WIN --> MP-IO) - /// - /// - /// - public Dictionary MachIobConf(string IdxMacchina) - { - using var activity = ActivitySource.StartActivity("MachIobConf"); - string source = "DB"; - Dictionary result = new Dictionary(); - // cerco in redis... - string currKey = redHashMpIO($"IOB:{IdxMacchina}:MachIobConf"); - try - { - result = redisDb - .HashGetAll(currKey) - .ToDictionary(x => $"{x.Name}", x => $"{x.Value}"); - source = "REDIS"; - } - catch (Exception exc) - { - Log.Error($"Errore in MachIobConf{Environment.NewLine}{exc}"); - } - if (result == null) - { - result = new Dictionary(); - LogTrace($"Init valore default MachIobConf | IdxMacchina: {IdxMacchina}"); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"MachIobConf per {IdxMacchina} | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Recupero singolo recordo info Machine-IOB x TAB (da info registrate IOB-WIN --> MP-IO) - /// - /// - /// - public string MachIobConfVal(string IdxMacchina, string Key) - { - string answ = ""; - var currList = MachIobConf(IdxMacchina); - if (currList.ContainsKey(Key)) - { - answ = currList[Key]; - } - return answ; - } - - /// - /// Elenco MSE stato amcchine - /// - /// - /// - public async Task> MseGetAll(bool forceDb = false) - { - using var activity = ActivitySource.StartActivity("MseGetAllAsync"); - string source = "DB"; - List? result = new List(); - // cerco in redisConn... - RedisValue rawData = redisDb.StringGet(Constants.redisMseKey); - if (rawData.HasValue && !forceDb) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.MseGetAll(2000)); - // serializzp e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(Constants.redisMseKey, rawData, TimeSpan.FromSeconds(1)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"MseGetAllAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Invio notifica rilettura (con parametro) - /// - /// - public void NotifyReloadRequest(string message) - { - if (ReloadRequest != null) - { - // messaggio - ReloadEventArgs rea = new ReloadEventArgs(message); - ReloadRequest.Invoke(this, rea); - } - } - - /// - /// Elenco ODL dato batch selezionato - /// - /// Batch richiesto - /// - public async Task> OdlByBatch(string BatchSel) - { - using var activity = ActivitySource.StartActivity("OdlByBatch"); - List? result = new List(); - string source = "DB"; - string currKey = Utils.redisOdlByBatch; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.OdlByBatch(BatchSel)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"OdlByBatch | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// ODL da chiave - /// - /// - /// - public ODLExpModel OdlByKey(int IdxOdl) - { - using var activity = ActivitySource.StartActivity("OdlByKey"); - ODLExpModel? result = new ODLExpModel(); - string source = "DB"; - result = dbController.OdlByKey(IdxOdl); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"OdlByKey | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Effettua chiusura dell'ODL indicato, andand - /// - /// idx odl da chiudere - /// idx idxMaccSel - /// matricola operatore - /// indica se confermare i pezzi priam di chiudere ODL - public async Task ODLClose(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi) - { - using var activity = ActivitySource.StartActivity("ODLClose"); - string source = "DB"; - bool fatto = false; - // recupero dati x conf modalità conferma - var configData = await ConfigGetAllAsync(); - if (configData != null) - { - bool confRett = false; - var currRec = configData.FirstOrDefault(x => x.Chiave == "confRett"); - if (currRec != null) + // se supero la soglia loggo... + if (activity?.Duration.TotalMilliseconds > slowLogThresh) { - bool.TryParse(currRec.Valore, out confRett); + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); } - int modoConfProd = 0; - currRec = configData.FirstOrDefault(x => x.Chiave == "modoConfProd"); - if (currRec != null) + return result; + } + bool fromDb = false; + // cache in redis + var cacheOptions = new FusionCacheEntryOptions() + .SetDuration(expiration) + .SetFailSafe(true); + // cache in RAM per 1/3 del tempo x risparmiare risorse + cacheOptions.MemoryCacheDuration = expiration / 3; + + var final = await _cache.GetOrSetAsync( + cacheKey, + async _ => { - int.TryParse(currRec.Valore, out modoConfProd); - } - // chiamo metodo conferma! - fatto = await dbController.ODLClose(idxOdl, idxMacchina, matrOpr, confPezzi, confRett, modoConfProd); - } + fromDb = true; + return await fetchFunc(); + }, + options: cacheOptions, + tags: tagList + ); + + source = fromDb ? "DB" : "REDIS"; activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ODLClose | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return fatto; + // switch log in base a source.. + switch (source) + { + case "DB": + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms", reqLevel: NLog.LogLevel.Info); + break; + + case "REDIS": + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms", reqLevel: NLog.LogLevel.Debug); + break; + + default: + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + break; + } + return final!; } /// - /// Record ODL da chaive + /// Restituisce un timeout dal valore secondi richiesti + tempo random +/-3% /// + /// /// - public async Task OdlGetByKey(int IdxOdl) + private TimeSpan GetRandTOut(double durationSec) { - using var activity = ActivitySource.StartActivity("OdlGetByKey"); - string source = "DB"; - var dbResult = await dbController.OdlGetByKey(IdxOdl); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"OdlGetByKey | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return dbResult; + double noise = (rand.NextDouble() * 0.06) - 0.03; + double rValue = durationSec * (1 + noise); + return TimeSpan.FromSeconds(rValue); } /// - /// ODL correnti (tutti) + /// Helper trace messaggio log (SE abilitato) /// - /// - /// - public List OdlGetCurrent() + /// + private void LogTrace(string traceMsg, NLog.LogLevel? reqLevel = null) { - using var activity = ActivitySource.StartActivity("OdlGetCurrent"); - List? dbResult = new List(); - string source = "DB"; - string currKey = $"{Utils.redisOdlCurrByMac}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - dbResult = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - dbResult = dbController.OdlGetCurrent().Select(x => x.IdxMacchina).Distinct().ToList(); - rawData = JsonConvert.SerializeObject(dbResult); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(3)); - } - if (dbResult == null) - { - dbResult = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", dbResult.Count); - activity?.Stop(); - LogTrace($"OdlGetCurrent | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return dbResult; - } + if (!traceEnabled) + return; - /// - /// elenco TUTTI gli ODL - /// - /// - /// - public List OdlListAll() - { - using var activity = ActivitySource.StartActivity("OdlListAll"); - List? result = new List(); - string source = "DB"; - result = dbController.OdlListAll(); - activity?.SetTag("data.source", "DB"); - activity?.Stop(); - LogTrace($"OdlListAll | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } + reqLevel ??= NLog.LogLevel.Trace; - /// - /// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato) - /// - /// Stato ODL: true=in corso/completato - /// Cod articolo - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Reparto selezionato - /// Macchina selezionata - /// Data inizio - /// Data fine - /// - public async Task> OdlListGetFilt(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) - { - using var activity = ActivitySource.StartActivity("OdlListGetFilt"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisOdlList}:{inCorso}:{codArt}:{keyRichPart}:{Reparto}:{IdxMacchina}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ListODLFilt(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"OdlListGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco operatori filtrati x gruppo - /// - /// - /// - public List OperatoriGetFilt(string codGruppo) - { - using var activity = ActivitySource.StartActivity("OperatoriGetFilt"); - List? result = new List(); - string source = "DB"; - string keyGrp = codGruppo != "*" ? codGruppo : "ALL"; - string currKey = $"{Utils.redisOprList}:{keyGrp}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.OperatoriGetFilt(codGruppo); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"OperatoriGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); activity?.SetTag("data.source", source); - return result; - } - - /// - /// Elenco di tutti i parametri filtrati x idxMaccSel - /// - /// * = tutte, altrimenti solo x una data idxMaccSel - /// - public async Task> ParametriGetFilt(string IdxMacchina) - { - using var activity = ActivitySource.StartActivity("ParametriGetFilt"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisFluxByMac}:{IdxMacchina}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ParametriGetFilt(IdxMacchina)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ParametriGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Eliminazione record selezionato - /// - /// - /// - public async Task POdlDeleteRecord(PODLExpModel currRec) - { - using var activity = ActivitySource.StartActivity("POdlDeleteRecord"); - string source = "DB+REDIS"; - var dbResult = await dbController.PODLDeleteRecord(currRec); - // elimino cache redis... - await POdlFlushCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"POdlDeleteRecord | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return dbResult; - } - - /// - /// Avvio fase setup per il record selezionato - /// - /// - /// - public async Task POdlDoSetup(PODLExpModel currRec) - { - using var activity = ActivitySource.StartActivity("POdlDoSetup"); - string source = "DB+REDIS"; - var dbResult = await dbController.PODL_startSetup(currRec, 0, 1, 1, "", DateTime.Now); - // elimino cache redis... - await POdlFlushCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"POdlDoSetup | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return dbResult; - } - - /// - /// Recupero PODL da chiave - /// - /// - /// - public async Task POdlGetByKey(int idxPODL) - { - PODLModel result = new PODLModel(); - if (idxPODL != 0) - { - using var activity = ActivitySource.StartActivity("POdlGetByKey"); - string source = "DB"; - string currKey = $"{Utils.redisPOdlByPOdl}:{idxPODL}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - var rawResult = JsonConvert.DeserializeObject($"{rawData}"); - if (rawResult != null) - { - result = rawResult; - source = "REDIS"; - } - } - else - { - result = await dbController.PODL_getByKey(idxPODL); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new PODLModel(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", 1); - activity?.Stop(); - Log.Trace($"POdlGetByKey | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - } - else - { - Log.Debug("Errore IdxPODL = 0"); - } - return result; - } - - /// - /// Recupero PODL da IdxODL - /// - /// - /// - public PODLModel POdlGetByOdl(int idxODL) - { - PODLModel result = new PODLModel(); - if (idxODL != 0) - { - using var activity = ActivitySource.StartActivity("POdlGetByOdl"); - string source = "DB"; - string currKey = $"{Utils.redisPOdlByOdl}:{idxODL}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - var rawResult = JsonConvert.DeserializeObject($"{rawData}"); - if (rawResult != null) - { - result = rawResult; - } - source = "REDIS"; - } - else - { - result = dbController.PODL_getByOdl(idxODL); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new PODLModel(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", 1); - activity?.Stop(); - Log.Trace($"POdlGetByOdl | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - } - else - { - Log.Debug("Errore IdxODL = 0"); - } - return result; - } - - /// - /// Effettua il task di eliminazione PODL KIT + istanze + riattivazione PODL originali disattivate tramite stored - /// - /// IdxPODL parent - public bool PodlIstKitDelete(int IdxPODL) - { - using var activity = ActivitySource.StartActivity("PodlIstKitDelete"); - bool fatto = false; - // salvo - fatto = dbController.PodlIstKitDelete(IdxPODL); - // svuoto cache - string pattern = $"{Utils.redisKit}:*"; - if (!string.IsNullOrEmpty(pattern)) - { - ExecFlushRedisPattern(pattern); - } - activity?.SetTag("data.source", "DB+REDIS"); - return fatto; - } - - /// - /// Elenco PODL in un istanza KIT dall'ID del parent - /// - /// IDX PODL parent - /// - public List POdlListByKitParent(int IdxPodlParent) - { - using var activity = ActivitySource.StartActivity("POdlListByKitParent"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisPOdlList}_kit:ByParent:{IdxPodlParent}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.ListPODL_ByKitParent(IdxPodlParent); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"POdlListByKitParent | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato) - /// - /// Solo lanciati (1) o ancora disponibili (0) - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Macchina - /// Gruppo - /// Data inizio - /// Data fine - /// - public List POdlListGetFilt(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) - { - using var activity = ActivitySource.StartActivity("POdlListGetFiltAsync"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisPOdlList}:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.ListPODLFilt(lanciato, keyRichPart, idxMacchina, codGruppo, startDate, endDate); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"POdlListGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco PODL (Async) non avviati filtrati x articolo, KeyRich (che contiene stato) - /// - /// Solo lanciati (1) o ancora disponibili (0) - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Macchina - /// Gruppo - /// Data inizio - /// Data fine - /// - public async Task> POdlListGetFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) - { - using var activity = ActivitySource.StartActivity("POdlListGetFiltAsync"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisPOdlList}:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ListPODLFilt(lanciato, keyRichPart, idxMacchina, codGruppo, startDate, endDate)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"POdlListGetFiltAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elenco PODL per composizione KIT (Async) non avviati filtrati x articolo, KeyRich (che contiene stato) - /// - /// Solo lanciati (1) o ancora disponibili (0) - /// KeyRich (parziale) da cercare (es cod stato x yacht) - /// Macchina - /// Gruppo - /// Data inizio - /// Data fine - /// - public async Task> POdlToKitListGetFiltAsync(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) - { - using var activity = ActivitySource.StartActivity("POdlToKitListGetFiltAsync"); - List? result = new List(); - string source = "DB"; - string currKey = $"{Utils.redisPOdlList}_kit:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ListPODL_KitFilt(lanciato, keyRichPart, idxMacchina, codGruppo, startDate, endDate)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"POdlToKitListGetFiltAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Chiamata salvataggio ricetta + refresh REDIS - /// - /// - /// - /// - public async Task POdlUpdateRecipe(int idxPODL, string recipeName) - { - using var activity = ActivitySource.StartActivity("POdlUpdateRecipe"); - string source = "DB+REDIS"; - bool answ = false; - answ = await dbController.PODL_updateRecipe(idxPODL, recipeName); - // reset redis... - if (answ) - { - await POdlFlushCache(); - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"POdlUpdateRecipe | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; - } - - /// - /// Aggiornamento record selezionato - /// - /// - /// - public async Task POdlUpdateRecord(PODLModel currRec) - { - using var activity = ActivitySource.StartActivity("POdlUpdateRecord"); - string source = "DB+REDIS"; - var dbResult = await dbController.PODLUpdateRecord(currRec); - // elimino cache redis... - await POdlFlushCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"POdlUpdateRecord | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return dbResult; - } - - /// - /// Restituisce le statistiche di processo correnti x depluplica FluxLog - /// - /// - public List ProcFLStats() - { - using var activity = ActivitySource.StartActivity("ProcFLStats"); - string source = "REDIS"; - List actStats = new List(); - string currKey = $"{Utils.redisStatsProcFL}"; - // recupero i record statistiche correnti - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - var rawStats = JsonConvert.DeserializeObject>($"{rawData}"); - if (rawStats != null) - { - actStats = rawStats; - } - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ProcFLStats | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return actStats; - } - - /// - /// Ricerca ricetta su MongoDB dato PODL - /// - /// - /// - public async Task RecipeGetByPODL(int idxPODL) - { - RecipeModel? result = null; - using var activity = ActivitySource.StartActivity("RecipeGetByPODL"); - string source = "MongoDB"; - result = await mongoController.RecipeGetByPODL(idxPODL); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"RecipeGetByPODL | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Salva ricetta su MongoDB - /// - /// - /// - public async Task RecipeSetByPODL(RecipeModel currRecord) - { - using var activity = ActivitySource.StartActivity("RecipeSetByPODL"); - string source = "DB+REDIS"; - bool answ = false; - answ = await mongoController.RecipeSetByPODL(currRecord); - if (answ) - { - await POdlFlushCache(); - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"RecipeSetByPODL | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; - } - - /// - /// Effettua conteggio chaivi REDIS dato pat2Flush ricerca - /// - /// - /// - public int RedisCountKey(string keyPattern) - { - using var activity = ActivitySource.StartActivity("RedisCountKey"); - string source = "REDIS"; - int num = 0; - keyPattern = (string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern); - try - { - var listEndpoints = redisConnAdmin.GetEndPoints(); - foreach (var endPoint in listEndpoints) - { - var server = redisConnAdmin.GetServer(endPoint); - foreach (RedisKey item in server.Keys(pattern: keyPattern, database: redisDb.Database, pageSize: 250, cursor: 0L)) - { - num++; - } - } - } - catch (Exception arg) - { - Log.Error($"Eccezione in RedisCountKey{Environment.NewLine}{arg}"); - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"RedisCountKey | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return num; - } - - /// - /// Esegue eliminazione memoria redis keyVal - /// - /// - /// - public bool RedisDelKey(string keyVal) - { - using var activity = ActivitySource.StartActivity("RedisDelKey"); - string source = "REDIS"; - bool answ = false; - var listEndpoints = redisConnAdmin.GetEndPoints(); - foreach (var endPoint in listEndpoints) - { - var server = redisConnAdmin.GetServer(endPoint); - if (server != null) - { - redisDb.KeyDelete((RedisKey)keyVal); - answ = true; - } - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"RedisDelKey | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; - } - - /// - /// Reset della cache IO post operazioni come setup ODL... - /// - /// Indirizzo base da cui rimuovere memoria cache - /// - public async Task ResetIoCache(string baseMem) - { - using var activity = ActivitySource.StartActivity("ResetIoCache"); - string source = "REDIS"; - // patterna a partire da cache IO... - RedisValue pattern = new RedisValue($"{MpIoNS}:*"); - if (!string.IsNullOrEmpty(baseMem)) - { - pattern = new RedisValue($"{MpIoNS}:{baseMem}:*"); - } - bool answ = await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ResetIoCache | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return answ; - } - - /// - /// Effettua reset microstato macchina - /// - /// - public async Task ResetMicrostatoMacchina(string idxMacchina) - { - using var activity = ActivitySource.StartActivity("ResetMicrostatoMacchina"); - string source = "DB"; - // salvo microstato 0... - MicroStatoMacchinaModel newRecMS = new MicroStatoMacchinaModel() - { - IdxMacchina = idxMacchina, - InizioStato = DateTime.Now, - IdxMicroStato = 0, - Value = "FER" - }; - var result = await dbController.MicroStatoMacchinaUpsert(newRecMS); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"ResetMicrostatoMacchina | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - } - - /// - /// Stato macchina - /// - /// - /// - public StatoMacchineModel StatoMacchina(string idxMacchina) - { - using var activity = ActivitySource.StartActivity("StatoMacchina"); - // setup parametri costanti - string source = "DB"; - StatoMacchineModel? result = new StatoMacchineModel(); - // cerco in redisConn... - string currKey = $"{Utils.redisStatoMacch}:{idxMacchina}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.StatoMacchina(idxMacchina); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(1)); - } - if (result == null) - { - result = new StatoMacchineModel(); - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"StatoMacchina | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Statistiche ODL calcolate (da stored stp_STAT_ODL) - /// - /// - public Task> StatOdl(int IdxOdl) - { - using var activity = ActivitySource.StartActivity("StatOdl"); - string source = "DB"; - var result = dbController.OdlStart(IdxOdl); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"StatOdl | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Restituisce il valore da REDIS associato al tag richiesto - /// - /// Chiave in cui cercare il valore - /// - public string TagConfGetKey(string redKey) - { - string outVal = ""; - using var activity = ActivitySource.StartActivity("TagConfGetKey"); - string source = "REDIS"; - // cerco in REDIS la conf x l'IOB - var rawData = redisDb.StringGet(redKey); - if (!string.IsNullOrEmpty(rawData)) - { - outVal = $"{rawData}"; - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"TagConfGetKey | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return outVal; - } - - /// - /// Elenco setup dei tag conf correnti - /// - /// - public Dictionary> TagsGetAll() - { - return currTagConf; - } - - /// - /// Elimina record + svuotamento cache - /// - /// - public async Task TemplateKitDelete(TemplateKitModel currRecord) - { - using var activity = ActivitySource.StartActivity("TemplateKitDelete"); - string source = "DB+REDIS"; - bool fatto = false; - // salvo - fatto = dbController.TemplateKitDelete(currRecord); - // svuoto cache - RedisValue pattern = $"{Utils.redisKitTempl}:*"; - await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"TemplateKitDelete | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Elenco Template KIT da ricerca - /// - /// - /// - /// - public List TemplateKitFilt(string codParent, string codChild) - { - using var activity = ActivitySource.StartActivity("TemplateKitFilt"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - string currKey = $"{Utils.redisKitTempl}:{codParent}:{codChild}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.TemplateKitFilt(codParent, codChild); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromMinutes(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"TemplateKitFilt | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Esegue salvataggio record + svuotamento cache - /// - /// - /// - public async Task TemplateKitUpsert(TemplateKitModel currRecord, string codAzienda) - { - using var activity = ActivitySource.StartActivity("TemplateKitUpsert"); - string source = "DB+REDIS"; - bool fatto = false; - // salvo - fatto = dbController.TemplateKitUpsert(currRecord, codAzienda); - // svuoto cache - RedisValue pattern = $"{Utils.redisKitTempl}:*"; - await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"TemplateKitUpsert | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Punteggio compatibilità KIT per KeyFilt indicato - /// - /// - /// - /// - /// - public List TksScore(string KeyFilt, int MaxResult, bool ForceDb) - { - using var activity = ActivitySource.StartActivity("TksScore"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - string currKey = $"{Utils.redisKitScore}:{KeyFilt}:{MaxResult}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue && !ForceDb) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.TksScore(KeyFilt, MaxResult); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromMinutes(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"TksScore | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Esegue traduzione dato vocabolario da Lingua + Lemma - /// - /// - /// - /// - public string Traduci(string lemma, string lingua) - { - string answ = $"[{lemma}]"; - // verifico se ho qualcosa nell'obj vocabolario... - if (ObjVocabolario == null || ObjVocabolario.Count == 0) - { - // inizializzo il vocabolario... - ObjVocabolario = VocabolarioGetAll(); - } - var record = ObjVocabolario.Where(x => x.Lingua == lingua && x.Lemma == lemma).FirstOrDefault(); - if (record != null) - { - answ = record.Traduzione; - } - return answ; - } - - /// - /// Update valore Dossier - /// - /// - /// - /// - public async Task updateDossierValue(DossierModel currDoss, FluxLogDTO editFL) - { - using var activity = ActivitySource.StartActivity("updateDossierValue"); - string source = "DB"; - bool answ = false; - // recupero intero set valori dossier deserializzando... - var fluxLogList = FluxLogDtoGetByFlux(currDoss.Valore); - // se tutto ok - if (fluxLogList != null) - { - // da provare...!!!! - - // elimino vecchio record - var currRec = fluxLogList.FirstOrDefault(x => x.CodFlux == editFL.CodFlux && x.dtEvento == editFL.dtEvento); - if (currRec != null) - { - fluxLogList.Remove(currRec); - // aggiungo nuovo - fluxLogList.Add(editFL); - } - - // serializzo nuovamente valore - DossierFluxLogDTO? result = new DossierFluxLogDTO(); - var ODLflux = result.ODL.ToList(); - foreach (var item in fluxLogList) - { - ODLflux.Add(item); - } - - DossierFluxLogDTO updatedResult = new DossierFluxLogDTO() { ODL = ODLflux }; - - string rawVal = JsonConvert.SerializeObject(updatedResult); - currDoss.Valore = rawVal; - // aggiorno record sul DB - await dbController.DossiersUpdateValore(currDoss); - } - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"updateDossierValue | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return answ; - } - - /// - /// Elenco completo tabella Vocabolario - /// - /// - public List VocabolarioGetAll() - { - List? result = new List(); - using var activity = ActivitySource.StartActivity("VocabolarioGetAll"); - string source = "REDIS"; - // cerco in redis... - RedisValue rawData = redisDb.StringGet(Utils.redisVocabolario); - if (!string.IsNullOrEmpty($"{rawData}")) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - } - else - { - result = dbController.VocabolarioGetAll(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(Utils.redisVocabolario, rawData, getRandTOut(redisLongTimeCache / 5)); - source = "DB"; - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"VocabolarioGetAll Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Elimina record + svuotamento cache - /// - /// - public bool WipKitDelete(WipSetupKitModel currRecord) - { - using var activity = ActivitySource.StartActivity("WipKitDelete"); - string source = "DB"; - bool fatto = false; - // salvo - fatto = dbController.WipKitDelete(currRecord); - // svuoto cache - EmptyWipCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"WipKitDelete Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Elimina i record associati al keyFilt indicato - /// - /// - public bool WipKitDeleteGroup(string KeyFilt) - { - using var activity = ActivitySource.StartActivity("WipKitDeleteGroup"); - string source = "DB"; - bool fatto = false; - // salvo - fatto = dbController.WipKitDeleteGroup(KeyFilt); - // svuoto cache - EmptyWipCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"WipKitDeleteGroup Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Elimina i record più vecchi della data-ora indicata - /// - /// - public bool WipKitDeleteOlder(DateTime DateLimit) - { - using var activity = ActivitySource.StartActivity("WipKitDeleteOlder"); - string source = "DB"; - bool fatto = false; - // salvo - fatto = dbController.WipKitDeleteOlder(DateLimit); - // svuoto cache - EmptyWipCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"WipKitDeleteOlder Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - /// - /// Elenco Template KIT da ricerca - /// - /// - /// - public List WipKitFilt(string KeyFilt) - { - using var activity = ActivitySource.StartActivity("WipKitFilt"); - string source = "DB"; - List? result = new List(); - // cerco in redis... - string currKey = $"{Utils.redisKitWip}:{KeyFilt}"; - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = dbController.WipKitFilt(KeyFilt); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromMinutes(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"WipKitFilt | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; - } - - /// - /// Esegue salvataggio record + svuotamento cache - /// - /// - public bool WipKitUpsert(WipSetupKitModel currRecord) - { - using var activity = ActivitySource.StartActivity("WipKitUpsert"); - string source = "DB"; - bool fatto = false; - // salvo - fatto = dbController.WipKitUpsert(currRecord); - // svuoto cache KitWip - EmptyWipCache(); - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"WipKitUpsert | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return fatto; - } - - #endregion Public Methods - - #region Protected Fields - - protected Random rand = new Random(); - - #endregion Protected Fields - - #region Protected Properties - - protected string canCacheParametri { get; set; } = ""; - - #endregion Protected Properties - - #region Protected Methods - - /// - /// Restituisce un timeout dai minuti richiesti + tempo random -15..+15 sec - /// - /// - /// - protected TimeSpan getRandTOut(double stdMinutes) - { - double rndValue = stdMinutes + (double)rand.Next(-15, 15) / 60; - return TimeSpan.FromMinutes(rndValue); + // Loggo! + Log.Log(reqLevel, traceMsg); } /// @@ -3175,10 +2398,9 @@ namespace MP.SPEC.Data /// /// /// - protected bool ProcDedupStatMerge(List procStats) + private async Task ProcDedupStatMergeAsync(List procStats) { - bool answ = false; - List actStats = ProcFLStats(); + List actStats = await ProcFLStatsAsync(); // se fosse vuoto --> add diretto if (actStats.Count == 0) { @@ -3210,8 +2432,7 @@ namespace MP.SPEC.Data // salvo record statistiche var rawData = JsonConvert.SerializeObject(actStats); string currKey = $"{Utils.redisStatsProcFL}"; - redisDb.StringSet(currKey, rawData); - return answ; + return await redisDb.StringSetAsync(currKey, rawData); } /// @@ -3219,100 +2440,18 @@ namespace MP.SPEC.Data /// /// /// - protected bool RecDbMaintStat(TimeSpan duration) + private async Task RecDbMaintStatAsync(TimeSpan duration) { - bool answ = false; - Dictionary actStats = DbDedupStats(); + Dictionary actStats = await DbDedupStatsAsync(); // aggiungo record! actStats.Add(DateTime.Now, duration.TotalSeconds); // salvo NUOVO record statistiche string currKey = $"{Utils.redisStatsDbMaint}"; var rawData = JsonConvert.SerializeObject(actStats); - redisDb.StringSet(currKey, rawData); - return answ; + return await redisDb.StringSetAsync(currKey, rawData); } - #endregion Protected Methods - - #region Private Fields - - /// - /// Oggetto per collezione dati Activity (span in Uptrace) - /// - private static readonly ActivitySource ActivitySource = new ActivitySource("MP.DATA.Tracer"); - - private static IConfiguration _configuration = null!; - - private static Logger Log = LogManager.GetCurrentClassLogger(); - - private string MpIoNS = ""; - - /// - /// Oggetto vocabolario x uso continuo traduzione - /// - private List ObjVocabolario = new List(); - - /// - /// Oggetto per connessione a REDIS - /// - private ConnectionMultiplexer redisConn = null!; - - /// - /// Oggetto per connessione a REDIS modalità admin (ex flux dati) - /// - private ConnectionMultiplexer redisConnAdmin = null!; - - /// - /// Oggetto DB redis da impiegare x chiamate R/W - /// - private IDatabase redisDb = null!; - - private int redisLongTimeCache = 5; - - private int redisShortTimeCache = 2; - - #endregion Private Fields - - #region Private Properties - - /// - /// Cache dati config - /// - private List configData { get; set; } = new List(); - - #endregion Private Properties - - #region Private Methods - - /// - /// Svuota cache creazione KIT - /// - private void EmptyWipCache() - { - string pattern = $"{Utils.redisKitWip}:*"; - if (!string.IsNullOrEmpty(pattern)) - { - ExecFlushRedisPattern(pattern); - } - } - - private async Task POdlFlushCache() - { - using var activity = ActivitySource.StartActivity("POdlFlushCache"); - bool answ = false; - RedisValue pattern = new RedisValue($"{Utils.redisXdlData}:*"); - answ = await ExecFlushRedisPatternAsync(pattern); - pattern = new RedisValue($"{Utils.redisPOdlByOdl}:*"); - answ = await ExecFlushRedisPatternAsync(pattern); - pattern = new RedisValue($"{Utils.redisPOdlByPOdl}:*"); - answ = await ExecFlushRedisPatternAsync(pattern); - pattern = new RedisValue($"{Utils.redisPOdlList}:*"); - answ = await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", "REDIS"); - return answ; - } - - private string redHashMpIO(string keyName) + private string RedHashMpIO(string keyName) { string result = keyName; try @@ -3321,40 +2460,12 @@ namespace MP.SPEC.Data } catch (Exception exc) { - Log.Error($"Errore in redHashMpIO{Environment.NewLine}{exc}"); + Log.Error($"Errore in RedHashMpIO{Environment.NewLine}{exc}"); } return result; } - private async Task resetCacheArticoli() - { - using var activity = ActivitySource.StartActivity("resetCacheArticoli"); - RedisValue pattern = new RedisValue($"{Utils.redisArtByDossier}:*"); - await ExecFlushRedisPatternAsync(pattern); - pattern = new RedisValue($"{Utils.redisArtList}:*"); - await ExecFlushRedisPatternAsync(pattern); - activity?.SetTag("data.source", "REDIS"); - } - - /// - /// Reset macchine e gruppi - /// - private void ResetMacGrpCache() - { - ExecFlushRedisPattern($"{Utils.redisAnagGruppi}:*"); - ExecFlushRedisPattern($"{Utils.redisMacList}:*"); - } - - /// - /// Reset cache operatori e gruppi - /// - private void ResetOprGrpCache() - { - ExecFlushRedisPattern($"{Utils.redisAnagGruppi}:*"); - ExecFlushRedisPattern($"{Utils.redisOprList}:*"); - } - #endregion Private Methods } } \ No newline at end of file diff --git a/MP.SPEC/Data/Refactor_Plan.md b/MP.SPEC/Data/Refactor_Plan.md new file mode 100644 index 00000000..1aa90a24 --- /dev/null +++ b/MP.SPEC/Data/Refactor_Plan.md @@ -0,0 +1,108 @@ +# Piano di Refactoring: Migrazione a FusionCache in `MpDataService.cs` + +Stiamo lavorando sul progetto MP-SPEC.sln, dentro la cartella MP-SPEC (ed i progetti da cui dipende). + +Voglio ottimizzare il file Data\MpDataService.cs + +## Obiettivo +Migrare la logica di caching manuale (Redis + DB) verso l'utilizzo di `IFusionCache` per implementare un approccio multi-layer (Memory + Redis + DB), standardizzando l'accesso ai dati. + +## Strategia di Migrazione +- **Metodo Standard**: `GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tagList)`. +- **Invalidazione**: Utilizzare i tag tramite `FlushFusionCacheByTagAsync`. + +## Stato Avanzamento + +### Fase 1: Analisi e Mapping (Completata) +- Analisi di `MpDataService.cs` effettuata. +- Identificati i metodi con caching manuale (Redis/DB) e quelli già migrati a `GetOrFetchAsync`. + +### Fase 2: Refactoring Metodi di Lettura (Cache-aside) (Completata) + +#### ✅ Metodi Migrati o Confermati (Pattern corretto per l'uso previsto) +- `AnagEventiGeneralAsync` +- `AnagStatiCommAsync` +- `AnagTipoArtLvAsync` +- `ArticleWithDossierAsync` +- `ArticoliCountAsync` +- `ArticoliCountSearchAsync` +- `ArticoliGetByTipoAsync` +- `ArticoliGetSearchAsync` +- `ArticoliInKitAsync` +- `ConfigGetAllAsync` +- `DossiersGetLastFiltAsync` +- `ElencoAziendeAsync` +- `ElencoGruppiFaseAsync` +- `ElencoLinkAsync` +- `IstKitFiltAsync` +- `ListGiacenzeAsync` +- `MacchineGetFiltAsync` +- `MacchineRecipeArchiveAsync` +- `MacchineRecipeConfAsync` +- `MacchineWithFluxAsync` +- `MachineWithOdlAsync` +- `MachIobConfAsync` +- `OdlByBatchAsync` (Migrato e rinominato) +- `OdlListGetFiltAsync` +- `OperatoriGetFiltAsync` +- `ParametriGetFiltAsync` +- `PODL_getDictOdlPodlAsync` (Gestione manuale L1/L2 con FusionCache) +- `POdlGetByOdlAsync` +- `POdlToKitListGetFiltAsync` +- `StatoMacchinaAsync` +- `TksScoreAsync` +- `Traduci` (Migrato con `GetOrSet` su dizionario lingua) +- `WipKitFiltAsync` +- `MseGetAllAsync` (Migrato e rinominato) +- `OdlByKeyAsync` (Migrato e rinominato) +- `TemplateKitDeleteAsync` (Migrato con tag invalidazione) +- `TemplateKitUpsertAsync` (Migrato con tag invalidazione) +- `WipKitDeleteAsync` (Migrato con tag invalidazione) +- `WipKitUpsertAsync` (Migrato con tag invalidazione) +- `AnagGruppiDeleteAsync` (Migrato con tag invalidazione) +- `AnagGruppiUpsertAsync` (Migrato con tag invalidazione) +- `Grp2MaccDeleteAsync` (Migrato con tag invalidazione) +- `Grp2MaccInsertAsync` (Migrato con tag invalidazione) +- `Grp2OperDeleteAsync` (Migrato con tag invalidazione) +- `Grp2OperInsertAsync` (Migrato con tag invalidazione) +- `ArticoliDeleteRecord` (Migrato con `FlushCacheArticoli`) +- `ArticoliUpdateRecord` (Migrato con `FlushCacheArticoli`) +- `DossiersDeleteRecordAsync` (Migrato con tag invalidazione) +- `DossiersTakeParamsSnapshotLast` (Migrato con tag invalidazione) +- `DossiersInsert` (Migrato con tag invalidazione) +- `DossiersUpdateValoreAsync` (Migrato con tag invalidazione) +- `ElencoRepartiDTO` (Migrato) +- `PodlIstKitDeleteAsync` (Migrato con tag invalidazione) +- `POdlUpdateRecipe` (Migrato con tag invalidazione) +- `POdlUpdateRecord` (Migrato con tag invalidazione) +- `POdlGetByKey` (Migrato con FusionCache) +- `POdlListByKitParentAsync` (Migrato con FusionCache) +- `ActionGetReq` (Pattern Redis/Channels corretto) +- `ActionSetReq` (Pattern Redis/Channels corretto) +- `DbDedupStatsAsync` (Pattern Redis persistente corretto) +- `ProcFLStats` (Pattern Redis persistente corretto) +- `RecDbMaintStatAsync` (Pattern Redis persistente corretto) + +#### 🛠️ Metodi da Migrare (Nessuno) +- *Nessun metodo residuo richiede migrazione a FusionCache.* + +### Fase 4: Verifica (Completata) +- [x] Verificare la compilazione della soluzione tramite script PowerShell. +- [x] Controllare che i log (NLog) continuano a riflettere correttamente le operazioni. +- [x] Verifica coerenza signature (async/task/sync). + +## Rischi e Mitigazioni +- **Rischio**: Discrepanza nelle chiavi di cache tra vecchio e nuovo sistema. + - *Mitigazione*: Utilizzare rigorosamente le costanti in `Utils.redis...` per garantire che le chiavi siano identiche o gestite dal nuovo sistema. +- **Rischio**: Errori di serializzazione. + - *Mitigazione*: `FusionCache` gestisce la serializzazione, ma è necessario assicurarsi che i tipi di ritorno siano compatibili con le aspettative dei chiamanti. + + + + + + + + + + diff --git a/MP.SPEC/Data/Refactor_Plan.pdf b/MP.SPEC/Data/Refactor_Plan.pdf new file mode 100644 index 00000000..18fab5be Binary files /dev/null and b/MP.SPEC/Data/Refactor_Plan.pdf differ diff --git a/MP.SPEC/Data/SelectXdlParams.cs b/MP.SPEC/Data/SelectXdlParams.cs index e91ae7c9..f36c3402 100644 --- a/MP.SPEC/Data/SelectXdlParams.cs +++ b/MP.SPEC/Data/SelectXdlParams.cs @@ -26,6 +26,7 @@ namespace MP.SPEC.Data public string SearchVal { get; set; } = "*"; public string Header { get; set; } = ""; public int TotCount { get; set; } = 0; + public bool ShowKit { get; set; } = false; #endregion Public Properties diff --git a/MP.SPEC/Extensions/NavigationManagerExtension.cs b/MP.SPEC/Extensions/NavigationManagerExtension.cs index 9383180a..5e3e5780 100644 --- a/MP.SPEC/Extensions/NavigationManagerExtension.cs +++ b/MP.SPEC/Extensions/NavigationManagerExtension.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.WebUtilities; +using System.ComponentModel; namespace MP.SPEC.Extensions { @@ -8,7 +9,7 @@ namespace MP.SPEC.Extensions #region Public Methods /// - /// Estensione metodo NavigationManager x recupero querystring + /// Estensione metodo NavigationManager x recupero querystring int/string /// /// https://code-maze.com/query-strings-blazor-webassembly/ /// @@ -16,7 +17,7 @@ namespace MP.SPEC.Extensions /// /// /// - public static T ExtractQueryStringByKey(this NavigationManager navManager, string key) + public static T? ExtractQueryStringByKey(this NavigationManager navManager, string key) { var uri = navManager.ToAbsoluteUri(navManager.Uri); QueryHelpers.ParseQuery(uri.Query) @@ -34,6 +35,46 @@ namespace MP.SPEC.Extensions return default; } + /// + /// Estensione metodo NavigationManager x recupero querystring di ogni tipo + /// + /// es: navManager.ExtractQueryStringByKey("isAdmin") + /// + /// + /// + /// + /// + public static T? ExtractQueryStringByKeyGeneric(this NavigationManager navManager, string key) + { + var uri = navManager.ToAbsoluteUri(navManager.Uri); + + // Estrai il valore associato alla chiave + if (!QueryHelpers.ParseQuery(uri.Query).TryGetValue(key, out var queryValue)) + { + return default; + } + + var stringValue = queryValue.ToString(); + + try + { + // Ottieni il convertitore dinamico per il tipo T + var converter = TypeDescriptor.GetConverter(typeof(T)); + if (converter != null && converter.CanConvertFrom(typeof(string))) + { + return (T?)converter.ConvertFromString(stringValue); + } + + // Fallback nel caso il convertitore standard non basti + return (T?)Convert.ChangeType(stringValue, typeof(T)); + } + catch + { + // Se la conversione fallisce (es. il testo non è un numero valido), ritorna il default + return default; + } + } + /// /// Recupero base page /// diff --git a/MP.SPEC/MP.SPEC.csproj b/MP.SPEC/MP.SPEC.csproj index 72831ad8..5037cd5c 100644 --- a/MP.SPEC/MP.SPEC.csproj +++ b/MP.SPEC/MP.SPEC.csproj @@ -5,7 +5,7 @@ enable enable MP.SPEC - 8.16.2604.2718 + 8.16.2606.409 1800a78a-6ff1-40f9-b490-87fb8bfc1394 en @@ -42,6 +42,7 @@ + @@ -52,6 +53,9 @@ + + + diff --git a/MP.SPEC/Pages/Articoli.razor b/MP.SPEC/Pages/Articoli.razor index 2130edd8..f50e61eb 100644 --- a/MP.SPEC/Pages/Articoli.razor +++ b/MP.SPEC/Pages/Articoli.razor @@ -12,17 +12,33 @@

    Articoli

    - + @if (CanAdd) + { + + }
    -
    -
    +
    +
    + + - - + + + + - @if (ListAziende != null) { foreach (var item in ListAziende) @@ -31,6 +47,7 @@ } } + #: @availRecord
    @@ -45,11 +62,11 @@
    Codice - @if(isNewArt) + @if (isNewArt) { } - else + else { } @@ -81,15 +98,38 @@
    Tipo - + @if (ListTipoArt != null) { - + foreach (var item in ListTipoArt) + { + + } } - } - + + } + else + { + + } +
    @@ -100,12 +140,12 @@
    - +
    - +
    @@ -118,7 +158,7 @@
    - @if (ListRecords == null) + @if (ListRecords == null || isLoading) { } @@ -150,10 +190,17 @@
    @foreach (var record in ListRecords) { - +
    Matr. Anagr.
    -
    @record.MatrOpr
    +
    -
    @record.Cognome @record.Nome
    +
    +
    @item.MatrOpr
    - + +
    @item.Cognome @item.Nome
    + + + @if (item.isEnabled) + { + + } + else + { + + } +
    - @if(EditRec==null) + @if (EditEnabled) { - - } - else - { - - } - @if (SelRecord == null) - { - + if (EditRec == null) + { + + } + else + { + + } + if (SelRecord == null) + { + + } } @record.CountMacc @record.CountOpr - @if (DelEnabled(record)) + @if (EditEnabled) { - - } - else - { - + if (DelEnabled(record)) + { + + } + else + { + + } }
    - - + + @if (record.Tipo.Equals("KIT")) + { + + } + else + { + + }
    @record.CodArticolo
    @@ -169,7 +216,7 @@
    @record.Azienda - @if (ArticoloDelEnabled(record.CodArticolo)) + @if (ArticoloDelEnabled(record)) { } @@ -189,7 +236,7 @@ \ No newline at end of file diff --git a/MP.SPEC/Pages/Articoli.razor.cs b/MP.SPEC/Pages/Articoli.razor.cs index 754d6211..47ac03bc 100644 --- a/MP.SPEC/Pages/Articoli.razor.cs +++ b/MP.SPEC/Pages/Articoli.razor.cs @@ -9,23 +9,13 @@ namespace MP.SPEC.Pages { #region Public Methods - public string checkSelect(string CodArticolo) + public string CheckSelect(string codArticolo) { - string answ = ""; - if (currRecord != null) - { - try - { - answ = (currRecord.CodArticolo == CodArticolo) ? "table-info" : ""; - } - catch - { } - } - return answ; + return currRecord?.CodArticolo == codArticolo + ? "table-info" + : ""; } - private SelectArticoliParams currFilter = new SelectArticoliParams(); - public void Dispose() { currRecord = null; @@ -36,16 +26,6 @@ namespace MP.SPEC.Pages GC.Collect(); } - public async void OnSeachUpdated() - { - await InvokeAsync(() => - { - currPage = 1; - Task task = UpdateData(); - StateHasChanged(); - }); - } - #endregion Public Methods #region Protected Properties @@ -59,55 +39,7 @@ namespace MP.SPEC.Pages [Inject] protected NavigationManager NavManager { get; set; } = null!; - protected int totalCount - { - get - { - int answ = 0; - if (SearchRecords != null) - { - answ = SearchRecords.Count; - } - return answ; - } - } - - #endregion Protected Properties - - #region Protected Methods - - private bool isNewArt = false; - - /// - /// Crea nuovo record e va in editing... - /// - /// - protected async Task addNew() - { - isNewArt = true; - currRecord = new AnagArticoliModel() - { - CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}", - DescArticolo = "Nuovo articolo", - Azienda = selAzienda != "*" ? selAzienda : "MAPO", - Disegno = "", - Tipo = "ART", - CurrRev = "", - ProdRev = "" - }; - await Task.Delay(1); - } - - protected async Task resetSearch() - { - SearchVal = ""; - await ReloadData(); - } - - protected string searchCss - { - get => string.IsNullOrEmpty(searchVal) ? "btn-secondary" : "btn-primary"; - } + private string searchCss => string.IsNullOrEmpty(searchVal) ? "btn-secondary" : "btn-primary"; protected string SearchVal { @@ -117,29 +49,55 @@ namespace MP.SPEC.Pages // salvo solo se 3+ chars if (value.Length > 2 || string.IsNullOrEmpty(value)) { - if (searchVal != value) - { - searchVal = value; - var pUpd = Task.Run(async () => - { - ListRecords = null; - await Task.Delay(1); - await ReloadData(); - }); - pUpd.Wait(); - } + searchVal = value; } } } - private string searchVal { get; set; } = ""; - private string chkDisabled => isNewArt ? "" : "disabled"; + protected int totalCount = 0; - protected async Task cancel() + #endregion Protected Properties + + #region Protected Methods + + /// + /// Crea nuovo record e va in editing... + /// + /// + protected void AddNew() { - currRecord = null; - await ReloadData(); - await Task.Delay(1); + isNewArt = true; + currRecord = new AnagArticoliModel() + { + CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}", + DescArticolo = "Nuovo articolo", + Azienda = !selAzienda.Equals("*") ? selAzienda : "MAPO", + Disegno = "", + Tipo = !selTipoArt.Equals("*") ? selTipoArt : "ART", + CurrRev = "", + ProdRev = "" + }; + } + + /// + /// Cloning record + /// + /// + protected void cloneRecord(AnagArticoliModel selRec) + { + isNewArt = true; + // creo record duplicato... + AnagArticoliModel newRec = new AnagArticoliModel() + { + Azienda = selRec.Azienda, + CodArticolo = $"clone-{selRec.CodArticolo}", + DescArticolo = $"CLONE - {selRec.DescArticolo}", + Disegno = selRec.Disegno, + Tipo = selRec.Tipo, + CurrRev = "", + ProdRev = "" + }; + currRecord = newRec; } /// @@ -154,7 +112,7 @@ namespace MP.SPEC.Pages await Task.Delay(1); var done = await MDService.ArticoliDeleteRecord(selRec); currRecord = null; - await ReloadData(); + await ReloadDataAsync(); await Task.Delay(1); } @@ -171,26 +129,12 @@ namespace MP.SPEC.Pages protected override async Task OnInitializedAsync() { numRecord = 10; -#if false - configData = await MDService.ConfigGetAll(); - var currRec = configData.FirstOrDefault(x => x.Chiave == "AZIENDA"); - if (currRec != null) - { - selAzienda = currRec.Valore; - } -#endif - selAzienda = await MDService.ConfigTryGetAsync("AZIENDA"); - if (string.IsNullOrEmpty(selAzienda)) - { - selAzienda = "*"; - } - ListAziende = MDService.ElencoAziende(); - ListTipoArt = await MDService.AnagTipoArtLV(); + await ReloadBaseData(); } protected override async Task OnParametersSetAsync() { - await ReloadData(); + await ReloadDataAsync(); } protected void ResetData() @@ -199,6 +143,12 @@ namespace MP.SPEC.Pages currRecord = null; } + protected async Task ResetSearch() + { + SearchVal = ""; + await ResetDataAsync(); + } + protected async Task resetSel() { isNewArt = false; @@ -212,40 +162,21 @@ namespace MP.SPEC.Pages currRecord = selRec; await Task.Delay(1); } - protected async Task cloneRecord(AnagArticoliModel selRec) - { - isNewArt = true; - // creo record duplicato... - AnagArticoliModel newRec = new AnagArticoliModel() - { - Azienda = selRec.Azienda, - CodArticolo = $"clone-{selRec.CodArticolo}", - DescArticolo = $"CLONE - {selRec.DescArticolo}", - Disegno = selRec.Disegno, - Tipo = selRec.Tipo, - CurrRev = "", - ProdRev = "" - }; - currRecord = newRec; - await Task.Delay(1); - } - - protected async Task update(AnagArticoliModel selRec) + protected async Task UpdateAsync(AnagArticoliModel selRec) { if (!await JSRuntime.InvokeAsync("confirm", "Confermi di voler salvare le modifiche?")) return; - await Task.Delay(1); + var done = await MDService.ArticoliUpdateRecord(selRec); - currRecord = null; - await ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } - protected async Task UpdateData() + protected async Task ResetDataAsync() { + currPage = 1; currRecord = null; - await ReloadData(); + await ReloadDataAsync(); } #endregion Protected Methods @@ -253,18 +184,23 @@ namespace MP.SPEC.Pages #region Private Fields private string _selAzienda = "*"; + private SelectArticoliParams currFilter = new SelectArticoliParams(); private AnagArticoliModel? currRecord = null; + private bool isNewArt = false; private List? ListAziende; private List? ListRecords; private List? ListTipoArt; + private int maxNumRecord = 1000; + private int availRecord = 1000; + private int totRecord = 0; private List? SearchRecords; #endregion Private Fields #region Private Properties - private int _currPage { get; set; } = 1; - private int _numRecord { get; set; } = 10; + private int _currPage = 1; + private int _numRecord = 10; private int currPage { @@ -274,8 +210,7 @@ namespace MP.SPEC.Pages if (_currPage != value) { _currPage = value; - var pUpd = Task.Run(async () => await ReloadData()); - pUpd.Wait(); + UpdateTable(); } } } @@ -290,12 +225,13 @@ namespace MP.SPEC.Pages if (_numRecord != value) { _numRecord = value; - var pUpd = Task.Run(async () => await ReloadData()); - pUpd.Wait(); + UpdateTable(); } } } + private string searchVal { get; set; } = ""; + private string selAzienda { get => _selAzienda; @@ -304,24 +240,29 @@ namespace MP.SPEC.Pages if (value != _selAzienda) { _selAzienda = value; - var pUpd = Task.Run(async () => - { - // svuoto cache redis... - ConfigModel updRec = new ConfigModel() - { - Chiave = "AZIENDA", - Valore = value - }; - MDService.ConfigUpdate(updRec); - await MDService.ConfigResetCache(); - // ricarico - await Task.Delay(1); - await ReloadData(); - }); - pUpd.Wait(); } } } + /// + /// Tipo articolo selezionato + /// + private string selTipoArt = "*"; + + private async Task ReloadAziendaAsync() + { + isLoading = true; + // svuoto cache redis... + ConfigModel updRec = new ConfigModel() + { + Chiave = "AZIENDA", + Valore = selAzienda + }; + await MDService.ConfigUpdateAsync(updRec); + await MDService.ConfigResetCacheAsync(); + // ricarico + await ResetDataAsync(); + } + private bool ShowCharts { get; set; } = false; @@ -330,21 +271,47 @@ namespace MP.SPEC.Pages #region Private Methods /// - /// Seleziona record x editing + /// Verifica cancellabilità record /// /// /// - private bool ArticoloDelEnabled(string codArt) + private bool ArticoloDelEnabled(AnagArticoliModel currRec) { - bool answ = MDService.ArticoloDelEnabled(codArt); - return answ; + if (currRec.Tipo.Equals("KIT")) + return false; + + return MDService.ArticoloDelEnabled(currRec.CodArticolo); } - private async Task ReloadData() + private async Task ReloadBaseData() + { + await MDService.EnsureArtCacheLoadedAsync(true); + selAzienda = await MDService.ConfigTryGetAsync("AZIENDA"); + if (string.IsNullOrEmpty(selAzienda)) + { + selAzienda = "*"; + } + ListAziende = await MDService.ElencoAziendeAsync(); + ListTipoArt = await MDService.AnagTipoArtLvAsync(); + } + + /// + /// Verifica cablata x add tutto tranne KIT + /// + private bool CanAdd => !selTipoArt.Equals("KIT"); + + private async Task ReloadDataAsync() { isLoading = true; - SearchRecords = await MDService.ArticoliGetSearch(100000, selAzienda, SearchVal); - ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList(); + SearchRecords = await MDService.ArticoliGetSearchAsync(maxNumRecord, selTipoArt, selAzienda, SearchVal); + availRecord = await MDService.ArticoliCountSearchAsync(selTipoArt, selAzienda, searchVal); + totalCount = SearchRecords.Count; + UpdateTable(); + } + + private void UpdateTable() + { + ListRecords = SearchRecords?.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList() ?? new(); isLoading = false; } diff --git a/MP.SPEC/Pages/DOSS.razor b/MP.SPEC/Pages/DOSS.razor index 202c48f5..f6ac1afa 100644 --- a/MP.SPEC/Pages/DOSS.razor +++ b/MP.SPEC/Pages/DOSS.razor @@ -6,16 +6,21 @@

    DOSSIERS

    -
    - @if (isFiltering) - { - - filtro x macchina / periodo - } - else - { - - } +
    +
    +
    max rec: @currFilter.MaxRecord
    +
    + @if (isFiltering) + { + + filtro x macchina / periodo + } + else + { + + } +
    +
    diff --git a/MP.SPEC/Pages/DOSS.razor.cs b/MP.SPEC/Pages/DOSS.razor.cs index 7e7198e4..7b0eaccc 100644 --- a/MP.SPEC/Pages/DOSS.razor.cs +++ b/MP.SPEC/Pages/DOSS.razor.cs @@ -1,9 +1,8 @@ +using EgwCoreLib.Razor; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using MP.Data.DbModels; -using MP.SPEC.Components; using MP.SPEC.Data; -using EgwCoreLib.Razor; namespace MP.SPEC.Pages { @@ -43,7 +42,6 @@ namespace MP.SPEC.Pages isLoading = true; isFiltering = true; // fix pagina - await Task.Delay(1); var modFilter = currFilter; modFilter.CurrPage = 1; currFilter = modFilter; @@ -71,7 +69,7 @@ namespace MP.SPEC.Pages #region Private Properties - private SelectDossierParams currFilter { get; set; } = new SelectDossierParams(); + private SelectDossierParams currFilter = new SelectDossierParams() { MaxRecord = 200, CurrPage = 1 }; private int currPage { diff --git a/MP.SPEC/Pages/FluxLogStatus.razor.cs b/MP.SPEC/Pages/FluxLogStatus.razor.cs index 846ecdf1..3f758d89 100644 --- a/MP.SPEC/Pages/FluxLogStatus.razor.cs +++ b/MP.SPEC/Pages/FluxLogStatus.razor.cs @@ -95,7 +95,7 @@ namespace MP.SPEC.Pages await MDataServ.FluxLogDataRedux(idxMaccSel, new List { item }, CurrPeriodo, ValMode, IntReq, NumItem); currStep++; } - //await MDataServ.FluxLogDataRedux(idxMaccSel, fluxList, CurrPeriodo, ValMode, IntReq, maxItem); + //await MDataServ.FluxLogDataReduxAsync(idxMaccSel, fluxList, CurrPeriodo, ValMode, IntReq, maxItem); sw.Stop(); lastDedupExecTime = $"{sw.Elapsed.Minutes}m {sw.Elapsed.Seconds}s"; isProcessing = false; @@ -114,23 +114,23 @@ namespace MP.SPEC.Pages Stopwatch sw = Stopwatch.StartNew(); lastDbMaintTime = "..."; await InvokeAsync(StateHasChanged); - await MDataServ.ForceDbMaint(true, true, true, 1000, 10, 50); + await MDataServ.ForceDbMaintAsync(true, true, true, 1000, 10, 50); sw.Stop(); lastDbMaintTime = $"{sw.Elapsed.Minutes}m {sw.Elapsed.Seconds}s"; isReindexing = false; } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { - ReloadStats(); - ReloadData(); + await ReloadStatsAsync(); + await ReloadDataAsync(); } - protected void ReloadMacchine() + protected async Task ReloadMacchineAsync() { if (ListMacchineAll == null || ListMacchineAll.Count == 0) { - var rawData = MDataServ.MacchineGetFilt("*"); + var rawData = await MDataServ.MacchineGetFiltAsync("*"); // trasformo! if (rawData != null) { @@ -218,18 +218,18 @@ namespace MP.SPEC.Pages #region Private Methods - private void ReloadData() + private async Task ReloadDataAsync() { - ReloadMacchine(); + await ReloadMacchineAsync(); DateTime dtEnd = DateTime.Today.AddDays(1); DateTime dtStart = dtEnd.AddMonths(-1); CurrPeriodo = new Periodo(dtStart, dtEnd); } - private void ReloadStats() + private async Task ReloadStatsAsync() { - actProcDedupStats = MDataServ.ProcFLStats(); - actDbMaintStats = MDataServ.DbDedupStats(); + actProcDedupStats = await MDataServ.ProcFLStatsAsync(); + actDbMaintStats = await MDataServ.DbDedupStatsAsync(); } private void updateExpTime() diff --git a/MP.SPEC/Pages/Giacenze.razor.cs b/MP.SPEC/Pages/Giacenze.razor.cs index e79e5ff8..06cf32da 100644 --- a/MP.SPEC/Pages/Giacenze.razor.cs +++ b/MP.SPEC/Pages/Giacenze.razor.cs @@ -26,16 +26,19 @@ namespace MP.SPEC.Pages protected override async Task OnInitializedAsync() { - await MDService.ConfigResetCache(); + await MDService.ConfigResetCacheAsync(); giacenzeConf = await MDService.ConfigTryGetAsync("SPEC_ShowGiacenze"); await Task.Delay(1); padCodXdl = await MDService.ConfigTryGetAsync("PadCodXdl"); var uri = NavManager.ToAbsoluteUri(NavManager.Uri); if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("IdxOdl", out var _idxOdl)) { - IdxOdl = int.Parse(_idxOdl); + if (!string.IsNullOrEmpty(_idxOdl)) + { + IdxOdl = int.Parse(_idxOdl.ToString()); + } } - odlExp = MDService.OdlByKey(IdxOdl); + odlExp = await MDService.OdlByKeyAsync(IdxOdl); } #endregion Protected Methods diff --git a/MP.SPEC/Pages/GroupMacOprMan.razor.cs b/MP.SPEC/Pages/GroupMacOprMan.razor.cs deleted file mode 100644 index 8bd01f77..00000000 --- a/MP.SPEC/Pages/GroupMacOprMan.razor.cs +++ /dev/null @@ -1,136 +0,0 @@ -using DnsClient.Protocol; -using Microsoft.AspNetCore.Components; -using MP.Core.DTO; -using MP.Data.DbModels; -using MP.Data.Services; -using MP.SPEC.Data; - -namespace MP.SPEC.Pages -{ - public partial class GroupMacOprMan - { - #region Protected Fields - - protected List? ListMacchine = null; - protected List? ListMacchineAll = null; - protected List? ListOperatori = null; - protected List? ListOperatoriAll = null; - protected List? ListReparti = null; - - #endregion Protected Fields - - #region Protected Properties - - [Inject] - protected MpDataService MDService { get; set; } = null!; - - #endregion Protected Properties - - #region Protected Methods - - protected override void OnInitialized() - { - ReloadData(); - } - - #endregion Protected Methods - - #region Private Fields - - private string CodGruppo = ""; - - private bool isLoading = false; - - #endregion Private Fields - - #region Private Properties - - private string CssMain - { - get => ShowDetail ? "col-3" : "col-12"; - } - - private bool ShowDetail - { - get => !string.IsNullOrEmpty(CodGruppo); - } - - #endregion Private Properties - - #region Private Methods - - private void ForceReload(bool doForce) - { - if (doForce) - { - CodGruppo = ""; - } - ReloadData(); - } - - private void ReloadData() - { - isLoading = true; - ListMacchine?.Clear(); - ListMacchineAll = MDService.MacchineGetFilt("*"); - ListOperatoriAll= MDService.OperatoriGetFilt("*").Where(x => x.isEnabled).ToList(); - var rawList = MDService.ElencoRepartiDTO(); - if(string.IsNullOrEmpty(SearchVal)) - { - ListReparti = rawList; - } - else - { - ListReparti = rawList.Where(x => x.CodGruppo.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.DescrGruppo.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase)).ToList(); - } - if (!string.IsNullOrEmpty(CodGruppo)) - { - ReloadDetail(); - } - isLoading = false; - } - - private void ReloadDetail() - { - if (!string.IsNullOrEmpty(CodGruppo)) - { - ListMacchine = MDService.MacchineGetFilt(CodGruppo); - ListOperatori = MDService.OperatoriGetFilt(CodGruppo).Where(x => x.isEnabled).ToList(); - } - } - - private void SetCodGruppo(string CodGruppoSel) - { - isLoading = true; - CodGruppo = CodGruppoSel; - ReloadDetail(); - isLoading = false; - } - - private string btnSearchCss - { - get => string.IsNullOrWhiteSpace(SearchVal) ? "btn-secondary" : "btn-primary"; - } - - private void ResetSearch() - { - SearchVal = ""; - } - - protected string SearchVal - { - get => searchVal; - set - { - if (searchVal != value) - { - searchVal = value; - ReloadData(); - } - } - } - private string searchVal = ""; - - #endregion Private Methods - } -} \ No newline at end of file diff --git a/MP.SPEC/Pages/Index.razor.cs b/MP.SPEC/Pages/Index.razor.cs index 0dad9401..5fbbf699 100644 --- a/MP.SPEC/Pages/Index.razor.cs +++ b/MP.SPEC/Pages/Index.razor.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Components; -using MP.AppAuth.Models; using MP.Data.DbModels; using MP.SPEC.Data; @@ -38,7 +37,7 @@ namespace MP.SPEC.Pages protected override async Task OnInitializedAsync() { // recupero elenco link - ElencoLink = MDService.ElencoLink(); + ElencoLink = await MDService.ElencoLinkAsync(); currAzienda = await MDService.ConfigTryGetAsync("AZIENDA"); await Task.Delay(1); } diff --git a/MP.SPEC/Pages/KIT.razor b/MP.SPEC/Pages/KIT.razor index 2596ab1e..2dfeacc9 100644 --- a/MP.SPEC/Pages/KIT.razor +++ b/MP.SPEC/Pages/KIT.razor @@ -29,12 +29,12 @@ }
    - +
    - +
    diff --git a/MP.SPEC/Pages/KIT.razor.cs b/MP.SPEC/Pages/KIT.razor.cs index b40dece1..af46bcbc 100644 --- a/MP.SPEC/Pages/KIT.razor.cs +++ b/MP.SPEC/Pages/KIT.razor.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.DataProtection; using Microsoft.JSInterop; using MP.Data.DbModels; using MP.SPEC.Data; @@ -56,9 +55,6 @@ namespace MP.SPEC.Pages if (sCodChild != value) { sCodChild = value; - currPage = 1; - ListRecords = null; - ReloadData(); } } } @@ -75,9 +71,6 @@ namespace MP.SPEC.Pages if (sCodParent != value) { sCodParent = value; - currPage = 1; - ListRecords = null; - ReloadData(); } } } @@ -119,7 +112,7 @@ namespace MP.SPEC.Pages // se deve essere autogenerato da counter... if (AutoGen) { - var cntRec = MDService.AnagCountersGetNext("NumKitArt"); + var cntRec = await MDService.AnagCountersGetNextAsync("NumKitArt"); if (cntRec != null) { codParent = $"{cntRec.CntCode}{cntRec.LastNum:000000}"; @@ -142,8 +135,7 @@ namespace MP.SPEC.Pages protected async Task DoCancel() { EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } protected async Task DoClone(TemplateKitModel selRec) @@ -152,12 +144,12 @@ namespace MP.SPEC.Pages TemplateKitModel newRec = new TemplateKitModel() { CodArtParent = selRec.CodArtParent, - CodArtChild = "",//selRec.CodArtParent, + CodArtChild = "", Qty = selRec.Qty }; EditRecord = newRec; SearchParent = selRec.CodArtParent; - await Task.Delay(1); + await ReloadDataAsync(); } /// @@ -170,29 +162,29 @@ namespace MP.SPEC.Pages if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione riga KIT: sei sicuro di voler procedere?")) return; - await Task.Delay(1); - var done = await MDService.TemplateKitDelete(selRec); + var done = await MDService.TemplateKitDeleteAsync(selRec); EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } /// /// Imposta filtro CodArtChild da record /// /// - protected void DoFiltChild(TemplateKitModel selRec) + protected async Task DoFiltChild(TemplateKitModel selRec) { SearchChild = selRec.CodArtChild; + await ResetDataAsync(); } /// /// Imposta filtro CodArtParent da record /// /// - protected void DoFiltParent(TemplateKitModel selRec) + protected async Task DoFiltParent(TemplateKitModel selRec) { SearchParent = selRec.CodArtParent; + await ResetDataAsync(); } protected async Task DoUpdate(TemplateKitModel selRec) @@ -201,51 +193,50 @@ namespace MP.SPEC.Pages return; await Task.Delay(1); - var done = await MDService.TemplateKitUpsert(selRec, CodAzienda); + var done = await MDService.TemplateKitUpsertAsync(selRec, CodAzienda); EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { numRecord = 10; - string rawVal = MDService.ConfigTryGet("SPEC_nArtSearch"); + string rawVal = await MDService.ConfigTryGetAsync("SPEC_nArtSearch"); if (!string.IsNullOrEmpty(rawVal)) { int.TryParse(rawVal, out minChar); } - rawVal = MDService.ConfigTryGet("AZIENDA"); + rawVal = await MDService.ConfigTryGetAsync("AZIENDA"); if (!string.IsNullOrEmpty(rawVal)) { CodAzienda = rawVal; } - rawVal = MDService.ConfigTryGet("SPEC_Kit_enabCount"); + rawVal = await MDService.ConfigTryGetAsync("SPEC_Kit_enabCount"); if (!string.IsNullOrEmpty(rawVal)) { bool.TryParse(rawVal, out enabKitCount); } - rawVal = MDService.ConfigTryGet("SPEC_Kit_enabSearch"); + rawVal = await MDService.ConfigTryGetAsync("SPEC_Kit_enabSearch"); if (!string.IsNullOrEmpty(rawVal)) { bool.TryParse(rawVal, out enabKitSearch); } - rawVal = MDService.ConfigTryGet("SPEC_Kit_enabFreeCodArt"); + rawVal = await MDService.ConfigTryGetAsync("SPEC_Kit_enabFreeCodArt"); if (!string.IsNullOrEmpty(rawVal)) { bool.TryParse(rawVal, out enabFreeCodArt); } } - protected override void OnParametersSet() + protected override Task OnParametersSetAsync() { - ReloadData(); + return ReloadDataAsync(); } - protected void ResetChild() + protected async Task ResetChild() { SearchChild = ""; - ReloadData(); + await ReloadDataAsync(); } protected void ResetData() @@ -253,10 +244,10 @@ namespace MP.SPEC.Pages EditRecord = null; } - protected void ResetParent() + protected async Task ResetParent() { SearchParent = ""; - ReloadData(); + await ReloadDataAsync(); } protected void ResetSel() @@ -280,10 +271,10 @@ namespace MP.SPEC.Pages numRecord = newNum; } - protected void UpdateData() + protected async Task UpdateData() { EditRecord = null; - ReloadData(); + await ReloadDataAsync(); } #endregion Protected Methods @@ -305,6 +296,7 @@ namespace MP.SPEC.Pages private bool enabKitCount = false; private bool enabKitSearch = false; + private List? ListRecords; private int minChar = 2; @@ -329,7 +321,7 @@ namespace MP.SPEC.Pages if (_currPage != value) { _currPage = value; - ReloadData(); + UpdateTable(); } } } @@ -344,7 +336,7 @@ namespace MP.SPEC.Pages if (_numRecord != value) { _numRecord = value; - ReloadData(); + UpdateTable(); } } } @@ -357,18 +349,25 @@ namespace MP.SPEC.Pages #region Private Methods - private void ReloadData() + /// + /// reeload dati + paginazione + /// + /// + private async Task ReloadDataAsync() { isLoading = true; - SearchRecords = MDService.TemplateKitFilt(SearchParent, SearchChild); + SearchRecords = await MDService.TemplateKitFiltAsync(SearchParent, SearchChild); totalCount = SearchRecords.Count; // conto i kit = distinct... kitCount = SearchRecords.GroupBy(x => x.CodArtParent).Count(); - ListRecords = SearchRecords - .Skip(numRecord * (currPage - 1)) - .Take(numRecord) - .ToList(); - isLoading = false; + UpdateTable(); + } + + private Task ResetDataAsync() + { + currPage = 1; + ListRecords = null; + return ReloadDataAsync(); } /// @@ -392,6 +391,18 @@ namespace MP.SPEC.Pages } } + /// + /// Paginazione dati + /// + private void UpdateTable() + { + ListRecords = SearchRecords? + .Skip(numRecord * (currPage - 1)) + .Take(numRecord) + .ToList() ?? new(); + isLoading = false; + } + #endregion Private Methods } } \ No newline at end of file diff --git a/MP.SPEC/Pages/ODL.razor.cs b/MP.SPEC/Pages/ODL.razor.cs index a364953f..af684446 100644 --- a/MP.SPEC/Pages/ODL.razor.cs +++ b/MP.SPEC/Pages/ODL.razor.cs @@ -105,13 +105,13 @@ namespace MP.SPEC.Pages protected override async Task OnInitializedAsync() { await getReparto(); - var allGruppiData = MDService.ElencoGruppiFase(); + var allGruppiData = await MDService.ElencoGruppiFaseAsync(); if (allGruppiData != null) { ListGruppiFase = allGruppiData.Where(x => x.SelEnabled).ToList(); } - ListStati = await MDService.AnagStatiComm(); - ListMacchine = MDService.MacchineGetFilt(selReparto); + ListStati = await MDService.AnagStatiCommAsync(); + ListMacchine = await MDService.MacchineGetFiltAsync(selReparto); padCodXdl = await MDService.ConfigTryGetAsync("PadCodXdl"); } diff --git a/MP.SPEC/Pages/Operatori.razor b/MP.SPEC/Pages/Operatori.razor new file mode 100644 index 00000000..f70941a2 --- /dev/null +++ b/MP.SPEC/Pages/Operatori.razor @@ -0,0 +1,52 @@ +@page "/operatori" + +
    +
    +
    +
    +
    +
    + Gestione Operatori +
    +
    +
    +
    +
    + + @if (ShowDetail) + { + + } + else + { + + } + +
    +
    +
    +
    +
    + @if (isLoading) + { + + } + else + { +
    +
    + +
    + @if (SelRec != null) + { +
    + +
    + } +
    + + } +
    +
    + + diff --git a/MP.SPEC/Pages/Operatori.razor.cs b/MP.SPEC/Pages/Operatori.razor.cs new file mode 100644 index 00000000..38d664aa --- /dev/null +++ b/MP.SPEC/Pages/Operatori.razor.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Components; +using MP.Core.DTO; +using MP.Data.DbModels; +using MP.SPEC.Data; + +namespace MP.SPEC.Pages +{ + public partial class Operatori + { + #region Protected Properties + + [Inject] + protected MpDataService MDService { get; set; } = null!; + + #endregion Protected Properties + + #region Protected Methods + + protected override async Task OnInitializedAsync() + { + await ReloadDataAsync(); + } + + #endregion Protected Methods + + #region Private Fields + + private bool isLoading = false; + private List ListGruppi = new(); + private List ListOperatori = new(); + private string SearchVal = ""; + private AnagOperatoriModel? SelRec = null; + + #endregion Private Fields + + #region Private Properties + + private string btnSearchCss => string.IsNullOrWhiteSpace(SearchVal) ? "btn-secondary" : "btn-primary"; + private string cssMain => SelRec == null ? "col-12" : "col-6"; + + private bool ShowDetail => SelRec != null; + + #endregion Private Properties + + #region Private Methods + + private async Task DoReset() + { + SearchVal = ""; + await ReloadDataAsync(); + } + + private async Task DoSelect(AnagOperatoriModel? newRec) + { + SelRec = newRec; + if (SelRec == null) + { + ListGruppi.Clear(); + } + else + { + // recupero gruppi operatore + ListGruppi = await MDService.GruppiRepartoDtoByOperAsync(SelRec.MatrOpr); + } + } + + private async Task ReloadDataAsync() + { + isLoading = true; + var rawList = await MDService.OperatoriGetFiltAsync("*"); + if (string.IsNullOrEmpty(SearchVal)) + { + ListOperatori = rawList; + } + else + { + ListOperatori = rawList + .Where(x => x.Cognome.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.Nome.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase)).ToList(); + } + isLoading = false; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/MP.SPEC/Pages/PARAMS.razor.cs b/MP.SPEC/Pages/PARAMS.razor.cs index fd1a75e4..3d8b689a 100644 --- a/MP.SPEC/Pages/PARAMS.razor.cs +++ b/MP.SPEC/Pages/PARAMS.razor.cs @@ -1,9 +1,8 @@ -using Microsoft.AspNetCore.Components; +using EgwCoreLib.Razor; +using Microsoft.AspNetCore.Components; using MP.Data.DbModels; -using MP.SPEC.Components; using MP.SPEC.Data; using NLog; -using EgwCoreLib.Razor; namespace MP.SPEC.Pages { @@ -23,7 +22,7 @@ namespace MP.SPEC.Pages public void ElapsedTimer(object? source, System.Timers.ElapsedEventArgs e) { // controllo se sia scaduto tempo massimo (in redis) x ricaricare pagina in modo completo... - var dtRif = MDService.ExpiryReloadParamGet(); + var dtRif = MDService.DtParamExpiry; if (dtRif > DateTime.Now) { Log.Trace("----- Elapsed check PARAMS.cs -----"); @@ -32,7 +31,7 @@ namespace MP.SPEC.Pages { var pUpd = Task.Run(async () => { - MDService.ExpiryReloadParamSet(DateTime.Now.AddSeconds(intForceReload)); + MDService.DtParamExpiry = DateTime.Now.AddSeconds(intForceReload); aTimer.Elapsed -= ElapsedTimer; aTimer.Stop(); aTimer.Close(); @@ -91,7 +90,6 @@ namespace MP.SPEC.Pages { updFilter.lastUpdate = updFilter.lastUpdate == "-" ? $"{adesso:yyyy/MM/dd HH:mm:ss}" : updFilter.lastUpdate; updFilter.IdxMacchina = newRec.IdxMacchina; - //updFilter.CodFlux = newRec.CodFlux; } else { @@ -112,9 +110,9 @@ namespace MP.SPEC.Pages protected async Task forceReloadCache() { Log.Debug("----- forceReloadCache on PARAMS.cs -----"); + await MDService.ForceFlushRedisCache(); await Task.Delay(1); - await MDService.FlushRedisCache(); - await Task.Delay(1); + await MDService.ForceFlushFusionCacheAsync(); // rimando a pagina corrente NavManager.NavigateTo(NavManager.Uri, true, true); } @@ -124,7 +122,6 @@ namespace MP.SPEC.Pages currPage = newNum; DateTime adesso = DateTime.Now.AddSeconds(1); var updFilter = currFilter; - //updFilter.LiveUpdate = (currPage == 1); updFilter.LiveUpdate = (currFilter.CurrPage == 1); updFilter.lastUpdate = updFilter.LiveUpdate ? "-" : $"{adesso:yyyy/MM/dd HH:mm:ss}"; // salvo filtro @@ -211,10 +208,10 @@ namespace MP.SPEC.Pages private void setExpiryReload() { // verifico se ho una scadenza expiry del periodo desiderato, sennò imposto nuova... - var dtRif = MDService.ExpiryReloadParamGet(); + var dtRif = MDService.DtParamExpiry; if (dtRif <= DateTime.Now) { - MDService.ExpiryReloadParamSet(DateTime.Now.AddSeconds(intForceReload)); + MDService.DtParamExpiry = DateTime.Now.AddSeconds(intForceReload); } } @@ -222,18 +219,11 @@ namespace MP.SPEC.Pages { isFiltering = false; isLoading = true; - await Task.Delay(1); currPage = 1; if (newParams.CurrPage == 0) { newParams.CurrPage = 1; - //newParams.LiveUpdate = false; } - else - { - //newParams.LiveUpdate = (currPage == 1); - } - await Task.Delay(1); await InvokeAsync(() => StateHasChanged()); currFilter = newParams; isLoading = false; diff --git a/MP.SPEC/Pages/PODL.razor b/MP.SPEC/Pages/PODL.razor index c6ad0b6b..61375d1c 100644 --- a/MP.SPEC/Pages/PODL.razor +++ b/MP.SPEC/Pages/PODL.razor @@ -12,7 +12,7 @@
    Da Produrre
    - +
    Lanciati
    @@ -29,20 +29,27 @@
    +
    +
    + + + +
    +
    @if (filtActive) {
    @if (selReparto != "*") { - + } @if (macchina != "*") { - + } @if (StatoSel != "*") { - + }
    } @@ -164,7 +171,7 @@
    Gruppo - @if (currGruppoSel != null && currGruppoSel.CodGruppo!=null) + @if (currGruppoSel != null && currGruppoSel.CodGruppo != null) { } diff --git a/MP.SPEC/Pages/PODL.razor.cs b/MP.SPEC/Pages/PODL.razor.cs index ce20588b..5e00967a 100644 --- a/MP.SPEC/Pages/PODL.razor.cs +++ b/MP.SPEC/Pages/PODL.razor.cs @@ -1,17 +1,14 @@ #if false using Blazored.LocalStorage; #endif +using EgwCoreLib.Razor; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using MP.Data.DbModels; -using MP.SPEC.Components; +using MP.Data.Services; using MP.SPEC.Data; using MP.SPEC.Services; using NLog; -using System.Reflection.PortableExecutable; -using EgwCoreLib.Razor; -using Microsoft.AspNetCore.DataProtection; -using MP.Data.Services; namespace MP.SPEC.Pages { @@ -61,10 +58,6 @@ namespace MP.SPEC.Pages [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; -#if false - [Inject] - protected ILocalStorageService localStorage { get; set; } = null!; -#endif [Inject] protected ILocalStorageService localStorage { get; set; } = null!; @@ -87,7 +80,7 @@ namespace MP.SPEC.Pages protected async Task cancel() { currRecord = null; - await ReloadData(); + await ReloadDataAsync(); await Task.Delay(1); } @@ -132,13 +125,13 @@ namespace MP.SPEC.Pages protected override async Task OnInitializedAsync() { await getReparto(); - ListAziende = MDService.ElencoAziende(); - var allGruppiData = MDService.ElencoGruppiFase(); + ListAziende = await MDService.ElencoAziendeAsync(); + var allGruppiData = await MDService.ElencoGruppiFaseAsync(); if (allGruppiData != null) { ListGruppiFase = allGruppiData.Where(x => x.SelEnabled).ToList(); } - ListStati = await MDService.AnagStatiComm(); + ListStati = await MDService.AnagStatiCommAsync(); currAzienda = await MDService.ConfigTryGetAsync("AZIENDA"); padCodXdl = await MDService.ConfigTryGetAsync("padCodXdl"); useFasi4KeyRich = await MDService.ConfigTryGetAsync("SPEC_KeyRichiesta"); @@ -168,7 +161,7 @@ namespace MP.SPEC.Pages protected override async Task OnParametersSetAsync() { // carico dati - await ReloadData(); + await ReloadDataAsync(); } protected async Task pgResetReq(bool doReset) @@ -344,7 +337,7 @@ namespace MP.SPEC.Pages { currRecord.CodArticolo = ""; } - await ReloadData(); + await ReloadDataAsync(); }); pUpd.Wait(); } @@ -363,7 +356,7 @@ namespace MP.SPEC.Pages _currAzienda = value; var pUpd = Task.Run(async () => { - await ReloadData(); + await ReloadDataAsync(); }); pUpd.Wait(); } @@ -383,7 +376,7 @@ namespace MP.SPEC.Pages } } - private SelectXdlParams currFilter { get; set; } = new SelectXdlParams(); + private SelectXdlParams currFilter { get; set; } = new SelectXdlParams() { SearchVal = "" }; private int currPage { @@ -498,12 +491,11 @@ namespace MP.SPEC.Pages } } - private async Task ReloadData() + private async Task ReloadDataAsync() { isLoading = true; - await Task.Delay(1); - ListMacchine = MDService.MacchineGetFilt(selReparto); - ListArticoli = await MDService.ArticoliGetSearch(100, currAzienda, artSearch); + ListMacchine = await MDService.MacchineGetFiltAsync(selReparto); + ListArticoli = await MDService.ArticoliGetSearchAsync(100, "*", currAzienda, artSearch); if (ListGruppiFase != null) { var firstGroup = ListGruppiFase.Where(x => x.CodGruppo == selReparto).FirstOrDefault(); @@ -515,6 +507,14 @@ namespace MP.SPEC.Pages isLoading = false; } + private string sSearchCss => string.IsNullOrEmpty(currFilter.SearchVal) ? "btn-secondary" : "btn-primary"; + + private async Task ResetSearch() + { + currFilter.SearchVal = ""; + await ReloadDataAsync(); + } + private async Task UpdateFilter(SelectXdlParams newParams) { isLoading = true; @@ -522,7 +522,7 @@ namespace MP.SPEC.Pages currPage = 1; // salvo comunque filtro reparto x utente await localStorage.SetItemAsync("reparto", selReparto); - await ReloadData(); + await ReloadDataAsync(); await Task.Delay(1); await InvokeAsync(() => StateHasChanged()); currFilter = newParams; diff --git a/MP.SPEC/Pages/Podl2Kit.razor.cs b/MP.SPEC/Pages/Podl2Kit.razor.cs index 9e8e270a..bea6e530 100644 --- a/MP.SPEC/Pages/Podl2Kit.razor.cs +++ b/MP.SPEC/Pages/Podl2Kit.razor.cs @@ -1,12 +1,8 @@ using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.JSInterop; using MP.Data.DbModels; using MP.Data.Services; -using MP.SPEC.Components; using MP.SPEC.Data; -using NLog.Layouts; -using System.Reflection.PortableExecutable; namespace MP.SPEC.Pages { @@ -37,10 +33,6 @@ namespace MP.SPEC.Pages [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; -#if false - [Inject] - protected ILocalStorageService localStorage { get; set; } = null!; -#endif [Inject] protected ILocalStorageService localStorage { get; set; } = null!; @@ -59,13 +51,17 @@ namespace MP.SPEC.Pages if (sCodComm != value) { sCodComm = value; - currPage = 1; - ListRecords = null; - ReloadData(); } } } + private async Task ResetDataAsync() + { + currPage = 1; + ListRecords = null; + await ReloadDataAsync(); + } + protected string sParentCss { get => string.IsNullOrEmpty(sCodComm) ? "btn-secondary" : "btn-primary"; @@ -120,8 +116,7 @@ namespace MP.SPEC.Pages protected async Task DoCancel() { EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } /// @@ -135,10 +130,9 @@ namespace MP.SPEC.Pages return; await Task.Delay(1); - var done = await MDService.IstKitDelete(selRec); + var done = await MDService.IstKitDeleteAsync(selRec); EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } protected async Task DoUpdate(IstanzeKitModel selRec) @@ -147,28 +141,27 @@ namespace MP.SPEC.Pages return; await Task.Delay(1); - var done = await MDService.IstKitUpsert(selRec); + var done = await MDService.IstKitUpsertAsync(selRec); EditRecord = null; - ReloadData(); - await Task.Delay(1); + await ResetDataAsync(); } - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { numRecord = 10; // gestione di base dei KIT - string rawVal = MDService.ConfigTryGet("OptAdmKitEnabled"); + string rawVal = await MDService.ConfigTryGetAsync("OptAdmKitEnabled"); if (!string.IsNullOrEmpty(rawVal)) { bool.TryParse(rawVal, out OptAdmKitEnabled); } // conf variabili decodifica - regExp_KO = MDService.ConfigTryGet("regExp_KO"); - regExp_OK = MDService.ConfigTryGet("regExp_OK"); - regExp_KitStart = MDService.ConfigTryGet("regExp_KitStart"); - regExp_KitSave = MDService.ConfigTryGet("regExp_KitSave"); + regExp_KO = await MDService.ConfigTryGetAsync("regExp_KO"); + regExp_OK = await MDService.ConfigTryGetAsync("regExp_OK"); + regExp_KitStart = await MDService.ConfigTryGetAsync("regExp_KitStart"); + regExp_KitSave = await MDService.ConfigTryGetAsync("regExp_KitSave"); // altre variabili - rawVal = MDService.ConfigTryGet("SPEC_nArtSearch"); + rawVal = await MDService.ConfigTryGetAsync("SPEC_nArtSearch"); if (!string.IsNullOrEmpty(rawVal)) { int.TryParse(rawVal, out minChar); @@ -176,9 +169,9 @@ namespace MP.SPEC.Pages setBaseFilt(); } - protected override void OnParametersSet() + protected override async Task OnParametersSetAsync() { - ReloadData(); + await ReloadDataAsync(); } protected void ResetData() @@ -191,10 +184,10 @@ namespace MP.SPEC.Pages idxMaccSel = "*"; } - protected void ResetParent() + protected async Task ResetParent() { SearchComm = ""; - ReloadData(); + await ResetDataAsync(); } protected void resetReparto() @@ -228,10 +221,10 @@ namespace MP.SPEC.Pages numRecord = newNum; } - protected void UpdateData() + protected async Task UpdateData() { EditRecord = null; - ReloadData(); + await ResetDataAsync(); } #endregion Protected Methods @@ -253,9 +246,9 @@ namespace MP.SPEC.Pages private List ListMacchine = new List(); - private List? ListRecords; + private List? ListRecords = new(); - private List? ListStati; + private List? ListStati = new(); private int minChar = 2; @@ -301,7 +294,7 @@ namespace MP.SPEC.Pages get => doAddNew ? (isComposing ? "Completare o Resettare" : "Chiudi Composizione KIT") : "Composizione Nuovo KIT"; } - private SelectXdlParams currFilter { get; set; } = new SelectXdlParams(); + private SelectXdlParams currFilter { get; set; } = new SelectXdlParams() { NumRec = 5 }; private int currPage { @@ -311,7 +304,7 @@ namespace MP.SPEC.Pages if (_currPage != value) { _currPage = value; - ReloadData(); + UpdateTable(); } } } @@ -342,7 +335,7 @@ namespace MP.SPEC.Pages if (_numRecord != value) { _numRecord = value; - ReloadData(); + UpdateTable(); } } } @@ -359,24 +352,29 @@ namespace MP.SPEC.Pages #region Private Methods - private void ReloadData() + private async Task ReloadDataAsync() { isLoading = true; // leggo dati x filtro - var allGruppiData = MDService.ElencoGruppiFase(); + var allGruppiData = await MDService.ElencoGruppiFaseAsync(); if (allGruppiData != null) { ListGruppiFase = allGruppiData.Where(x => x.SelEnabled).ToList(); } - ListMacchine = MDService.MacchineGetFilt(repartoSel); - SearchRecords = MDService.IstKitFilt("", ""); + ListMacchine = await MDService.MacchineGetFiltAsync(repartoSel); + SearchRecords = await MDService.IstKitFiltAsync("", ""); totalCount = SearchRecords.Count; // conto i kit = distinct... kitCount = SearchRecords.GroupBy(x => x.CodArtParent).Count(); - ListRecords = SearchRecords - .Skip(numRecord * (currPage - 1)) - .Take(numRecord) - .ToList(); + UpdateTable(); + } + + private void UpdateTable() + { + ListRecords = SearchRecords? + .Skip(numRecord * (currPage - 1)) + .Take(numRecord) + .ToList() ?? new(); isLoading = false; } @@ -423,7 +421,7 @@ namespace MP.SPEC.Pages currPage = 1; // salvo filtro reparto x utente... spostare in componente? await localStorage.SetItemAsync("reparto", repartoSel); - ReloadData(); + await ReloadDataAsync(); currFilter = newParams; isLoading = false; } diff --git a/MP.SPEC/Pages/ProdPlanner.razor b/MP.SPEC/Pages/ProdPlanner.razor index 2142f878..87f4c4a9 100644 --- a/MP.SPEC/Pages/ProdPlanner.razor +++ b/MP.SPEC/Pages/ProdPlanner.razor @@ -11,7 +11,8 @@
    - +
    inserire calendar planner
    + @* *@
    diff --git a/MP.SPEC/Pages/GroupMacOprMan.razor b/MP.SPEC/Pages/RepOper.razor similarity index 87% rename from MP.SPEC/Pages/GroupMacOprMan.razor rename to MP.SPEC/Pages/RepOper.razor index 066214f9..22084e57 100644 --- a/MP.SPEC/Pages/GroupMacOprMan.razor +++ b/MP.SPEC/Pages/RepOper.razor @@ -16,11 +16,11 @@ @if (ShowDetail) { - + } else { - + }
    @@ -37,11 +37,11 @@
    - +
    @if (ShowDetail) { -
    +
    diff --git a/MP.SPEC/Pages/RepOper.razor.cs b/MP.SPEC/Pages/RepOper.razor.cs new file mode 100644 index 00000000..0f3ec8fa --- /dev/null +++ b/MP.SPEC/Pages/RepOper.razor.cs @@ -0,0 +1,134 @@ +using Microsoft.AspNetCore.Components; +using MP.Core.DTO; +using MP.Data.DbModels; +using MP.SPEC.Data; + +namespace MP.SPEC.Pages +{ + public partial class RepOper + { + #region Protected Fields + + protected List? ListMacchine = null; + protected List? ListMacchineAll = null; + protected List? ListOperatori = null; + protected List? ListOperatoriAll = null; + protected List? ListReparti = null; + + #endregion Protected Fields + + #region Protected Properties + + [Inject] + protected MpDataService MDService { get; set; } = null!; + + protected string SearchVal + { + get => searchVal; + set + { + if (searchVal != value) + { + searchVal = value; + } + } + } + + #endregion Protected Properties + + #region Protected Methods + protected override async Task OnInitializedAsync() + { + await ReloadBaseDataAsync(); + await ReloadDataAsync(); + } + + #endregion Protected Methods + + #region Private Fields + + private string CodGruppo = ""; + + private bool isLoading = false; + + private string searchVal = ""; + + #endregion Private Fields + + #region Private Properties + + private string btnSearchCss => string.IsNullOrWhiteSpace(SearchVal) ? "btn-secondary" : "btn-primary"; + + private string CssMain => ShowDetail ? "col-4" : "col-12"; + + private bool ShowDetail => !string.IsNullOrEmpty(CodGruppo); + + #endregion Private Properties + + #region Private Methods + + private async Task ForceReload(bool doForce) + { + if (doForce) + { + CodGruppo = ""; + } + await ReloadDataAsync(); + } + + private async Task ReloadBaseDataAsync() + { + ListMacchineAll = await MDService.MacchineGetFiltAsync("*"); + var listRaw = await MDService.OperatoriGetFiltAsync("*"); + ListOperatoriAll = listRaw.Where(x => x.isEnabled).ToList(); + } + + private async Task ReloadDataAsync() + { + isLoading = true; + //ListMacchine?.Clear(); + if (string.IsNullOrEmpty(CodGruppo) || true) + { + ListReparti?.Clear(); + var rawList = await MDService.ElencoRepartiDtoAsync(); + if (string.IsNullOrEmpty(SearchVal)) + { + ListReparti = rawList; + } + else + { + ListReparti = rawList.Where(x => x.CodGruppo.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase) || x.DescrGruppo.Contains(SearchVal, StringComparison.InvariantCultureIgnoreCase)).ToList(); + } + } + if (!string.IsNullOrEmpty(CodGruppo)) + { + await ReloadDetailAsync(); + } + isLoading = false; + } + + private async Task ReloadDetailAsync() + { + if (!string.IsNullOrEmpty(CodGruppo)) + { + ListMacchine = await MDService.MacchineGetFiltAsync(CodGruppo); + ListOperatori = (await MDService.OperatoriGetFiltAsync(CodGruppo)) + .Where(x => x.isEnabled).ToList(); + } + } + + private async Task ResetSearch() + { + SearchVal = ""; + await ReloadDataAsync(); + } + + private async Task SetCodGruppo(string CodGruppoSel) + { + CodGruppo = CodGruppoSel; + await ReloadDetailAsync(); + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/MP.SPEC/Pages/RepStop.razor.cs b/MP.SPEC/Pages/RepStop.razor.cs index 2bc4bd0c..b49a4714 100644 --- a/MP.SPEC/Pages/RepStop.razor.cs +++ b/MP.SPEC/Pages/RepStop.razor.cs @@ -116,7 +116,7 @@ namespace MP.SPEC.Pages { isLoading = true; await Task.Delay(100); - CurrMSE = await MDService.MseGetAll(true); + CurrMSE = await MDService.MseGetAllAsync(true); isLoading = false; } @@ -136,7 +136,7 @@ namespace MP.SPEC.Pages foreach (var idxMacc in CurrMachSel) { DateTime adesso = DateTime.Now.Floor(TimeSpan.FromSeconds(1)); - var rigaStato = MDService.StatoMacchina(idxMacc); + var rigaStato = await MDService.StatoMacchinaAsync(idxMacc); string valData = $"SPEC | FRep.Fine | {MService.DomainName}\\{MService.UserName}"; // chiamo stored @@ -146,7 +146,7 @@ namespace MP.SPEC.Pages } forceResetSel = true; - var ListMSE = await MDService.MseGetAll(true); + var ListMSE = await MDService.MseGetAllAsync(true); CurrMachSel = new(); await Task.Delay(250); await ReloadData(); @@ -175,7 +175,7 @@ namespace MP.SPEC.Pages // se conferma ciclo x ogni macchina e registro foreach (var idxMacc in CurrMachSel) { - var rigaStato = MDService.StatoMacchina(idxMacc); + var rigaStato = await MDService.StatoMacchinaAsync(idxMacc); // preparo info utente x Value... string valData = $"SPEC | FRep.Inizio | {MService.DomainName}\\{MService.UserName}"; @@ -197,7 +197,7 @@ namespace MP.SPEC.Pages await TabDServ.resetMicrostatoMacchina(idxMacc); } forceResetSel = true; - var ListMSE = await MDService.MseGetAll(true); + var ListMSE = await MDService.MseGetAllAsync(true); CurrMachSel = new(); await Task.Delay(250); await ReloadData(); @@ -211,8 +211,8 @@ namespace MP.SPEC.Pages private async Task ReloadData() { - CurrMSE = await MDService.MseGetAll(false); - SearchFermate = MDService.AnagEventiGeneral(); + CurrMSE = await MDService.MseGetAllAsync(false); + SearchFermate = await MDService.AnagEventiGeneralAsync(); } #endregion Private Methods diff --git a/MP.SPEC/Pages/Test.razor b/MP.SPEC/Pages/Test.razor index 60775048..0febaf6d 100644 --- a/MP.SPEC/Pages/Test.razor +++ b/MP.SPEC/Pages/Test.razor @@ -29,7 +29,7 @@
    - +
    diff --git a/MP.SPEC/Pages/Test.razor.cs b/MP.SPEC/Pages/Test.razor.cs index 9d489526..8d495b95 100644 --- a/MP.SPEC/Pages/Test.razor.cs +++ b/MP.SPEC/Pages/Test.razor.cs @@ -38,8 +38,8 @@ namespace MP.SPEC.Pages CurrAction.IsActive = false; CurrAction.Topic = "Chiusura ODL"; CurrAction.Message = "Rilevato possibile fine operazioni, Vuoi chiudere la commessa?"; - MMDataService.ActionSetReq(CurrAction); - await Task.Delay(1); + + await MMDataService.ActionSetReqAsync(CurrAction); } protected override async Task OnInitializedAsync() @@ -68,11 +68,11 @@ namespace MP.SPEC.Pages } } - protected void sendMessage() + protected async Task SendMessageAsync() { CurrAction.DtReq = DateTime.Now; CurrAction.IsActive = true; - MMDataService.ActionSetReq(CurrAction); + await MMDataService.ActionSetReqAsync(CurrAction); } #endregion Protected Methods diff --git a/MP.SPEC/Pages/Utils.razor.cs b/MP.SPEC/Pages/Utils.razor.cs index f26cdad2..5020e3eb 100644 --- a/MP.SPEC/Pages/Utils.razor.cs +++ b/MP.SPEC/Pages/Utils.razor.cs @@ -9,8 +9,8 @@ namespace MP.SPEC.Pages public async Task flushCache() { - await Task.Delay(1); - await MDService.FlushRedisCache(); + await MDService.ForceFlushRedisCache(); + await MDService.ForceFlushFusionCacheAsync(); // rimando a home NavManager.NavigateTo("", true); } diff --git a/MP.SPEC/Pages/_Host.cshtml b/MP.SPEC/Pages/_Host.cshtml deleted file mode 100644 index cc60006b..00000000 --- a/MP.SPEC/Pages/_Host.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@page "/" -@namespace MP.SPEC.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@{ - Layout = "_Layout"; -} - - \ No newline at end of file diff --git a/MP.SPEC/Pages/_Layout.cshtml b/MP.SPEC/Pages/_Layout.cshtml deleted file mode 100644 index ce82407f..00000000 --- a/MP.SPEC/Pages/_Layout.cshtml +++ /dev/null @@ -1,69 +0,0 @@ -@using Microsoft.AspNetCore.Components.Web -@namespace MP.SPEC.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers - - - - - MP-SPEC - - - - - - - - - - - - - - @RenderBody() - -
    - - An error has occurred. This application may no longer respond until reloaded. - - - An unhandled exception has occurred. See browser dev tools for details. - - Reload - 🗙 -
    - - - - - - - - - @*Gestione autoriconnessione: https://github.com/dotnet/aspnetcore/issues/38305 (vedere anche https://docs.microsoft.com/it-it/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-6.0#modify-the-reconnection-handler-blazor-server)*@ - - - diff --git a/MP.SPEC/Program.cs b/MP.SPEC/Program.cs index 23fcc447..a90fc99b 100644 --- a/MP.SPEC/Program.cs +++ b/MP.SPEC/Program.cs @@ -1,34 +1,26 @@ using Microsoft.AspNetCore.Authentication.Negotiate; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Extensions.Configuration; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.FileProviders; -using Microsoft.JSInterop; -using MP.AppAuth.Services; -using MP.Data.Services; +using MP.Data; using MP.SPEC.Components; using MP.SPEC.Data; using MP.SPEC.Services; using NLog; using NLog.Targets; -using NLog.Targets.OpenTelemetryProtocol; using NLog.Web; using OpenTelemetry.Resources; using OpenTelemetry.Trace; using StackExchange.Redis; - +using ZiggyCreatures.Caching.Fusion; +using ZiggyCreatures.Caching.Fusion.Backplane.StackExchangeRedis; +using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson; var builder = WebApplication.CreateBuilder(args); -/*-------------------- - * Note migrazione startup.cs --> program.cs: - * - * - https://stackoverflow.com/questions/69722872/asp-net-core-6-how-to-access-ConfMan-during-startup - * - https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60?view=aspnetcore-5.0&tabs=visual-studio#where-do-i-put-state-that-was-stored-as-fields-in-my-program-or-startup-class - * - * */ - ConfigurationManager configuration = builder.Configuration; var logger = LogManager.Setup() @@ -43,7 +35,7 @@ string connStringRedis = configuration.GetConnectionString("Redis") ?? "localhos //string connStringRedis = ConfMan.GetConnectionString("RedisAdmin"); string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":")); // avvio oggetto shared x redis... -var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); +IConnectionMultiplexer redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); // ==================================================================== @@ -141,32 +133,78 @@ builder.Services.AddAuthorization(options => options.FallbackPolicy = options.DefaultPolicy; }); -// redis replliminare -builder.Services.AddSingleton(redisMultiplexer); +//setup Blazor +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); + builder.Services.AddRazorPages(); -builder.Services.AddServerSideBlazor(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); + +// memory + redis preliminare +builder.Services.AddSingleton(redisMultiplexer); + +// ✅ Distributed cache (necessario per FusionCache) +builder.Services.AddStackExchangeRedisCache(options => +{ + options.Configuration = connStringRedis; +}); + +// ✅ FusionCache +builder.Services.AddFusionCache() + .WithDistributedCache(sp => sp.GetRequiredService()) + .WithSerializer(new FusionCacheNewtonsoftJsonSerializer()) + .WithBackplane(new RedisBackplane(new RedisBackplaneOptions + { + ConnectionMultiplexerFactory = () => Task.FromResult(redisMultiplexer) + })); + +// Metodi principali x accesso dati +var connStr = builder.Configuration.GetConnectionString("MP.Data") + ?? throw new InvalidOperationException("ConnString 'MP.Data' mancante."); +// aggiungo il costruttore x i vari DbContextFactory +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStr) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStr) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + +var connStrFL = builder.Configuration.GetConnectionString("MP.Flux") + ?? throw new InvalidOperationException("ConnString 'MP.Flux' mancante."); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStrFL) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + +var connStrSta = builder.Configuration.GetConnectionString("MP.Stats") + ?? throw new InvalidOperationException("ConnString 'MP.Stats' mancante."); +builder.Services.AddDbContextFactory(options => + options.UseSqlServer(connStrSta) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + +// Init centralizzato Repository/Servizi da MP.Data Services +builder.Services.AddSpecDataLayer(); + +// servizi del progetto SPEC +builder.Services.TryAddScoped(); +builder.Services.TryAddSingleton(); +builder.Services.TryAddScoped(); + +#if false builder.Services.AddSingleton(); -builder.Services.AddScoped(); +builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -#if false -builder.Services.AddBlazoredLocalStorage(); -builder.Services.AddBlazoredSessionStorage(); +builder.Services.AddSingleton(); #endif + +#if false // aggiunta helper local/session storage service builder.Services.AddScoped(); -builder.Services.AddScoped(); -//builder.Services.AddScoped(); -//builder.Services.AddScoped(); -//builder.Services.AddScoped(sp => -// new SessionStorageService(sp.GetRequiredService())); -//builder.Services.AddScoped(sp => -// new LocalStorageService(sp.GetRequiredService())); - +builder.Services.AddScoped(); +#endif builder.Services.AddHttpClient(); @@ -179,7 +217,9 @@ logger.Info("Build App"); // aggiunt base URL x routing corretto -app.UsePathBase(configuration.GetValue("SpecialConf:AppUrl")); +string baseUrl = configuration.GetValue("SpecialConf:AppUrl") ?? ""; +app.UsePathBase(baseUrl); +logger.Info($"BaseUrl: {baseUrl}"); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) @@ -193,6 +233,13 @@ app.UseHttpsRedirection(); app.UseStaticFiles(); +app.UseRouting(); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.UseAntiforgery(); + // gestione static files: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-8.0 string BasePathOdlReturn = configuration.GetValue("ServerConf:BasePathOdlReturn") ?? configuration.GetValue("OptConf:BasePathOdlReturn") ?? ""; if (!string.IsNullOrEmpty(BasePathOdlReturn)) @@ -215,8 +262,11 @@ if (!string.IsNullOrEmpty(BasePathOdlReturn)) // https://harrybellamy.com/posts/getting-mime-types-from-file-extensions-in-net-core/ foreach (var item in mimeDict) { - // Add new mappings - provider.Mappings[item.Key] = item.Value; + if (!string.IsNullOrEmpty(item.Value)) + { + // Add new mappings + provider.Mappings[item.Key] = item.Value; + } } } @@ -234,19 +284,8 @@ if (!string.IsNullOrEmpty(BasePathOdlReturn)) } } -app.UseRouting(); - -app.UseAuthentication(); -app.UseAuthorization(); - -app.UseEndpoints(endpoints => -{ - endpoints.MapControllers(); - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); -}); -//app.MapBlazorHub(); -//app.MapFallbackToPage("/_Host"); +app.MapRazorComponents() + .AddInteractiveServerRenderMode(); logger.Info("Run App"); diff --git a/MP.SPEC/Resources/ChangeLog.html b/MP.SPEC/Resources/ChangeLog.html index 133a7fea..b6126dfe 100644 --- a/MP.SPEC/Resources/ChangeLog.html +++ b/MP.SPEC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOSPEC -

    Versione: 8.16.2604.2718

    +

    Versione: 8.16.2606.409


    Note di rilascio:
    • diff --git a/MP.SPEC/Resources/VersNum.txt b/MP.SPEC/Resources/VersNum.txt index 87ec763e..722b7892 100644 --- a/MP.SPEC/Resources/VersNum.txt +++ b/MP.SPEC/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2604.2718 +8.16.2606.409 diff --git a/MP.SPEC/Resources/manifest.xml b/MP.SPEC/Resources/manifest.xml index 6abb2dad..85bf0bb0 100644 --- a/MP.SPEC/Resources/manifest.xml +++ b/MP.SPEC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2604.2718 + 8.16.2606.409 https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/MP.SPEC.zip https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/ChangeLog.html false diff --git a/MP.SPEC/Services/IOApiService.cs b/MP.SPEC/Services/IOApiService.cs index 05f70c25..d0372db3 100644 --- a/MP.SPEC/Services/IOApiService.cs +++ b/MP.SPEC/Services/IOApiService.cs @@ -1,7 +1,5 @@ -using Microsoft.Extensions.Configuration; -using MP.SPEC.Data; +using MP.SPEC.Data; using NLog; -using System.Text.Json; namespace MP.SPEC.Services { @@ -21,7 +19,7 @@ namespace MP.SPEC.Services _configuration = configuration; _clientFactory = clientFactory; // conf url x chiamate REST - MpIoBaseUrl = _configuration.GetValue("ServerConf:MpIoBaseUrl"); + MpIoBaseUrl = _configuration.GetValue("ServerConf:MpIoBaseUrl") ?? "MoonPro"; } #endregion Public Constructors diff --git a/MP.SPEC/_Imports.razor b/MP.SPEC/_Imports.razor index 8af8acff..1e775e6f 100644 --- a/MP.SPEC/_Imports.razor +++ b/MP.SPEC/_Imports.razor @@ -1,5 +1,6 @@ @using System.Net.Http @using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Components @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @@ -15,6 +16,7 @@ @using MP.SPEC.Components @using MP.SPEC.Components.Chart @using MP.SPEC.Components.Fermate +@using MP.SPEC.Components.Layout @using MP.SPEC.Components.ProdKit @using MP.SPEC.Components.Reparti @using EgwCoreLib.Razor \ No newline at end of file diff --git a/MP.SPEC/appsettings.Development.json b/MP.SPEC/appsettings.Development.json index de8e232d..8c2753ce 100644 --- a/MP.SPEC/appsettings.Development.json +++ b/MP.SPEC/appsettings.Development.json @@ -14,7 +14,6 @@ "ServerConf": { "maxAge": "2000", "cacheCheckArtUsato": 2, - "redisLongTimeCache": 15, "MpIoBaseUrl": "https://iis01.egalware.com/MP/IO/" } } diff --git a/MP.SPEC/appsettings.Production.json b/MP.SPEC/appsettings.Production.json index 07c7752c..f4ebc6a0 100644 --- a/MP.SPEC/appsettings.Production.json +++ b/MP.SPEC/appsettings.Production.json @@ -27,7 +27,9 @@ "ServerConf": { "maxAge": "2000", "cacheCheckArtUsato": 2, - "redisLongTimeCache": 15, + "redisShortTimeCache": 10, + "redisLongTimeCache": 600, + "slowLogThresh": 200, "MpIoBaseUrl": "http://localhost/MP/IO/", "MpIoNS": "MoonPro:SQL2016DEV:MoonPro", "BasePathOdlReturn": "\\\\iis01\\W$\\Files\\ODL", diff --git a/MP.SPEC/appsettings.Staging.json b/MP.SPEC/appsettings.Staging.json index d61f5682..531d2258 100644 --- a/MP.SPEC/appsettings.Staging.json +++ b/MP.SPEC/appsettings.Staging.json @@ -14,7 +14,6 @@ "ServerConf": { "maxAge": "2000", "cacheCheckArtUsato": 2, - "redisLongTimeCache": 15, "MpIoBaseUrl": "http://localhost/MP/IO/" } } diff --git a/MP.SPEC/appsettings.json b/MP.SPEC/appsettings.json index a061328d..6bda77be 100644 --- a/MP.SPEC/appsettings.json +++ b/MP.SPEC/appsettings.json @@ -2,7 +2,10 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Warning", + "Microsoft.EntityFrameworkCore.Database.Command": "Warning", + "ZiggyCreatures.Caching.Fusion": "Warning" } }, "NLog": { @@ -60,6 +63,7 @@ "MP.Land": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.SPEC;", "MP.Land.Auth": "Server=SQL2016DEV;Database=MoonPro_Anagrafica; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.SPEC;", "MP.Sched": "Server=SQL2016DEV;Database=MoonPro_ES3; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.SPEC;", + "MP.Stats": "Server=SQL2016DEV;Database=MoonPro_STATS;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=MP.SPEC;", "Redis": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=5,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true", "RedisAdmin": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=5,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true", "mdbConnString": "mongodb://W2019-MONGODB:27017" @@ -67,7 +71,9 @@ "ServerConf": { "maxAge": "2000", "cacheCheckArtUsato": "2", - "redisLongTimeCache": "15", + "redisShortTimeCache": 5, + "redisLongTimeCache": 120, + "slowLogThresh": 1, "MpIoBaseUrl": "http://localhost:20967/", "MpIoNS": "MoonPro:SQL2016DEV:MoonPro", "BasePathOdlReturn": "\\\\iis01\\ODL\\ftpdata\\syncfolder", @@ -81,7 +87,7 @@ "maxChar4Scroll": 21 }, "SpecialConf": { - "AppUrl": "/MP/SPEC", + "AppUrl": "/MP/SPEC/", "CodApp": "MP-SPEC", "CodModulo": "MP-SPEC" } diff --git a/MP.SPEC/refactor_repository.md b/MP.SPEC/refactor_repository.md new file mode 100644 index 00000000..d0a75046 --- /dev/null +++ b/MP.SPEC/refactor_repository.md @@ -0,0 +1,80 @@ +# Refactoring Repository: Decomposizione MpSpecController - STATO COMPLETO + +## Riepilogo + +| Progetto | Build | Errori | +|---|---|---| +| MP.Data | OK | 0 | +| MP.SPEC | OK | 0 | + +## Repository Creati (8 nuovi) + +| # | Repository | Interfaccia | Metodi | DbContext | +|---|---|---|---|---| +| 1 | **Anag** | `IAnagRepository` | 26 | `MoonProContext` | +| 2 | **Production** | `IProductionRepository` | 32 | `MoonProContext` | +| 3 | **Dossier** | `IDossierRepository` | 6 | `MoonPro_FluxContext` | +| 4 | **FluxLog** | `IFluxLogRepository` | 3 | `MoonPro_FluxContext` | +| 5 | **System** | `ISystemRepository` | 7 | `MoonProContext` + `MoonProAdminContext` | +| 6 | **MpVoc** | `IMpVocRepository` | 3 | `MoonPro_VocContext` | +| 7 | **MpMon** | `IMpMonRepository` | 4 | `MoonProContext` | +| 8 | **MpLand** | `IMpLandRepository` | 6 | `MoonProContext` | + +## Sostituzioni dbController Completate + +| File Originale | Sostituito con | Chiamate | Stato | +|---|---|---|---| +| **MpDataService.cs** | 5 repository (Anag, System, Dossier, FluxLog, Production) | ~90 | Completato | +| **TranslateSrv.cs** | `IMpVocRepository` | 7 | Completato | +| **StatusData.cs** | `IMpMonRepository` | 10 | Completato | +| **LandDataService.cs** | `IMpLandRepository` | 9 | Completato | +| **OrderDataSrv.cs** | System + Production | 2 | Completato | +| **ListSelectDataSrv.cs** | System + Production | 4 | Completato | + +## Architettura DI (DataServiceCollectionExtensions.cs) + +```csharp +// Repository Scoped +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +services.TryAddScoped(); +``` + +## File Modificati + +- `MP.Data/DataServiceCollectionExtensions.cs` (+10/-1) +- `MP.Data/Services/LandDataService.cs` (+10/-10) +- `MP.Data/Services/MonDataFeeder.cs` (+1/-1) +- `MP.Data/Services/StatusData.cs` (+12/-12) +- `MP.Data/Services/TabDataFeeder.cs` (+1/-1) +- `MP.Data/Services/TranslateSrv.cs` (+13/-13) +- `MP.SPEC/Data/MpDataService.cs` (+1/-3) + +## File Nuovi (6) + +- `MP.Data/Repository/MpLand/IMpLandRepository.cs` +- `MP.Data/Repository/MpLand/MpLandRepository.cs` +- `MP.Data/Repository/MpMon/IMpMonRepository.cs` +- `MP.Data/Repository/MpMon/MpMonRepository.cs` +- `MP.Data/Repository/MpVoc/IMpVocRepository.cs` +- `MP.Data/Repository/MpVoc/MpVocRepository.cs` + +## Verifiche + +- Nessun riferimento a `dbController.XXX()` nei file di servizio +- `ArticleWithDossierAsync` esportato correttamente (rimossi `#if false`) +- `VocabolarioGetLang` reso sincrono (firma originale sincrona) +- `tryLoadIobTags` in StatusData usa `GetAwaiter().GetResult()` (contesto sync) +- `InitDict` in TranslateSrv usa `GetAwaiter().GetResult()` (contesto sync) + +## MpSpecRepository (MpSpecController) + +I metodi原价 sono ancora visibili nel file ma: +- Non sono usati dai layer superiori (tutti migrati ai repository) +- Possono essere spostati a `#if false` come ultima fase di pulizia +- Rimangono come fallback documentato diff --git a/MP.SPEC/refactor_repository.pdf b/MP.SPEC/refactor_repository.pdf new file mode 100644 index 00000000..806fa38d Binary files /dev/null and b/MP.SPEC/refactor_repository.pdf differ diff --git a/MP.Stats/Components/ChartEnergy.razor b/MP.Stats/Components/ChartEnergy.razor index af03a9bb..9c5146f3 100644 --- a/MP.Stats/Components/ChartEnergy.razor +++ b/MP.Stats/Components/ChartEnergy.razor @@ -1,5 +1,4 @@ -@using ChartJs - +
      @if (RawData == null || RawData.Count == 0) { diff --git a/MP.Stats/Components/ChartJs/Chart.razor b/MP.Stats/Components/ChartJs/Chart.razor index 7be94585..abfd3f21 100644 --- a/MP.Stats/Components/ChartJs/Chart.razor +++ b/MP.Stats/Components/ChartJs/Chart.razor @@ -16,13 +16,13 @@ public ChartType Type { get; set; } [Parameter] - public string[]? Data { get; set; } + public string[] Data { get; set; } [Parameter] - public string[]? BackgroundColor { get; set; } + public string[] BackgroundColor { get; set; } [Parameter] - public string[]? Labels { get; set; } + public string[] Labels { get; set; } protected override async Task OnAfterRenderAsync(bool firstRender) { diff --git a/MP.Stats/Data/MpStatsService.cs b/MP.Stats/Data/MpStatsService.cs index 54e4803b..247fa567 100644 --- a/MP.Stats/Data/MpStatsService.cs +++ b/MP.Stats/Data/MpStatsService.cs @@ -11,6 +11,7 @@ using System.Data; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; namespace MP.Stats.Data { @@ -24,7 +25,11 @@ namespace MP.Stats.Data #region Public Constructors - public MpStatsService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) + public MpStatsService( + IConfiguration configuration, + IConnectionMultiplexer redConn, + IFusionCache cache + ) : base(configuration, cache, redConn) { Stopwatch sw = Stopwatch.StartNew(); sw.Start(); diff --git a/MP.Stats/MP.Stats.csproj b/MP.Stats/MP.Stats.csproj index 84ec23fb..6a9935f9 100644 --- a/MP.Stats/MP.Stats.csproj +++ b/MP.Stats/MP.Stats.csproj @@ -4,10 +4,14 @@ net8.0 MP.Stats 826e877c-ba70-4253-84cb-d0b1cafd4440 - 8.16.2605.0414 + 8.16.2606.0408 true en + + + $(NoWarn);1591 + diff --git a/MP.Stats/Resources/ChangeLog.html b/MP.Stats/Resources/ChangeLog.html index c29e503f..793e14ba 100644 --- a/MP.Stats/Resources/ChangeLog.html +++ b/MP.Stats/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo statistiche MAPO -

      Versione: 8.16.2605.0414

      +

      Versione: 8.16.2606.0408


      Note di rilascio:
        diff --git a/MP.Stats/Resources/VersNum.txt b/MP.Stats/Resources/VersNum.txt index 6b8be000..47fe7fc3 100644 --- a/MP.Stats/Resources/VersNum.txt +++ b/MP.Stats/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.0414 +8.16.2606.0408 diff --git a/MP.Stats/Resources/manifest.xml b/MP.Stats/Resources/manifest.xml index 58cf6bff..0a7e3eaa 100644 --- a/MP.Stats/Resources/manifest.xml +++ b/MP.Stats/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.0414 + 8.16.2606.0408 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.Stats/Startup.cs b/MP.Stats/Startup.cs index 3511f254..17c36165 100644 --- a/MP.Stats/Startup.cs +++ b/MP.Stats/Startup.cs @@ -1,10 +1,14 @@ -using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Localization; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; +using MP.Data; using MP.Data.Services; using MP.Stats.Data; using MP.TaskMan.Services; @@ -13,6 +17,10 @@ using System; using System.Globalization; using System.IO; using System.Reflection; +using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; +using ZiggyCreatures.Caching.Fusion.Backplane.StackExchangeRedis; +using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson; namespace MP.Stats { @@ -133,11 +141,35 @@ namespace MP.Stats var cString = Configuration.GetConnectionString("Redis"); string connStringRedis = cString ?? "localhost:6379, DefaultDatabase=5, connectTimeout=5000, syncTimeout=5000, asyncTimeout=5000, abortConnect=false, ssl=false"; // avvio oggetto shared x redis... - var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); + IConnectionMultiplexer redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); + + // ✅ FusionCache + services.AddFusionCache() + .WithDistributedCache(sp => sp.GetRequiredService()) + .WithSerializer(new FusionCacheNewtonsoftJsonSerializer()) + .WithBackplane(new RedisBackplane(new RedisBackplaneOptions + { + ConnectionMultiplexerFactory = () => Task.FromResult(redisMultiplexer) + })); // Add services x accesso dati services.AddSingleton(redisMultiplexer); + // aggiungo il costruttore x i vari DbContextFactory + var connStr = Configuration.GetConnectionString("MP.Stats") + ?? throw new InvalidOperationException("ConnString 'MP.Stats' mancante."); + services.AddDbContextFactory(options => + options.UseSqlServer(connStr) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + + var connStrVoc = Configuration.GetConnectionString("MP.Voc") + ?? throw new InvalidOperationException("ConnString 'MP.Voc' mancante."); + services.AddDbContextFactory(options => + options.UseSqlServer(connStrVoc) + .EnableSensitiveDataLogging(false) // true solo in Sviluppo + .ConfigureWarnings(w => w.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning))); + services.AddLocalization(); @@ -145,9 +177,11 @@ namespace MP.Stats services.AddServerSideBlazor(); services.AddSingleton(Configuration); + services.AddStatsDataLayer(); + //services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddScoped(); } diff --git a/MP.Stats/appsettings.json b/MP.Stats/appsettings.json index 0dc6bccb..56b81552 100644 --- a/MP.Stats/appsettings.json +++ b/MP.Stats/appsettings.json @@ -53,8 +53,6 @@ "ConnectionStrings": { "DefaultConnection": "Server=SQL2016DEV;Database=MoonPro_STATS;Trusted_Connection=True;MultipleActiveResultSets=true", "MP.Stats": "Server=SQL2016DEV;Database=MoonPro_STATS;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=MP.STATS;", - //"DefaultConnection": "Server=SQL2016DEV;Database=Jetco_MoonPro_STATS_Prod;Trusted_Connection=True;MultipleActiveResultSets=true", - //"MP.Stats": "Server=SQL2022PROD;Database=Jetco_MoonPro_STATS_Prod;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=MP.STATS;", "MP.Voc": "Server=SQL2016DEV;Database=MoonPro;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=MP.STATS;", "Redis": "redis.ufficio:26379,serviceName=devel,DefaultDatabase=5,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true" }, diff --git a/MP.TaskMan/Controllers/MpTaskController.cs b/MP.TaskMan/Controllers/MpTaskController.cs index 0ccb73bf..fadf73d4 100644 --- a/MP.TaskMan/Controllers/MpTaskController.cs +++ b/MP.TaskMan/Controllers/MpTaskController.cs @@ -2,16 +2,11 @@ using Microsoft.Extensions.Configuration; using MP.TaskMan.Models; using NLog; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using static MP.TaskMan.Objects.Enums; namespace MP.TaskMan.Controllers { - public class MpTaskController : IDisposable + public class MpTaskController { #region Public Constructors @@ -87,11 +82,7 @@ namespace MP.TaskMan.Controllers return dtNext; } - public void Dispose() - { - _configuration = null; - } - + /// /// Chiamata esecuzione di un singolo task programmato, SE in stato abilitato /// diff --git a/MP.TaskMan/Services/TaskService.cs b/MP.TaskMan/Services/TaskService.cs index 7727f72a..abbf331e 100644 --- a/MP.TaskMan/Services/TaskService.cs +++ b/MP.TaskMan/Services/TaskService.cs @@ -16,7 +16,7 @@ using static MP.TaskMan.Objects.Enums; namespace MP.TaskMan.Services { - public class TaskService : BaseServ, IDisposable + public class TaskService : BaseServ { #region Public Constructors @@ -88,15 +88,6 @@ namespace MP.TaskMan.Services #region Public Methods - public void Dispose() - { - // Clear database controller - MLController.Dispose(); - // redis dispose - redisConn = null; - redisDb = null; - } - /// /// Chiamata esecuzione di un singolo task programmato /// @@ -136,18 +127,22 @@ namespace MP.TaskMan.Services { var callResp = await RCallService.CallRestGet(TaskRec.Command, TaskRec.Args); DateTime dtEnd = DateTime.Now; - string formattedJson = JValue.Parse(callResp.Content).ToString(Formatting.Indented); - TaskExecModel tExeMod = new TaskExecModel() + if (callResp != null && !string.IsNullOrEmpty(callResp.Content)) { - DtEnd = dtEnd, - DtStart = dtStart, - IsError = callResp.StatusCode != System.Net.HttpStatusCode.OK, - TaskId = TaskRec.TaskId, - // deserializzazione come json indentato?!? - Result = formattedJson// $"{callResp.Content}".Replace("\"", ""), - }; - // salvo su DB - answ = MLController.TaskExecSaveExecuted(TaskRec.TaskId, SchedNext, tExeMod); + + string formattedJson = JValue.Parse(callResp.Content).ToString(Formatting.Indented); + TaskExecModel tExeMod = new TaskExecModel() + { + DtEnd = dtEnd, + DtStart = dtStart, + IsError = callResp.StatusCode != System.Net.HttpStatusCode.OK, + TaskId = TaskRec.TaskId, + // deserializzazione come json indentato?!? + Result = formattedJson// $"{callResp.Content}".Replace("\"", ""), + }; + // salvo su DB + answ = MLController.TaskExecSaveExecuted(TaskRec.TaskId, SchedNext, tExeMod); + } } break; diff --git a/MP.TaskMan/TaskExeList.razor.cs b/MP.TaskMan/TaskExeList.razor.cs index 2ffdad04..8fa45d62 100644 --- a/MP.TaskMan/TaskExeList.razor.cs +++ b/MP.TaskMan/TaskExeList.razor.cs @@ -95,8 +95,8 @@ namespace MP.TaskMan private static Logger Log = LogManager.GetCurrentClassLogger(); - private List ListRecords; - private List SearchRecords; + private List ListRecords = new(); + private List SearchRecords = new(); #endregion Private Fields @@ -112,19 +112,26 @@ namespace MP.TaskMan private async Task ReloadData() { - SearchRecords = await TService.TaskExecGetFilt(CurrRecord.TaskId, 1000, ""); - // se non tutti filtro... - if (ShowErrorMode != 0) + if (CurrRecord != null) { - if (ShowErrorMode == 1) + SearchRecords = await TService.TaskExecGetFilt(CurrRecord.TaskId, 1000, ""); + // se non tutti filtro... + if (ShowErrorMode != 0) { - SearchRecords = SearchRecords.FindAll(x => x.IsError); - } - else if (ShowErrorMode == 2) - { - SearchRecords = SearchRecords.FindAll(x => !x.IsError); + if (ShowErrorMode == 1) + { + SearchRecords = SearchRecords.FindAll(x => x.IsError); + } + else if (ShowErrorMode == 2) + { + SearchRecords = SearchRecords.FindAll(x => !x.IsError); + } } } + else + { + SearchRecords = new(); + } totalCount = SearchRecords.Count; ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList(); } diff --git a/MP.TaskMan/TaskList.razor.cs b/MP.TaskMan/TaskList.razor.cs index 09de8099..30eabb1a 100644 --- a/MP.TaskMan/TaskList.razor.cs +++ b/MP.TaskMan/TaskList.razor.cs @@ -205,8 +205,11 @@ namespace MP.TaskMan protected void ResetData() { - TService.rollBackEdit(currRecord); - currRecord = null; + if (currRecord != null) + { + TService.rollBackEdit(currRecord); + currRecord = null; + } } protected double righDiv(double num, double den) diff --git a/MP.TaskMan/TaskListTable.razor.cs b/MP.TaskMan/TaskListTable.razor.cs index 58d7f59f..2449ca37 100644 --- a/MP.TaskMan/TaskListTable.razor.cs +++ b/MP.TaskMan/TaskListTable.razor.cs @@ -10,10 +10,10 @@ namespace MP.TaskMan #region Public Properties [Parameter] - public int CodGroup { get; set; } = 0; + public List AllRecords { get; set; } = new List(); [Parameter] - public List AllRecords { get; set; } = new List(); + public int CodGroup { get; set; } = 0; [Parameter] public EventCallback EC_Cancel { get; set; } @@ -207,7 +207,6 @@ namespace MP.TaskMan private int currPage = 1; private TaskListModel? DetailTaskId = null; - private bool isLoading = false; private List ListRecords = new List(); private int maxOrdinal = 999; private int minOrdinal = 0; diff --git a/build_all_par.ps1 b/build_all_par.ps1 new file mode 100644 index 00000000..8d845d01 --- /dev/null +++ b/build_all_par.ps1 @@ -0,0 +1,167 @@ +# build_all_par.ps1 +# script per compilazione (parallela) progetti MAPO-CORE +# nb: prerequisito powershell >= 7, install con +# winget install Microsoft.PowerShell + + +# --- CONFIGURAZIONE --- +$pattern = "MP-*.sln" +$sharedProjectPath = ".\MP.Data\MP.Data.csproj" + +# Controllo robusto del parametro --agent (cerca in tutti gli argomenti passati) +$agentMode = $args -contains "--agent" + +# Avvia il cronometro per calcolare il tempo totale +$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() + +# 1. Trova l'MSBuild ufficiale di Visual Studio 2022 +$vsPaths = @(& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -version "[17.0,19.0)" -products * -requires Microsoft.Component.MSBuild -property installationPath) +# versione WKS-R9-SAM +# $vsPaths = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -version "[17.0,18.0)" -products * -requires Microsoft.Component.MSBuild -property installationPath +if (-not $vsPaths) { + if ($agentMode) { exit 1 } + Write-Host "❌ Impossibile trovare Visual Studio 2022!" -ForegroundColor Red + Exit +} +$msbuildPath = Join-Path $vsPaths[0] "MSBuild\Current\Bin\MSBuild.exe" + +if (-not $agentMode) { + Write-Host "🎯 Usando MSBuild di VS2022: $msbuildPath" -ForegroundColor Gray +} + +# Cerca tutte le soluzioni escludendo cartelle di build +$solutions = Get-ChildItem -Path . -Filter $pattern -Recurse | Where-Object { + $_.FullName -notmatch '\\(bin|obj|\\.git|\\.vs)\\.' +} + +if ($solutions.Count -eq 0) { + if ($agentMode) { exit 1 } + Write-Host "⚠️ Nessuna soluzione trovata che corrisponde al pattern: $pattern" -ForegroundColor Yellow + Exit +} + +if (-not $agentMode) { + Write-Host "🚀 Trovate $($solutions.Count) soluzioni univoche." -ForegroundColor Magenta +} + +# FASE 1: Compilazione preventiva del progetto comune +if (Test-Path $sharedProjectPath) { + if (-not $agentMode) { Write-Host "`n📦 Fase 1: Compilazione del progetto comune condiviso..." -ForegroundColor Cyan } + + # AGGIORNAMENTO: Se siamo in agentMode silenziamo completamente MSBuild (/v:q) e ridirigiamo l'output + if ($agentMode) { + & $msbuildPath $sharedProjectPath /p:Configuration=Release /v:q /nologo > $null 2>&1 + } + else { + & $msbuildPath $sharedProjectPath /p:Configuration=Release /v:m /nologo + } + + if ($LASTEXITCODE -ne 0) { + if (-not $agentMode) { Write-Host "❌ Errore critico: Impossibile compilare il progetto comune. Interruzione." -ForegroundColor Red } + exit 1 + } + if (-not $agentMode) { Write-Host "✅ Progetto comune pronto." -ForegroundColor Green } +} + +$numPar=3 + +# FASE 2: Compilazione parallela iniziale +if (-not $agentMode) { + Write-Host "`n🛠️ Fase 2: Avvio compilazione parallela delle soluzioni (Max $($numPar))..." -ForegroundColor Magenta + Write-Host "==================================================" -ForegroundColor Magenta +} + +$parallelResults = $solutions | ForEach-Object -Parallel { + $solName = $_.Name + $solPath = $_.FullName + $msb = $using:msbuildPath + + # Aggiunto /nologo per evitare intestazioni ripetute nei log interni + $log = & $msb $solPath /p:Configuration=Release /m:1 /p:BuildInParallel=false /v:m /nologo 2>&1 + + [PSCustomObject]@{ + Name = $solName + FullName = $solPath + Success = ($LASTEXITCODE -eq 0) + Log = $log + } +} -ThrottleLimit $numPar + +# --- ANALISI PRIMO ROUND E FASE 3 (RETRY SEQUENZIALE) --- +$successSolutions = @() +$failedToRetry = @() + +foreach ($res in $parallelResults) { + if ($res.Success) { + if (-not $agentMode) { Write-Host "✅ $($res.Name) compilata con successo (in parallelo)!" -ForegroundColor Green } + $successSolutions += $res.Name + } + else { + if (-not $agentMode) { Write-Host "⚠️ $($res.Name) fallita in parallelo. Accodata per il recupero sequenziale..." -ForegroundColor Yellow } + $failedToRetry += $res + } +} + +# Se ci sono falliti, li rieseguiamo UNO ALLA VOLTA pulendo la cache +if ($failedToRetry.Count -gt 0) { + if (-not $agentMode) { + Write-Host "`n🔄 Fase 3: Riesecuzione sequenziale dei task falliti ($($failedToRetry.Count) soluzioni)..." -ForegroundColor Magenta + Write-Host "==================================================" -ForegroundColor Magenta + } + + foreach ($failedRes in $failedToRetry) { + if (-not $agentMode) { Write-Host "⏳ Ripristino e compilazione sequenziale: $($failedRes.Name)..." -ForegroundColor Cyan } + + & $msbuildPath $failedRes.FullName /t:Restore /v:q /nologo > $null 2>&1 + & $msbuildPath $failedRes.FullName /t:Clean /v:q /p:Configuration=Release /nologo > $null 2>&1 + $retryLog = & $msbuildPath $failedRes.FullName /t:Build /p:Configuration=Release /v:m /nologo 2>&1 + + if ($LASTEXITCODE -eq 0) { + if (-not $agentMode) { Write-Host "✅ FALSO ALLARME: $($failedRes.Name) compilata correttamente in sequenziale!" -ForegroundColor Green } + $successSolutions += $failedRes.Name + } + else { + if (-not $agentMode) { Write-Host "❌ ERRORE REALE: $($failedRes.Name) è fallita anche in sequenziale." -ForegroundColor Red } + $failedRes.Log = $retryLog + } + } +} + +# Ferma il cronometro e calcola il tempo trascorso +$stopwatch.Stop() +$elapsedTime = "{0:mm\:ss}" -f $stopwatch.Elapsed + +# --- ELABORAZIONE DEI RISULTATI FINALI --- +$totalCount = $solutions.Count +$successCount = $successSolutions.Count +$failCount = $totalCount - $successCount +$failColor = if ($failCount -gt 0) { "Red" } else { "Gray" } + +# --- RIEPILOGO FINALE --- +if (-not $agentMode) { + Write-Host "`n==================================================" -ForegroundColor Magenta + Write-Host "🏁 Processo di verifica completato in $elapsedTime!" -ForegroundColor Magenta + Write-Host "==================================================" -ForegroundColor Magenta + Write-Host " Soluzioni Totali: $totalCount" -ForegroundColor White + Write-Host " Successi totali: $successCount" -ForegroundColor Green + Write-Host " Errori reali: $failCount" -ForegroundColor $failColor + Write-Host " Tempo impiegato: $elapsedTime" -ForegroundColor Cyan + + if ($failCount -gt 0) { + Write-Host "`n❌ Elenco delle soluzioni con ERRORI REALI:" -ForegroundColor Red + foreach ($res in $parallelResults) { + if ($successSolutions -notcontains $res.Name) { + Write-Host " - $($res.Name)" -ForegroundColor Red + Write-Host " 👉 Ultimi dettagli errore:" -ForegroundColor DarkRed + $res.Log | Where-Object { $_ -match "error" } | Select-Object -First 3 | Write-Host -ForegroundColor Gray + } + } + } + else { + Write-Host "`n🎉 Eccellente! Tutte le soluzioni compilano senza errori." -ForegroundColor Green + } + Write-Host "==================================================" -ForegroundColor Magenta +} + +# Exit code standard per ambienti automatizzati (0 = Successo, 1 = Fallimento) +if ($failCount -gt 0) { exit 1 } else { exit 0 } \ No newline at end of file