diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa07b88..beb4701 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,9 +11,9 @@ variables: - | $hasSource = C:\Tools\nuget.exe sources list | find "`"Steamware Nexus`"" /C if ($hasSource -eq 0) { - C:\Tools\nuget.exe sources Add -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"viaDante16`"" + C:\Tools\nuget.exe sources Add -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"$NEXUS_PASSWD`"" } else { - C:\Tools\nuget.exe sources Update -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"viaDante16`"" + C:\Tools\nuget.exe sources Update -Name "`"Steamware Nexus`"" -Source https://nexus.steamware.net/repository/nuget-group -username "`"nugetUser`"" -password "`"$NEXUS_PASSWD`"" } echo $hasSource @@ -27,7 +27,6 @@ variables: New-Item $Target".sha1" $MD5.Hash | Set-Content -Path $Target".md5" $SHA1.Hash | Set-Content -Path $Target".sha1" - echo "Created HASH files for $Target" # helper x send su NEXUS @@ -56,8 +55,6 @@ variables: mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file "Resources\manifest.xml" https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/manifest.xml mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file "Resources\ChangeLog.html" https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/ChangeLog.html -# mCurl -v -u $env:NEXUS_USER:$env:NEXUS_PASSWD --upload-file bin/release/$env:APP_NAME.zip $env:NEXUS_SERVER/utility/$env:NEXUS_PATH/$version/$env:APP_NAME-$version.zip - # helper x fix version number .version-fix: &version-fix - | diff --git a/EgwProxy.DataLayer/App.config b/EgwProxy.DataLayer/App.config new file mode 100644 index 0000000..10ebf98 --- /dev/null +++ b/EgwProxy.DataLayer/App.config @@ -0,0 +1,25 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EgwProxy.DataLayer/Controllers/LogMachineController.cs b/EgwProxy.DataLayer/Controllers/LogMachineController.cs new file mode 100644 index 0000000..a8f029b --- /dev/null +++ b/EgwProxy.DataLayer/Controllers/LogMachineController.cs @@ -0,0 +1,121 @@ +using EgwProxy.DataLayer.DbModel; +using EgwProxy.MagMan.DTO; +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Data.Entity.Infrastructure.Design.Executor; + +namespace EgwProxy.DataLayer.Controllers +{ + public class LogMachineController : IDisposable + { + #region Public Constructors + + /// + /// Init classe + /// + /// + public LogMachineController() + { + } + + #endregion Public Constructors + + #region Public Methods + + public void Dispose() + { + } + + /// + /// Helper conversione a LogMachineDTO + /// + /// + /// + /// + /// + /// + public static LogMachineDTO ConvToItemDto(LogMachineModel currRec, int keyNum, int machineCloudId, int projCloudId) + { + LogMachineDTO answ = new LogMachineDTO() + { + DtEvent = currRec.DtEvent, + EvType = (MagMan.MachLogTypes)currRec.EvType, + KeyNum = keyNum, + MachineCloudId = machineCloudId, + ProjCloudId = projCloudId, + VarAddress = currRec.VarAddress, + VarValue = currRec.VarValue + }; + return answ; + } + + /// + /// Recupero i dati in ordine crescente fino al num max indicato + /// + /// + /// + public List GetUnsentAsc(int numMax) + { + using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING)) + { + // retrieve + return localDbCtx + .DbSetLogMac + .Where(x => x.DtSent == null) + .OrderBy(x => x.DtEvent) + .Take(numMax) + .ToList(); + } + } + + + /// + /// Aggiorna i record indicati inserendo dataora corrente x DtSent + /// + /// + /// + public bool SetDtSent(List rec2upd) + { + bool done = false; + using (DatabaseContext localDbCtx = new DatabaseContext(DbConfig.CONNECTION_STRING)) + { + DateTime adesso = DateTime.Now; + foreach (var item in rec2upd) + { + var currRec = localDbCtx + .DbSetLogMac + .Where(x => x.DtSent == null && x.LogDbId == item.LogDbId) + .FirstOrDefault(); + if (currRec != null) + { + currRec.DtSent = adesso; + } + + + // indico modificato + localDbCtx.Entry(currRec).State = System.Data.Entity.EntityState.Modified; + + } + // Salvataggio finale + localDbCtx.SaveChanges(); + } + + return done; + } + + #endregion Public Methods + + #region Private Fields + + /// + /// Istanza logger + /// + private NLog.Logger Log = LogManager.GetCurrentClassLogger(); + + #endregion Private Fields + } +} \ No newline at end of file diff --git a/EgwProxy.DataLayer/Core/MachLog.cs b/EgwProxy.DataLayer/Core/MachLog.cs new file mode 100644 index 0000000..c7e7e71 --- /dev/null +++ b/EgwProxy.DataLayer/Core/MachLog.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EgwProxy.DataLayer.Core +{ + public class MachLog + { + public enum MachLogTypes + { + NULL = 0 + , PART_STATUS = 1 + , MACHGROUP_STATUS = 2 + , MACHINE_MODE = 3 + , MACHINE_STATUS = 4 + , MACHINE_COMMAND = 5 + , READ_VAR = 6 + , WRITE_VAR = 7 + , ALARM = 8 + , OPERATOR_MSG = 9 + , PROGRAM_SEND = 10 + } + } +} diff --git a/EgwProxy.DataLayer/DatabaseContext.cs b/EgwProxy.DataLayer/DatabaseContext.cs new file mode 100644 index 0000000..5930dfa --- /dev/null +++ b/EgwProxy.DataLayer/DatabaseContext.cs @@ -0,0 +1,49 @@ +using EgwProxy.DataLayer.DbModel; +using MySql.Data.EntityFramework; +using NLog; +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EgwProxy.DataLayer +{ + [DbConfigurationType(typeof(MySqlEFConfiguration))] + public partial class DatabaseContext : DbContext + { + #region Public Constructors + + public DatabaseContext(string currConnString) : base(currConnString) + { + connString = currConnString; + } + + #endregion Public Constructors + + #region Public Properties + + public virtual DbSet DbSetLogMac { get; set; } + + #endregion Public Properties + + #region Protected Methods + + + + #endregion Protected Methods + + #region Private Fields + + private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); + private string connString = ""; + + #endregion Private Fields + + #region Private Methods + + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/EgwProxy.DataLayer/DbConfig.cs b/EgwProxy.DataLayer/DbConfig.cs new file mode 100644 index 0000000..6d23cca --- /dev/null +++ b/EgwProxy.DataLayer/DbConfig.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EgwProxy.DataLayer +{ + public static class DbConfig + { + public static string DATABASE_NAME = "EgtBwDb"; + + public static int DATABASE_PROCESS_TIMEOUT = 5; + public static string DATABASE_PWD = "viacremasca"; + + // Database config + public static string DATABASE_SERV = "127.0.0.1"; + + public static string DATABASE_USER = "EgtUser"; + + /// + /// DB Connection string per azioni amministrative: + /// aggiunto parametro "allow user variables", da https://forums.mysql.com/read.php?38,609672,610320#msg-610320 + /// + public static string ADMIN_CONNECTION_STRING { get; set; } = ""; + + /// + /// DB Connection string, per effettuare migration riportare valore connessione admin cablato (server=localhost;port=3306;database=EgtBwDb_000102;uid=root;pwd=Egalware_24068!;) + /// + public static string CONNECTION_STRING { get; set; } = "server=localhost;port=3306;database=EgtBwDb_000470;uid=root;pwd=Egalware_24068!;allow user variables=true"; + } +} diff --git a/EgwProxy.DataLayer/DbModel/LogMachineModel.cs b/EgwProxy.DataLayer/DbModel/LogMachineModel.cs new file mode 100644 index 0000000..ea2c57e --- /dev/null +++ b/EgwProxy.DataLayer/DbModel/LogMachineModel.cs @@ -0,0 +1,56 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace EgwProxy.DataLayer.DbModel +{ + /// + /// Tabella dei LOG Macchina + /// + [Table("LogMachine")] + public class LogMachineModel + { + #region Public Properties + + /// + /// Chiave primaria evento LOG + /// + [Key, Column("DbId"), DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int LogDbId { get; set; } + + /// + /// Stato da enum Core + /// + [Column("EvType")] + public Core.MachLog.MachLogTypes EvType { get; set; } = Core.MachLog.MachLogTypes.NULL; + + /// + /// Data Evento + /// + [Column("DtEvent")] + public DateTime DtEvent { get; set; } = DateTime.Now; + + /// + /// Indirizzo VAR (Supervisore) + /// + [Column("VarAddress")] + public string VarAddress { get; set; } = ""; + + /// + /// Valore VAR + /// + [Column("VarValue")] + public string VarValue { get; set; } = ""; + + + /// + /// Data di invio evento (su cloud) + /// + [Column("DtSent")] + public DateTime? DtSent { get; set; } = null; + + + #endregion Public Properties + + } +} diff --git a/EgwProxy.DataLayer/EgwProxy.DataLayer.csproj b/EgwProxy.DataLayer/EgwProxy.DataLayer.csproj new file mode 100644 index 0000000..d28f771 --- /dev/null +++ b/EgwProxy.DataLayer/EgwProxy.DataLayer.csproj @@ -0,0 +1,135 @@ + + + + + + Debug + AnyCPU + {87935FC9-C1BC-4984-83CA-A9EDABBE2228} + Library + Properties + EgwProxy.DataLayer + EgwProxy.DataLayer + v4.7.2 + 512 + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\BouncyCastle.1.8.3.1\lib\BouncyCastle.Crypto.dll + + + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll + + + ..\packages\K4os.Compression.LZ4.1.1.11\lib\net46\K4os.Compression.LZ4.dll + + + ..\packages\K4os.Compression.LZ4.Streams.1.1.11\lib\net46\K4os.Compression.LZ4.Streams.dll + + + ..\packages\K4os.Hash.xxHash.1.0.6\lib\net46\K4os.Hash.xxHash.dll + + + ..\packages\MySql.Data.8.0.21\lib\net452\MySql.Data.dll + + + ..\packages\MySql.Data.EntityFramework.8.0.21\lib\net452\MySql.Data.EntityFramework.dll + + + ..\packages\NLog.5.2.8\lib\net46\NLog.dll + + + ..\packages\SSH.NET.2016.1.0\lib\net40\Renci.SshNet.dll + + + + ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll + + + + + + + + + + + + ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + + + + + + + + + ..\packages\MySql.Data.8.0.21\lib\net452\Ubiety.Dns.Core.dll + + + ..\packages\MySql.Data.8.0.21\lib\net452\Zstandard.Net.dll + + + + + + + + + + + + + + + + + {1696d7a5-765a-4d25-8d29-ca7345023479} + EgwProxy.MagMan + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/EgwProxy.DataLayer/Properties/AssemblyInfo.cs b/EgwProxy.DataLayer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9817416 --- /dev/null +++ b/EgwProxy.DataLayer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("EgwProxy.DataLayer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EgwProxy.DataLayer")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("87935fc9-c1bc-4984-83ca-a9edabbe2228")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/EgwProxy.DataLayer/packages.config b/EgwProxy.DataLayer/packages.config new file mode 100644 index 0000000..0a59926 --- /dev/null +++ b/EgwProxy.DataLayer/packages.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EgwProxy.MagMan.sln b/EgwProxy.MagMan.sln index 96190d3..6716d04 100644 --- a/EgwProxy.MagMan.sln +++ b/EgwProxy.MagMan.sln @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EgwProxy.MagMan", "EgwProxy EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TestWinFormVB", "TestWinFormVB\TestWinFormVB.vbproj", "{665C94F5-27A6-4CD0-9487-036D199CDC47}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EgwProxy.DataLayer", "EgwProxy.DataLayer\EgwProxy.DataLayer.csproj", "{87935FC9-C1BC-4984-83CA-A9EDABBE2228}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {665C94F5-27A6-4CD0-9487-036D199CDC47}.Debug|Any CPU.Build.0 = Debug|Any CPU {665C94F5-27A6-4CD0-9487-036D199CDC47}.Release|Any CPU.ActiveCfg = Release|Any CPU {665C94F5-27A6-4CD0-9487-036D199CDC47}.Release|Any CPU.Build.0 = Release|Any CPU + {87935FC9-C1BC-4984-83CA-A9EDABBE2228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87935FC9-C1BC-4984-83CA-A9EDABBE2228}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87935FC9-C1BC-4984-83CA-A9EDABBE2228}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87935FC9-C1BC-4984-83CA-A9EDABBE2228}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/EgwProxy.MagMan/DTO/LogMachineDTO.cs b/EgwProxy.MagMan/DTO/LogMachineDTO.cs new file mode 100644 index 0000000..1334029 --- /dev/null +++ b/EgwProxy.MagMan/DTO/LogMachineDTO.cs @@ -0,0 +1,54 @@ +using System; + +namespace EgwProxy.MagMan.DTO +{ + // + // This is here so CodeMaid doesn't reorganize this document + // + public class LogMachineDTO + { + + /// + /// Key di riferimento per il progetto + /// + public int KeyNum { get; set; } = 0; + + /// + /// ID Macchina (cloud) + /// + public int MachineCloudId { get; set; } = 0; + + /// + /// Key progetto (DB) / CLOUD + /// + public int ProjCloudId { get; set; } = 0; + +#if false + /// + /// ID del DB EgtBW, univoco con KeyNum, (DB) / istanza locale + /// + public int ProjLocalId { get; set; } = 0; +#endif + + /// + /// Stato da enum + /// + public MachLogTypes EvType { get; set; } = MachLogTypes.NULL; + + /// + /// Data Evento + /// + public DateTime DtEvent { get; set; } = DateTime.Now; + + /// + /// Indirizzo VAR (Supervisore) + /// + public string VarAddress { get; set; } = ""; + + /// + /// Valore VAR + /// + public string VarValue { get; set; } = ""; + + } +} diff --git a/EgwProxy.MagMan/DataSyncro.cs b/EgwProxy.MagMan/DataSyncro.cs index b192183..35a88b6 100644 --- a/EgwProxy.MagMan/DataSyncro.cs +++ b/EgwProxy.MagMan/DataSyncro.cs @@ -4,6 +4,7 @@ using NLog; using RestSharp; using System; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Threading; @@ -376,6 +377,77 @@ namespace EgwProxy.MagMan return await Task.FromResult(answ); } + /// + /// Invio elenco LogMachine da tab locale + /// + /// record da inviare + /// + public bool LogMachineSend(List rec2send) + { + bool answ = false; + if (rec2send != null && rec2send.Count > 0) + { + // cerco online + using (RestClient client = new RestClient(rcOptions)) + { + string MKeyEnc = HttpUtility.UrlEncode(RestToken); + // impacchetto dati x invio... + RestPayload.LogData newPayload = new RestPayload.LogData() + { + LogList = rec2send + }; + var jsonBody = JsonConvert.SerializeObject(newPayload); + var request = new RestRequest($"LogMachine/upsert/{MKeyEnc}", Method.Post).AddJsonBody(jsonBody); + var response = client.Post(request); + // controllo risposta + if (response.StatusCode == HttpStatusCode.OK) + { + Log.Debug($"LogMachineSend | #rec: {rec2send.Count} | Response StatusCode: {response.StatusCode} | content: {response.Content}"); + answ = true; + } + else + { + Log.Error($"LogMachineSend | #rec: {rec2send.Count} | Response StatusCode: {response.StatusCode} | content: {response.Content}"); + } + } + } + return answ; + } + + /// + /// Versione async Invio elenco LogMachine da tab locale + /// + /// record da inviare, se consumo Qty deve essere negativa + /// + public async Task LogMachineSendAsync(List rec2send) + { + bool answ = false; + // cerco online + using (RestClient client = new RestClient(rcOptions)) + { + string MKeyEnc = HttpUtility.UrlEncode(RestToken); + // impacchetto dati x invio... + RestPayload.LogData newPayload = new RestPayload.LogData() + { + LogList = rec2send + }; + var jsonBody = JsonConvert.SerializeObject(newPayload); + var request = new RestRequest($"LogMachine/upsert/{MKeyEnc}", Method.Post).AddJsonBody(jsonBody); + var response = await client.PostAsync(request); + // controllo risposta + if (response.StatusCode == HttpStatusCode.OK) + { + Log.Debug($"LogMachineSendAsync | #rec: {rec2send.Count} | Response StatusCode: {response.StatusCode} | content: {response.Content}"); + answ = true; + } + else + { + Log.Error($"LogMachineSendAsync | #rec: {rec2send.Count} | Response StatusCode: {response.StatusCode} | content: {response.Content}"); + } + } + return await Task.FromResult(answ); + } + /// /// Elenco Materiali dato RestToken /// @@ -587,8 +659,7 @@ namespace EgwProxy.MagMan } /// - /// Invio record Proj x upsert - /// record da inviare + /// Invio record Proj x upsert record da inviare /// /// ProjCloudId (essitente o nuovo) public int ProjectSend(ProjectDTO rec2send) @@ -610,7 +681,6 @@ namespace EgwProxy.MagMan if (response.StatusCode == HttpStatusCode.OK) { int.TryParse(response.Content, out answ); - } else { @@ -652,6 +722,82 @@ namespace EgwProxy.MagMan return await Task.FromResult(answ); } + /// + /// Verifica elenco di risorse associate ad un progetto + /// + /// DbId del progetto da inviare + /// tipo di registrazione da inviare (stima, consumo, ...) + /// DataOra di riferimento del record + /// record da inviare, se consumo Qty deve essere negativa + /// 0 = errore comunicazione / 1 = risorse invariate / 2 = risorse cambiate + public int ResourceCheck(int idxProjDbId, ProjResState recType, DateTime dtRif, List rec2send) + { + int answ = 0; + // cerco online + using (RestClient client = new RestClient(rcOptions)) + { + string MKeyEnc = HttpUtility.UrlEncode(RestToken); + // impacchetto dati x invio... + RestPayload.Resources newPayload = new RestPayload.Resources() + { + DtReq = dtRif, + ProjCloudId = idxProjDbId, + ReqState = recType, + ResourceList = rec2send + }; + var jsonBody = JsonConvert.SerializeObject(newPayload); + var request = new RestRequest($"Resources/check/{MKeyEnc}", Method.Post).AddJsonBody(jsonBody); + var response = client.Post(request); + // controllo risposta + if (response.StatusCode == HttpStatusCode.OK) + { + answ = response.Content == "EQUAL" ? 1 : 2; + } + else + { + Log.Error($"ResourceCheck | Response StatusCode: {response.StatusCode} | content: {response.Content}"); + } + } + return answ; + } + + /// + /// Versione async Verifica elenco di risorse associate ad un progetto + /// + /// DbId del progetto da inviare + /// tipo di registrazione da inviare (stima, consumo, ...) + /// record da inviare, se consumo Qty deve essere negativa + /// 0 = errore comunicazione / 1 = risorse invariate / 2 = risorse cambiate + public async Task ResourceCheckAsync(int idxProjDbId, ProjResState recType, List rec2send) + { + int answ = 0; + // cerco online + using (RestClient client = new RestClient(rcOptions)) + { + string MKeyEnc = HttpUtility.UrlEncode(RestToken); + // impacchetto dati x invio... + RestPayload.Resources newPayload = new RestPayload.Resources() + { + ProjCloudId = idxProjDbId, + ReqState = recType, + ResourceList = rec2send + }; + var jsonBody = JsonConvert.SerializeObject(newPayload); + var request = new RestRequest($"Resources/check/{MKeyEnc}", Method.Post).AddJsonBody(jsonBody); + var response = await client.PostAsync(request); + // controllo risposta + if (response.StatusCode == HttpStatusCode.OK) + { + answ = response.Content == "EQUAL" ? 1 : 2; + } + else + { + Log.Error($"ResourceCheckAsync | Response StatusCode: {response.StatusCode} | content: {response.Content}"); + } + } + return await Task.FromResult(answ); + } + /// /// Elenco risorse associate a progetto /// @@ -780,87 +926,15 @@ namespace EgwProxy.MagMan return await Task.FromResult(answ); } - - /// - /// Verifica elenco di risorse associate ad un progetto - /// - /// DbId del progetto da inviare - /// tipo di registrazione da inviare (stima, consumo, ...) - /// DataOra di riferimento del record - /// record da inviare, se consumo Qty deve essere negativa - /// 0 = errore comunicazione / 1 = risorse invariate / 2 = risorse cambiate - public int ResourceCheck(int idxProjDbId, ProjResState recType, DateTime dtRif, List rec2send) - { - int answ = 0; - // cerco online - using (RestClient client = new RestClient(rcOptions)) - { - string MKeyEnc = HttpUtility.UrlEncode(RestToken); - // impacchetto dati x invio... - RestPayload.Resources newPayload = new RestPayload.Resources() - { - DtReq = dtRif, - ProjCloudId = idxProjDbId, - ReqState = recType, - ResourceList = rec2send - }; - var jsonBody = JsonConvert.SerializeObject(newPayload); - var request = new RestRequest($"Resources/check/{MKeyEnc}", Method.Post).AddJsonBody(jsonBody); - var response = client.Post(request); - // controllo risposta - if (response.StatusCode == HttpStatusCode.OK) - { - answ = response.Content == "EQUAL" ? 1 : 2; - } - else - { - Log.Error($"ResourceCheck | Response StatusCode: {response.StatusCode} | content: {response.Content}"); - } - } - return answ; - } - - /// - /// Versione async Verifica elenco di risorse associate ad un progetto - /// - /// DbId del progetto da inviare - /// tipo di registrazione da inviare (stima, consumo, ...) - /// record da inviare, se consumo Qty deve essere negativa - /// 0 = errore comunicazione / 1 = risorse invariate / 2 = risorse cambiate - public async Task ResourceCheckAsync(int idxProjDbId, ProjResState recType, List rec2send) - { - int answ = 0; - // cerco online - using (RestClient client = new RestClient(rcOptions)) - { - string MKeyEnc = HttpUtility.UrlEncode(RestToken); - // impacchetto dati x invio... - RestPayload.Resources newPayload = new RestPayload.Resources() - { - ProjCloudId = idxProjDbId, - ReqState = recType, - ResourceList = rec2send - }; - var jsonBody = JsonConvert.SerializeObject(newPayload); - var request = new RestRequest($"Resources/check/{MKeyEnc}", Method.Post).AddJsonBody(jsonBody); - var response = await client.PostAsync(request); - // controllo risposta - if (response.StatusCode == HttpStatusCode.OK) - { - answ = response.Content == "EQUAL" ? 1 : 2; - } - else - { - Log.Error($"ResourceCheckAsync | Response StatusCode: {response.StatusCode} | content: {response.Content}"); - } - } - return await Task.FromResult(answ); - } - #endregion Public Methods #region Private Fields + /// + /// Istanza logger + /// + private static Logger Log = LogManager.GetCurrentClassLogger(); + /// /// URL dell'API x chiamate gestione licenze /// @@ -868,11 +942,6 @@ namespace EgwProxy.MagMan private int callTimeout = 500; - /// - /// Istanza logger - /// - private static Logger Log = LogManager.GetCurrentClassLogger(); - /// /// Opzioni standard di chiamata /// diff --git a/EgwProxy.MagMan/EgwProxy.MagMan.csproj b/EgwProxy.MagMan/EgwProxy.MagMan.csproj index fc5733a..eef5a43 100644 --- a/EgwProxy.MagMan/EgwProxy.MagMan.csproj +++ b/EgwProxy.MagMan/EgwProxy.MagMan.csproj @@ -86,6 +86,7 @@ + diff --git a/EgwProxy.MagMan/Enums.cs b/EgwProxy.MagMan/Enums.cs index 288e10e..be7a24a 100644 --- a/EgwProxy.MagMan/Enums.cs +++ b/EgwProxy.MagMan/Enums.cs @@ -12,27 +12,47 @@ namespace EgwProxy.MagMan BEAM = 1, WALL = 2 } + + public enum MachLogTypes + { + NULL = 0 + , PART_STATUS = 1 + , MACHGROUP_STATUS = 2 + , MACHINE_MODE = 3 + , MACHINE_STATUS = 4 + , MACHINE_COMMAND = 5 + , READ_VAR = 6 + , WRITE_VAR = 7 + , ALARM = 8 + , OPERATOR_MSG = 9 + , PROGRAM_SEND = 10 + } + public enum ProjResState { /// /// Registrazione consumo effettivo (update giacenza su tab RawItemList) /// Consumed = -1, + /// /// Non definito /// ND = 0, + /// /// Consumo stimato da nesting (solo simulazione) /// Estimated, + /// /// Consumo confermato (da ordinare) /// Confirmed, + /// /// Riservato (utile x calcolo quantità da ordinare) /// Reserved } -} +} \ No newline at end of file diff --git a/EgwProxy.MagMan/RestPayload.cs b/EgwProxy.MagMan/RestPayload.cs index c0c6ccd..0341b4f 100644 --- a/EgwProxy.MagMan/RestPayload.cs +++ b/EgwProxy.MagMan/RestPayload.cs @@ -83,6 +83,19 @@ namespace EgwProxy.MagMan #endregion Public Properties } + + public class LogData + { + #region Public Properties + + /// + /// Elenco record log x invio POST + /// + public List LogList { get; set; } + + #endregion Public Properties + } + #endregion Public Classes } } \ No newline at end of file diff --git a/MagMan.Core/DTO/LogMachineDTO.cs b/MagMan.Core/DTO/LogMachineDTO.cs new file mode 100644 index 0000000..432f0ec --- /dev/null +++ b/MagMan.Core/DTO/LogMachineDTO.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MagMan.Core.DTO +{ + // + // This is here so CodeMaid doesn't reorganize this document + // + public class LogMachineDTO + { + + /// + /// Key di riferimento per il progetto + /// + public int KeyNum { get; set; } = 0; + + /// + /// ID Macchina (cloud) + /// + public int MachineCloudId { get; set; } = 0; + + /// + /// Key progetto (DB) / CLOUD + /// + public int ProjCloudId { get; set; } = 0; + +#if false + /// + /// ID del DB EgtBW, univoco con KeyNum, (DB) / istanza locale + /// + public int ProjLocalId { get; set; } = 0; +#endif + + /// + /// Stato da enum + /// + public Enums.MachLogTypes EvType { get; set; } = Enums.MachLogTypes.NULL; + + /// + /// Data Evento + /// + public DateTime DtEvent { get; set; } = DateTime.Now; + + /// + /// Indirizzo VAR (Supervisore) + /// + public string VarAddress { get; set; } = ""; + + /// + /// Valore VAR + /// + public string VarValue { get; set; } = ""; + + } +} diff --git a/MagMan.Core/Enums.cs b/MagMan.Core/Enums.cs index 4df7c47..9bd8a9a 100644 --- a/MagMan.Core/Enums.cs +++ b/MagMan.Core/Enums.cs @@ -22,37 +22,57 @@ namespace MagMan.Core Request, } + public enum MachLogTypes + { + NULL = 0 + , PART_STATUS = 1 + , MACHGROUP_STATUS = 2 + , MACHINE_MODE = 3 + , MACHINE_STATUS = 4 + , MACHINE_COMMAND = 5 + , READ_VAR = 6 + , WRITE_VAR = 7 + , ALARM = 8 + , OPERATOR_MSG = 9 + , PROGRAM_SEND = 10 + } + public enum ProjResState { /// /// Registrazione consumo effettivo (update giacenza su tab RawItemList) /// Consumed = -1, + /// /// Non definito /// ND = 0, + /// /// Consumo stimato da nesting (solo simulazione) /// Estimated, + /// /// Consumo confermato (da ordinare) /// Confirmed, + /// /// Riservato (utile x calcolo quantità da ordinare) /// Reserved } +#if false public enum ResultTypes { NULL = 0, EXECUTED = 1, RESULT = 2 - } - + } +#endif #endregion Public Enums } diff --git a/MagMan.Core/RestPayload.cs b/MagMan.Core/RestPayload.cs index 1c1350f..9037417 100644 --- a/MagMan.Core/RestPayload.cs +++ b/MagMan.Core/RestPayload.cs @@ -35,6 +35,17 @@ namespace MagMan.Core #endregion Public Properties } + public class LogData + { + #region Public Properties + + /// + /// Elenco record log x invio POST + /// + public List LogList { get; set; } = new List(); + + #endregion Public Properties + } public class Materials { diff --git a/MagMan.Data.Tenant/Controllers/TenantController.cs b/MagMan.Data.Tenant/Controllers/TenantController.cs index f686906..5b4592f 100644 --- a/MagMan.Data.Tenant/Controllers/TenantController.cs +++ b/MagMan.Data.Tenant/Controllers/TenantController.cs @@ -12,6 +12,8 @@ using System.Linq; using System.Runtime.ConstrainedExecution; using System.Text; using System.Threading.Tasks; +using System.Xml; +using static MagMan.Core.Enums; using static Microsoft.EntityFrameworkCore.DbLoggerCategory; namespace MagMan.Data.Tenant.Controllers @@ -522,6 +524,62 @@ namespace MagMan.Data.Tenant.Controllers return done; } + /// + /// Elenco Materiali gestiti a magazzino formato DTO + /// + /// Stringa connessione (variabile x cliente) + /// idMacchina di cui si vuole log + /// num rec max da recuperare + /// + public List LogMacGetLast(string connString, int machineId, int numRec) + { + List dbResult = new List(); + using (MagManContext dbCtx = new MagManContext(connString)) + { + dbResult = dbCtx + .DbSetLogMac + .Where(x => x.MachineID == machineId) + .OrderByDescending(x => x.DtEvent) + .Take(numRec) + .ToList(); + } + return dbResult; + } + + public int LogMacUpdate(string connString, List recList) + { + int numMod = 0; + using (MagManContext dbCtx = new MagManContext(connString)) + { + try + { + // verifico record x data/progetto... + foreach (var item in recList) + { + // cerco + var recOld = dbCtx + .DbSetLogMac + .Where(x => x.DtEvent == item.DtEvent && x.ProjDbId == item.ProjDbId && x.MachineID == item.MachineID) + .FirstOrDefault(); + if (recOld == null) + { + dbCtx + .DbSetLogMac + .Add(item); + numMod++; + } + } + // salvo su DB + dbCtx.SaveChanges(); + } + catch (Exception exc) + { + Log.Error($"Eccezione in LogMacUpdate{Environment.NewLine}{exc}"); + } + } + return numMod; + } + /// /// Elimina Materiale da magazzino /// @@ -972,6 +1030,39 @@ namespace MagMan.Data.Tenant.Controllers return newId; } + /// + /// Recupera ultimo record attivo di un progetto/stato indicato + /// + /// Stringa connessione (variabile x cliente) + /// ID del progetto da cercare + /// Stato richiesta da cercare + /// + public RequestPlanModel ReqPlanGetLast(string connString, int ProjCloudId, ProjResState ResState) + { + RequestPlanModel dbResult = new RequestPlanModel(); ; + using (MagManContext dbCtx = new MagManContext(connString)) + { + try + { + /* + * Ricerca x Id corrispondente + * */ + var currData = dbCtx + .DbSetReqPlan + .Where(x => x.ProjDbId == ProjCloudId && x.ReqState == ResState && x.IsActive) + .OrderByDescending(x => x.DtRequest) + .FirstOrDefault(); + + dbResult = currData ?? new RequestPlanModel(); + } + catch (Exception exc) + { + Log.Error($"Eccezione in ReqPlanGetLast{Environment.NewLine}{exc}"); + } + } + return dbResult; + } + /// /// Aggiunge/Modifica un record ReqPlan /// @@ -1047,6 +1138,23 @@ namespace MagMan.Data.Tenant.Controllers return newId; } + /// + /// Converte il DTO in ResourceModel + /// + /// DTO di partenza + /// + public ResourceModel ResourceFromDto(ResourceDTO origItem, int reqId) + { + ResourceModel answ = new ResourceModel() + { + Qty = origItem.Qty, + RawItemId = origItem.RawItemCloudId, + RequestId = reqId, + ResourceId = 0 + }; + return answ; + } + /// /// Elenco risorse dato progetto e stato /// @@ -1139,22 +1247,6 @@ namespace MagMan.Data.Tenant.Controllers } return dbResult; } - /// - /// Converte il DTO in ResourceModel - /// - /// DTO di partenza - /// - public ResourceModel ResourceFromDto(ResourceDTO origItem, int reqId) - { - ResourceModel answ = new ResourceModel() - { - Qty = origItem.Qty, - RawItemId = origItem.RawItemCloudId, - RequestId = reqId, - ResourceId = 0 - }; - return answ; - } /// /// Aggiunge/Modifica un elenco di Resource (+ eventuali update giacenze) diff --git a/MagMan.Data.Tenant/DbModels/LogMachineModel.cs b/MagMan.Data.Tenant/DbModels/LogMachineModel.cs index 15e65fc..87dbc2d 100644 --- a/MagMan.Data.Tenant/DbModels/LogMachineModel.cs +++ b/MagMan.Data.Tenant/DbModels/LogMachineModel.cs @@ -24,15 +24,26 @@ namespace MagMan.Data.Tenant.DbModels [Key, Column("DbId"), DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int LogDbId { get; set; } + /// + /// Key di riferimento per il progetto + /// + public int KeyNum { get; set; } = 0; + /// /// Id macchina (diMagMan) /// public int MachineID { get; set; } = 0; /// - /// Key di riferimento per il progetto + /// Progetto di riferimento (CloudId) /// - public int KeyNum { get; set; } = 0; + public int ProjDbId { get; set; } + + /// + /// Data Registrazione + /// + [Column("DtEvent")] + public DateTime DtEvent { get; set; } = DateTime.Now; #if false /// @@ -101,8 +112,8 @@ namespace MagMan.Data.Tenant.DbModels /// /// Stato da enum Core /// - [Column("ResultType")] - public ResultTypes ResultType { get; set; } = ResultTypes.NULL; + [Column("EvType")] + public MachLogTypes EvType { get; set; } = MachLogTypes.NULL; /// /// Indirizzo VAR diff --git a/MagMan.Data.Tenant/MagManContext.cs b/MagMan.Data.Tenant/MagManContext.cs index 1eab0c9..31ba688 100644 --- a/MagMan.Data.Tenant/MagManContext.cs +++ b/MagMan.Data.Tenant/MagManContext.cs @@ -47,6 +47,7 @@ namespace MagMan.Data.Tenant public virtual DbSet DbSetReqPlan { get; set; } = null!; public virtual DbSet DbSetResources { get; set; } = null!; public virtual DbSet DbSetMovMag { get; set; } = null!; + public virtual DbSet DbSetLogMac { get; set; } = null!; diff --git a/MagMan.Data.Tenant/Migrations/20240427093933_AddLogMachine.Designer.cs b/MagMan.Data.Tenant/Migrations/20240427093933_AddLogMachine.Designer.cs new file mode 100644 index 0000000..bb5da54 --- /dev/null +++ b/MagMan.Data.Tenant/Migrations/20240427093933_AddLogMachine.Designer.cs @@ -0,0 +1,394 @@ +// +using System; +using MagMan.Data.Tenant; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MagMan.Data.Tenant.Migrations +{ + [DbContext(typeof(MagManContext))] + [Migration("20240427093933_AddLogMachine")] + partial class AddLogMachine + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.25") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.AliasModel", b => + { + b.Property("Family") + .HasColumnType("varchar(255)"); + + b.Property("ValueOriginal") + .HasColumnType("varchar(255)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ValueAlias") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Family", "ValueOriginal"); + + b.ToTable("AliasList"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.ConfigModel", b => + { + b.Property("KeyName") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnOrder(0); + + b.Property("Note") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("varchar(250)") + .HasColumnOrder(3); + + b.Property("Val") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnOrder(1); + + b.Property("ValStd") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnOrder(2) + .HasComment("Valore di default/riferimento per la variabile"); + + b.HasKey("KeyName"); + + b.ToTable("Config"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.LogMachineModel", b => + { + b.Property("LogDbId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("DbId"); + + b.Property("DtEvent") + .HasColumnType("datetime(6)") + .HasColumnName("DtEvent"); + + b.Property("EvType") + .HasColumnType("int") + .HasColumnName("EvType"); + + b.Property("KeyNum") + .HasColumnType("int"); + + b.Property("MachineID") + .HasColumnType("int"); + + b.Property("ProjDbId") + .HasColumnType("int"); + + b.Property("VarAddress") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("VarAddress"); + + b.Property("VarValue") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("VarValue"); + + b.HasKey("LogDbId"); + + b.HasIndex("KeyNum"); + + b.HasIndex("MachineID"); + + b.ToTable("LogMachine"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.MaterialModel", b => + { + b.Property("MatId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("HMm") + .HasColumnType("decimal(65,30)"); + + b.Property("LMm") + .HasColumnType("decimal(65,30)"); + + b.Property("MatCode") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MatDesc") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WMm") + .HasColumnType("decimal(65,30)"); + + b.HasKey("MatId"); + + b.ToTable("MaterialsList"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.MovMagModel", b => + { + b.Property("MovID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DtRec") + .HasColumnType("datetime(6)"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("QtyRec") + .HasColumnType("int"); + + b.Property("RawItemId") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("MovID"); + + b.HasIndex("RawItemId"); + + b.ToTable("MovMag"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.ProjModel", b => + { + b.Property("ProjDbId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BTLFileName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("DtCreated") + .HasColumnType("datetime(6)"); + + b.Property("DtLastAction") + .HasColumnType("datetime(6)"); + + b.Property("DtSchedule") + .HasColumnType("datetime(6)"); + + b.Property("DtStartProd") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsArchived") + .HasColumnType("tinyint(1)"); + + b.Property("KeyNum") + .HasColumnType("int"); + + b.Property("ListName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Machine") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MachineID") + .HasColumnType("int"); + + b.Property("PType") + .HasColumnType("int"); + + b.Property("ProcTimeEst") + .HasColumnType("double"); + + b.Property("ProcTimeReal") + .HasColumnType("double"); + + b.Property("ProjDescription") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ProjExtDbId") + .HasColumnType("int"); + + b.Property("ProjExtId") + .HasColumnType("int"); + + b.HasKey("ProjDbId"); + + b.HasIndex("IsActive"); + + b.HasIndex("IsArchived"); + + b.HasIndex("KeyNum"); + + b.HasIndex("MachineID"); + + b.HasIndex("ProjExtDbId"); + + b.ToTable("ProjList"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.RawItemModel", b => + { + b.Property("RawItemId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("HMm") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsRemn") + .HasColumnType("tinyint(1)"); + + b.Property("LMm") + .HasColumnType("decimal(65,30)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MatId") + .HasColumnType("int"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("QtyAvail") + .HasColumnType("int"); + + b.Property("WMm") + .HasColumnType("decimal(65,30)"); + + b.HasKey("RawItemId"); + + b.HasIndex("MatId"); + + b.ToTable("RawItemList"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.RequestPlanModel", b => + { + b.Property("RequestId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DtRequest") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ProjDbId") + .HasColumnType("int"); + + b.Property("ReqState") + .HasColumnType("int"); + + b.HasKey("RequestId"); + + b.ToTable("RequestPlan"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.ResourceModel", b => + { + b.Property("ResourceId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Qty") + .HasColumnType("int"); + + b.Property("RawItemId") + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.HasKey("ResourceId"); + + b.HasIndex("RawItemId"); + + b.HasIndex("RequestId"); + + b.ToTable("ResourceList"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.MovMagModel", b => + { + b.HasOne("MagMan.Data.Tenant.DbModels.RawItemModel", "ItemNav") + .WithMany() + .HasForeignKey("RawItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ItemNav"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.RawItemModel", b => + { + b.HasOne("MagMan.Data.Tenant.DbModels.MaterialModel", "MaterialNav") + .WithMany("RawItemList") + .HasForeignKey("MatId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("MaterialNav"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.ResourceModel", b => + { + b.HasOne("MagMan.Data.Tenant.DbModels.RawItemModel", "ItemNav") + .WithMany() + .HasForeignKey("RawItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("MagMan.Data.Tenant.DbModels.RequestPlanModel", "RequestNav") + .WithMany("ResourcesList") + .HasForeignKey("RequestId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ItemNav"); + + b.Navigation("RequestNav"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.MaterialModel", b => + { + b.Navigation("RawItemList"); + }); + + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.RequestPlanModel", b => + { + b.Navigation("ResourcesList"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MagMan.Data.Tenant/Migrations/20240427093933_AddLogMachine.cs b/MagMan.Data.Tenant/Migrations/20240427093933_AddLogMachine.cs new file mode 100644 index 0000000..03f3cb0 --- /dev/null +++ b/MagMan.Data.Tenant/Migrations/20240427093933_AddLogMachine.cs @@ -0,0 +1,52 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MagMan.Data.Tenant.Migrations +{ + public partial class AddLogMachine : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "LogMachine", + columns: table => new + { + DbId = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + KeyNum = table.Column(type: "int", nullable: false), + MachineID = table.Column(type: "int", nullable: false), + ProjDbId = table.Column(type: "int", nullable: false), + DtEvent = table.Column(type: "datetime(6)", nullable: false), + EvType = table.Column(type: "int", nullable: false), + VarAddress = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + VarValue = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_LogMachine", x => x.DbId); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_LogMachine_KeyNum", + table: "LogMachine", + column: "KeyNum"); + + migrationBuilder.CreateIndex( + name: "IX_LogMachine_MachineID", + table: "LogMachine", + column: "MachineID"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "LogMachine"); + } + } +} diff --git a/MagMan.Data.Tenant/Migrations/MagManContextModelSnapshot.cs b/MagMan.Data.Tenant/Migrations/MagManContextModelSnapshot.cs index 3aed6b0..638ee66 100644 --- a/MagMan.Data.Tenant/Migrations/MagManContextModelSnapshot.cs +++ b/MagMan.Data.Tenant/Migrations/MagManContextModelSnapshot.cs @@ -70,6 +70,49 @@ namespace MagMan.Data.Tenant.Migrations b.ToTable("Config"); }); + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.LogMachineModel", b => + { + b.Property("LogDbId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("DbId"); + + b.Property("DtEvent") + .HasColumnType("datetime(6)") + .HasColumnName("DtEvent"); + + b.Property("EvType") + .HasColumnType("int") + .HasColumnName("EvType"); + + b.Property("KeyNum") + .HasColumnType("int"); + + b.Property("MachineID") + .HasColumnType("int"); + + b.Property("ProjDbId") + .HasColumnType("int"); + + b.Property("VarAddress") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("VarAddress"); + + b.Property("VarValue") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("VarValue"); + + b.HasKey("LogDbId"); + + b.HasIndex("KeyNum"); + + b.HasIndex("MachineID"); + + b.ToTable("LogMachine"); + }); + modelBuilder.Entity("MagMan.Data.Tenant.DbModels.MaterialModel", b => { b.Property("MatId") diff --git a/MagMan.Data.Tenant/Services/TenantService.cs b/MagMan.Data.Tenant/Services/TenantService.cs index 8a9aa0a..2f3a970 100644 --- a/MagMan.Data.Tenant/Services/TenantService.cs +++ b/MagMan.Data.Tenant/Services/TenantService.cs @@ -17,6 +17,7 @@ using System.Runtime; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using static MagMan.Core.Enums; namespace MagMan.Data.Tenant.Services { @@ -242,7 +243,7 @@ namespace MagMan.Data.Tenant.Services public RawItemModel ItemFromDto(ItemDTO origItem, bool isActive, int nKey) { RawItemModel answ = ItemFromDto(origItem, isActive); - if(string.IsNullOrEmpty(answ.Note)) + if (string.IsNullOrEmpty(answ.Note)) { string cString = ConnString(nKey); var matRec = dbController.MaterialGetFilt(cString, origItem.MatCloudId, false).FirstOrDefault(); @@ -253,6 +254,7 @@ namespace MagMan.Data.Tenant.Services } return answ; } + /// /// Converte il DTO in ItemModel /// @@ -494,6 +496,106 @@ namespace MagMan.Data.Tenant.Services return fatto; } + /// + /// Converte il DTO in ItemModel + /// + /// DTO di partenza + /// + public LogMachineModel LogMacFromDto(LogMachineDTO origItem) + { + LogMachineModel answ = new LogMachineModel() + { + ProjDbId = origItem.ProjCloudId, + DtEvent = origItem.DtEvent, + EvType = origItem.EvType, + MachineID = origItem.MachineCloudId, + KeyNum = origItem.KeyNum, + VarAddress = origItem.VarAddress, + VarValue = origItem.VarValue + }; + + return answ; + } + + /// + /// Lista Projects gestiti a magazzino + /// + /// Key di riferimento + /// idMacchina di cui si vuole log + /// num rec max da recuperare + /// + public async Task> LogMacGetLast(int nKey, int machineId, int numRec) + { + string source = "DB"; + string cString = ConnString(nKey); + List? dbResult = new List(); + DateTime adesso = DateTime.Now; + try + { + // cache al minuto... + string currKey = $"{Const.rKeyConfig}:{nKey}:LogMacLast:{machineId}:{adesso:yyMMdd}::{adesso:HHmm}:{numRec}"; + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + string? rawData = await redisDb.StringGetAsync(currKey); + if (!string.IsNullOrEmpty(rawData)) + { + source = "REDIS"; + var tempResult = JsonConvert.DeserializeObject>(rawData); + if (tempResult == null) + { + dbResult = new List(); + } + else + { + dbResult = tempResult; + } + } + else + { + dbResult = dbController.LogMacGetLast(cString, machineId, numRec); + rawData = JsonConvert.SerializeObject(dbResult, JSSettings); + await redisDb.StringSetAsync(currKey, rawData, FastCache); + } + if (dbResult == null) + { + dbResult = new List(); + } + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Debug($"LogMacGetLast | {source} in: {ts.TotalMilliseconds} ms"); + } + catch (Exception exc) + { + Log.Error($"Error during LogMacGetLast:{Environment.NewLine}{exc}"); + } + return dbResult; + } + + /// + /// Aggiunge/Modifica un record Resource + /// + /// Key di riferimento + /// Elenco record da aggiungere/aggiornare + /// + public async Task LogMacUpdate(int nKey, List recList) + { + int newId = 0; + string cString = ConnString(nKey); + try + { + newId = dbController.LogMacUpdate(cString, recList); + if (newId > 0) + { + await FlushRedisCache(); + } + } + catch (Exception exc) + { + Log.Error($"Error during LogMacUpdate:{Environment.NewLine}{exc}"); + } + return newId; + } + /// /// Elimina Materiale da magazzino + refresh cache /// @@ -1148,6 +1250,29 @@ namespace MagMan.Data.Tenant.Services return prjCloudId; } + /// + /// Recupera ultimo record attivo ReqPlan x tipo richiesto + /// + /// Key di riferimento + /// ID del progetto da cercare + /// Stato richiesta da cercare + /// Record cercato o default se non trovato + public RequestPlanModel ReqPlanGetLast(int nKey, int ProjCloudId, ProjResState ResState) + { + RequestPlanModel lastRec = new RequestPlanModel(); + string cString = ConnString(nKey); + try + { + // cerco record (se fosse con valori "ini" p non trovata + lastRec = dbController.ReqPlanGetLast(cString, ProjCloudId, ResState); + } + catch (Exception exc) + { + Log.Error($"Error during ReqPlanGetLast:{Environment.NewLine}{exc}"); + } + return lastRec; + } + /// /// Aggiunge/Modifica un record ReqPlan /// diff --git a/MagMan.UI/Areas/Identity/Pages/Account/ForgotPassword.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/ForgotPassword.cshtml index 43aa112..77d93fd 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/ForgotPassword.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/ForgotPassword.cshtml @@ -1,26 +1,71 @@ @page @model ForgotPasswordModel @{ - ViewData["Title"] = "Forgot your password?"; + ViewData["Title"] = "Password dimenticata?"; } -

@ViewData["Title"]

-

Enter your email.

-
-
-
-
-
-
- - - -
- -
-
+ +
+

@ViewData["Title"]

+
+
+
+
+
+ EgtBeam&Wall +
+
+ Powered by +
+
+ +
+
+ EgalWare +
+
+
+
+
+
+
+
+

Inserisci email.

+
+
+
+ + + +
+
+ +
+ +
+
+
+
+
+ +
+ + @section Scripts { } diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml index 660620d..957a125 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml @@ -2,83 +2,75 @@ @model LoginModel @{ - ViewData["Title"] = "Log in"; + ViewData["Title"] = "MagMan"; } -
-

@ViewData["Title"]

-
-
-
-

Use a local account to log in.

-
-
-
- - - +
+

@ViewData["Title"]

+
+
+
+
+
+
+ EgtBeam&Wall
-
- - - +
+ Powered by
-
-
- -
+
+
-
- +
+ EgalWare
-
- - -
-
- @*
-
-

Use another service to log in.

-
- @{ - if ((Model.ExternalLogins?.Count ?? 0) == 0) - { -
-

- There are no external authentication services configured. See this article - about setting up this ASP.NET application to support logging in via external services. -

-
- } - else - { -
+
+
+
+
+
+
+ +

Login Utente

+
+
+
+ + + +
+
+ + + +
+
+
+ +
+
+
+ +

- @foreach (var provider in Model.ExternalLogins!) - { - - } + Password dimenticata? +

+

+ Registra nuovo utente +

+

+ Reinvia email di conferma

- } - } -
- *@ + + + + @section Scripts { diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml.cs b/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml.cs index 7584b6d..b77be36 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/MagMan.UI/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -160,7 +160,7 @@ namespace MagMan.UI.Areas.Identity.Pages.Account /// intended to be used directly from your code. This API may change or be removed in /// future releases. /// - [Display(Name = "Remember me?")] + [Display(Name = "Ricordami")] public bool RememberMe { get; set; } #endregion Public Properties diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml index d130b8e..5a316fb 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml @@ -8,7 +8,7 @@

@ViewData["Title"]

-
+
diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/Email.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/Email.cshtml index 9464333..cae0b8f 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/Email.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/Email.cshtml @@ -8,7 +8,7 @@

@ViewData["Title"]

-
+
@if (Model.IsEmailConfirmed) diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/Index.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/Index.cshtml index 1d0e00f..12e8a0c 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/Index.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/Index.cshtml @@ -8,7 +8,7 @@

@ViewData["Title"]

-
+
@@ -20,7 +20,7 @@
- +
diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml index 0835493..f281f4f 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml @@ -8,16 +8,17 @@

@ViewData["Title"]

-
+

Your account contains personal data that you have given us. This page allows you to download or delete that data.

-

+

+ +
+
+

Deleting this data will permanently remove your account, and this cannot be recovered.

-
- -

- Delete + Delete

diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml index dd5827f..edc50fd 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml @@ -12,7 +12,7 @@ account so you can log in without an external login.

-
+
diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/_Layout.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/_Layout.cshtml index fb77735..937fa18 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/_Layout.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/_Layout.cshtml @@ -1,5 +1,5 @@ @{ - if (ViewData.TryGetValue("ParentLayout", out var parentLayout) && parentLayout != null) + if (ViewData.TryGetValue("ParentLayout", out var parentLayout) && parentLayout != null) { Layout = parentLayout.ToString(); } @@ -9,21 +9,41 @@ } } -

Manage your account

- -
-

Change your account settings

-
-
-
- +
+

Gestione account

+
+
+
+
+
+
+
+ EgtBeam&Wall +
+ +
+
+ Powered by +
+
+ +
+
+ EgalWare +
+
-
- @RenderBody() +
+
+
+
+ @RenderBody() +
+
@section Scripts { @RenderSection("Scripts", required: false) -} +} \ No newline at end of file diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml index 59b1bb1..db558d1 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml @@ -10,6 +10,6 @@ { } - + @* *@ diff --git a/MagMan.UI/Areas/Identity/Pages/Account/Register.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/Register.cshtml index e8ff83b..a63b556 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/Register.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/Register.cshtml @@ -1,67 +1,74 @@ @page @model RegisterModel @{ - ViewData["Title"] = "Register"; + ViewData["Title"] = "Registrazione"; } +

@ViewData["Title"]

+
-
-
- -

Create a new account.

-
-
-
- - - + +
+
+
+
+
+ EgtBeam&Wall +
+
+ Powered by +
+
+ +
+
+ EgalWare +
-
- - - -
-
- - - -
- - -
-
-
-

Use another service to register.

-
- @{ - if ((Model.ExternalLogins?.Count ?? 0) == 0) - { -
-

- There are no external authentication services configured. See this article - about setting up this ASP.NET application to support logging in via external services. -

-
- } - else - { -
+
+
+
+
+
+ +

Nuovo Account

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+

- @foreach (var provider in Model.ExternalLogins!) - { - - } + Hai già un profilo? Clicca qui +

+

+ Password dimenticata? +

+

+ Reinvia email di conferma

- } - } - +
+
+
-
+
@section Scripts { } diff --git a/MagMan.UI/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml b/MagMan.UI/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml index ccce148..507545d 100644 --- a/MagMan.UI/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml +++ b/MagMan.UI/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml @@ -1,26 +1,72 @@ @page @model ResendEmailConfirmationModel @{ - ViewData["Title"] = "Resend email confirmation"; + ViewData["Title"] = "Reinvio email di conferma"; } -

@ViewData["Title"]

-

Enter your email.

-
-
-
-
-
-
- - - -
- -
-
+ + +
+

@ViewData["Title"]

+ + +
+
+
+
+
+ EgtBeam&Wall +
+
+ Powered by +
+
+ +
+
+ EgalWare +
+
+
+
+
+
+
+
+

Inserisci l'email

+
+
+
+ + + +
+
+ +
+ +
+
+
+
+
+ +
@section Scripts { } diff --git a/MagMan.UI/Components/AliasEdit.razor b/MagMan.UI/Components/AliasEdit.razor index bb2cc09..86b8950 100644 --- a/MagMan.UI/Components/AliasEdit.razor +++ b/MagMan.UI/Components/AliasEdit.razor @@ -8,7 +8,14 @@
- +
diff --git a/MagMan.UI/Components/AliasEdit.razor.cs b/MagMan.UI/Components/AliasEdit.razor.cs index bddfec8..3a7867d 100644 --- a/MagMan.UI/Components/AliasEdit.razor.cs +++ b/MagMan.UI/Components/AliasEdit.razor.cs @@ -63,6 +63,26 @@ namespace MagMan.UI.Components } } + protected override async Task OnParametersSetAsync() + { + await ReloadData(); + } + + private List ListAliasTarget { get; set; } = new List(); + private List AllMaterials { get; set; } = new List(); + protected async Task ReloadData() + { + // rileggo TUTTI i materiali + AllMaterials = await TService.MaterialDtoGetAll(KeyNum, false); + // proietto elenco alias ammissibili + ListAliasTarget = AllMaterials + .GroupBy(x => x.MatCode) + .Select(grp=> grp.First()) + .OrderBy(x => x.MatCode) + .Select(x => x.MatCode) + .ToList(); + } + #endregion Protected Methods } } \ No newline at end of file diff --git a/MagMan.UI/Components/MaterialMan.razor.cs b/MagMan.UI/Components/MaterialMan.razor.cs index 191dec5..9f4d095 100644 --- a/MagMan.UI/Components/MaterialMan.razor.cs +++ b/MagMan.UI/Components/MaterialMan.razor.cs @@ -109,12 +109,13 @@ namespace MagMan.UI.Components if (selItem != null) { MaterialId = selItem.MatCloudId; + E_MaterialSel.InvokeAsync(TService.MaterialFromDto(selItem)); } else { MaterialId = 0; + E_MaterialSel.InvokeAsync(null); } - E_MaterialSel.InvokeAsync(TService.MaterialFromDto(selItem)); } protected async Task ForceReload(bool force) diff --git a/MagMan.UI/Components/SetupDiagnostics.razor b/MagMan.UI/Components/SetupDiagnostics.razor index e0b04ba..eec09ea 100644 --- a/MagMan.UI/Components/SetupDiagnostics.razor +++ b/MagMan.UI/Components/SetupDiagnostics.razor @@ -55,7 +55,7 @@ return model.Password == "f@mmiEntrare!"; } } - protected bool DbLogOk { get; set; } = false; + protected bool DbCustOk { get; set; } = false; protected bool DbAllOk { get; set; } = false; protected bool DbIdentity { get; set; } = false; protected bool processRunning { get; set; } = false; @@ -88,10 +88,10 @@ protected async Task ReloadData() { var resultIden = await Health.Checks.DbIdentity(MagMan.Data.Admin.DbConfig.DATABASE_NAME); - var resultLog = await Health.Checks.DbPlantTable(MagMan.Data.Tenant.DbConfig.DATABASE_NAME); + var resultCustCnt = await Health.Checks.CustomersCount(); DbIdentity = (resultIden.Status == HealthStatus.Healthy); - DbLogOk = (resultLog.Status == HealthStatus.Healthy); - DbAllOk = (DbLogOk && DbIdentity); + DbCustOk = (resultCustCnt.Status == HealthStatus.Healthy); + DbAllOk = (DbCustOk && DbIdentity); } } \ No newline at end of file diff --git a/MagMan.UI/Controllers/AliasController.cs b/MagMan.UI/Controllers/AliasController.cs index 6789d7d..2e818b0 100644 --- a/MagMan.UI/Controllers/AliasController.cs +++ b/MagMan.UI/Controllers/AliasController.cs @@ -52,7 +52,7 @@ namespace MagMan.UI.Controllers [HttpGet] public async Task> Get() { - // se non ho chaive --> vuoto! + // se non ho chiave --> vuoto! List ListRecords = new List(); await Task.Delay(100); return ListRecords; diff --git a/MagMan.UI/Controllers/KeysController.cs b/MagMan.UI/Controllers/KeysController.cs index 9dee97b..3d78728 100644 --- a/MagMan.UI/Controllers/KeysController.cs +++ b/MagMan.UI/Controllers/KeysController.cs @@ -37,7 +37,7 @@ namespace MagMan.UI.Controllers [HttpGet] public async Task> Get() { - // se non ho chaive --> vuoto! + // se non ho chiave --> vuoto! List ListRecords = new List(); await Task.Delay(100); return ListRecords; diff --git a/MagMan.UI/Controllers/LogMachineController.cs b/MagMan.UI/Controllers/LogMachineController.cs new file mode 100644 index 0000000..38cf552 --- /dev/null +++ b/MagMan.UI/Controllers/LogMachineController.cs @@ -0,0 +1,138 @@ +using MagMan.Core.DTO; +using MagMan.Core; +using MagMan.Data.Admin.DbModels; +using MagMan.Data.Admin.Services; +using MagMan.Data.Tenant.Services; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using NLog; +using MagMan.Data.Tenant.DbModels; + +namespace MagMan.UI.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class LogMachineController : ControllerBase + { + #region Public Constructors + + public LogMachineController(MTAdminService MTDataService, TenantService TDataService) + { + MTAdmService = MTDataService; + TService = TDataService; + // json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/ + JSSettings = new JsonSerializerSettings() + { + ReferenceLoopHandling = ReferenceLoopHandling.Ignore + }; + Log.Info("Avviata classe LogMachineController"); + } + + #endregion Public Constructors + + #region Public Methods + + /// + /// Controllo status Alive + /// GET: api/LogMachine/alive + /// + /// + [HttpGet("alive")] + public string alive() + { + return $"OK"; + } + + // GET api/LogMachine + [HttpGet] + public async Task> Get() + { + // se non ho chiave --> vuoto! + List ListRecords = new List(); + await Task.Delay(100); + return ListRecords; + } + + /// + /// Elenco ultimi valori LogMachineModel dato RestToken + /// + /// Rest Token cliente + /// Chiave associata ai progetti + /// idMacchina di cui si vuole log + /// num rec max da recuperare + /// + // GET api/LogMachine/2cba60c7-7be4-40b1-aa0d-52e7c71fc1a7 + [HttpGet("{id}")] + public async Task> Get(string id, int KeyNum, int machineId, int numRec) + { + List ListRecords = new List(); + if (!string.IsNullOrEmpty(id)) + { + // in primis recupero codice chiave da token... + int nKey = await MTAdmService.MainKeyByToken(id); + var rawList = await TService.LogMacGetLast(nKey, machineId,numRec); + if(rawList!=null) + { + ListRecords.AddRange(rawList); + } + } + return ListRecords; + } + + /// + /// Processa una chiamata POST per l'invio di un oggetto di upsert progetto + /// PUT: api/Inventory/upsert/00000000-0000-0000-0000-000000000000 + /// + /// token comunicazione + /// ID del progetto creato da usare come CloudId + [HttpPost("upsert/{id}")] + public async Task upsert(string id, [FromBody] RestPayload.LogData rawData) + { + int answ = 0; + // verifico ci sia valore + if (!string.IsNullOrEmpty(id) && rawData != null && rawData.LogList != null) + { + // in primis recupero codice chiave da token... + int nKey = await MTAdmService.MainKeyByToken(id); + if (nKey > 0) + { + // converto elenco da Dto --> DB + var listRec = rawData.LogList.Select(x=> TService.LogMacFromDto(x)).ToList(); + try + { + // upsert! + answ = await TService.LogMacUpdate(nKey, listRec); + } + catch (Exception exc) + { + Log.Error($"LogMachineController.upsert | Errore in fase salvataggio di {rawData.LogList.Count} LogMacDTO{Environment.NewLine}{exc}"); + } + // resetto cache redis + await MTAdmService.FlushRedisCache(); + } + } + return answ; + } + + #endregion Public Methods + + #region Private Fields + + private static JsonSerializerSettings? JSSettings; + + /// + /// Classe per logging + /// + private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); + + #endregion Private Fields + + #region Private Properties + + private MTAdminService MTAdmService { get; set; } = null!; + private TenantService TService { get; set; } = null!; + + #endregion Private Properties + } +} diff --git a/MagMan.UI/Controllers/MachinesController.cs b/MagMan.UI/Controllers/MachinesController.cs index e820228..da54e75 100644 --- a/MagMan.UI/Controllers/MachinesController.cs +++ b/MagMan.UI/Controllers/MachinesController.cs @@ -37,7 +37,7 @@ namespace MagMan.UI.Controllers [HttpGet] public async Task> Get() { - // se non ho chaive --> vuoto! + // se non ho chiave --> vuoto! List ListRecords = new List(); await Task.Delay(100); return ListRecords; diff --git a/MagMan.UI/Controllers/MaterialsController.cs b/MagMan.UI/Controllers/MaterialsController.cs index 6d512f3..9fd372f 100644 --- a/MagMan.UI/Controllers/MaterialsController.cs +++ b/MagMan.UI/Controllers/MaterialsController.cs @@ -51,7 +51,7 @@ namespace MagMan.UI.Controllers [HttpGet] public async Task> Get() { - // se non ho chaive --> vuoto! + // se non ho chiave --> vuoto! List ListRecords = new List(); await Task.Delay(100); return ListRecords; diff --git a/MagMan.UI/Controllers/ProjectsController.cs b/MagMan.UI/Controllers/ProjectsController.cs index c624242..8bb8e48 100644 --- a/MagMan.UI/Controllers/ProjectsController.cs +++ b/MagMan.UI/Controllers/ProjectsController.cs @@ -38,21 +38,20 @@ namespace MagMan.UI.Controllers /// /// Controllo status Alive - /// GET: api/Machines/alive + /// GET: api/Projects/alive /// /// [HttpGet("alive")] public string alive() { - //Log.Debug("Chiamata alive"); return $"OK"; } - // GET api/Machines/5 + // GET api/Projects/5 [HttpGet] public async Task> Get() { - // se non ho chaive --> vuoto! + // se non ho chiave --> vuoto! List ListRecords = new List(); await Task.Delay(100); return ListRecords; @@ -64,7 +63,7 @@ namespace MagMan.UI.Controllers /// Rest Token cliente /// Chiave associata ai progetti /// - // GET api/Machines/2cba60c7-7be4-40b1-aa0d-52e7c71fc1a7 + // GET api/Projects/2cba60c7-7be4-40b1-aa0d-52e7c71fc1a7 [HttpGet("{id}")] public async Task> Get(string id, int KeyNum) { @@ -86,7 +85,7 @@ namespace MagMan.UI.Controllers /// Chiave associata ai progetti /// Key del proj /// - // GET api/Machines/2cba60c7-7be4-40b1-aa0d-52e7c71fc1a7 + // GET api/Projects/2cba60c7-7be4-40b1-aa0d-52e7c71fc1a7 [HttpGet("single/{id}")] public async Task GetSingle(string id, int ProjCloudId) { diff --git a/MagMan.UI/Controllers/ResourcesController.cs b/MagMan.UI/Controllers/ResourcesController.cs index 6ed0759..fc496b3 100644 --- a/MagMan.UI/Controllers/ResourcesController.cs +++ b/MagMan.UI/Controllers/ResourcesController.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using NLog; +using System.Linq; namespace MagMan.UI.Controllers { @@ -16,13 +17,8 @@ namespace MagMan.UI.Controllers [ApiController] public class ResourcesController : ControllerBase { - /// - /// Classe per logging - /// - private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); - private MTAdminService MTAdmService { get; set; } = null!; - private static JsonSerializerSettings? JSSettings; - private TenantService TService { get; set; } = null!; + #region Public Constructors + public ResourcesController(MTAdminService MTDataService, TenantService TDataService) { MTAdmService = MTDataService; @@ -35,6 +31,10 @@ namespace MagMan.UI.Controllers Log.Info("Avviata classe ResourcesController"); } + #endregion Public Constructors + + #region Public Methods + /// /// Controllo status Alive /// GET: api/Resources/alive @@ -47,18 +47,106 @@ namespace MagMan.UI.Controllers return $"OK"; } + /// + /// Processa una chiamata POST per la verifica di un oggetto di TRACKING risorse progetto (RestPayload.Resources) + /// PUT: api/Resources/check/00000000-0000-0000-0000-000000000000 + /// + /// token comunicazione + /// + /// restituisce diversi valori secondo esito: ND/EQUAL/CHANGED, dove | ND = non definito / + /// non calcolato | EQUAL = il set inviato èidentico all'ultimo registrato (in termini di + /// numero barre impiegate complessivo e per singolo tipo, check da CloudId barre) | CHANGED + /// = il set inviato è differente (per tipo/numero/mix di barre) + /// + [HttpPost("check/{id}")] + public async Task check(string id, [FromBody] RestPayload.Resources projectData) + { + string answ = "ND"; + bool isEqual = false; + // verifico ci sia valore + if (!string.IsNullOrEmpty(id) && projectData != null) + { + // in primis recupero codice chiave da token... + int nKey = await MTAdmService.MainKeyByToken(id); + if (nKey > 0) + { + // nel projData ho le info x gestire aggiornamento PER INTERO + int ProjCloudId = projectData.ProjCloudId; + // proseguo solo se ho un Id valido + if (ProjCloudId > 0) + { + // inizio dal num risorse DTO... se vuoto è sempre FALSE + int numResDTO = 0; + if (projectData.ResourceList == null || projectData.ResourceList.Count == 0) + { + // confermo che NON corrisponde + isEqual = false; + } + else + { + numResDTO = projectData.ResourceList.Count; + // recupero ultimo set ricevuto... + var lastRecPlan = TService.ReqPlanGetLast(nKey, ProjCloudId, Enums.ProjResState.Estimated); + // se non corrisponde ProjId --> false + if (lastRecPlan == null || lastRecPlan.ProjDbId != ProjCloudId) + { + // confermo che NON corrisponde + isEqual = false; + } + // altrimenti verifico contenuto come barre + else + { + // ora recupero risorse associate alla registrazione ricevuta... + var lastResList = await TService.ResourcesGetByProject(nKey, ProjCloudId, true, false); + // se lista vuota + if (lastResList == null || lastResList.Count == 0) + { + // confermo che NON corrisponde + isEqual = false; + } + else + { + //...o se num tot != numResDto --> false + if (lastResList.Count != numResDTO) + { + // confermo che NON corrisponde + isEqual = false; + } + else + { + // altrimenti check CloudId barre + quantità x equality... + // inizio convertendo + List listRes = projectData.ResourceList.Select(x => TService.ResourceFromDto(x, lastRecPlan.RequestId)).ToList(); + // dato x scontato che ho stesso numero di barre --> + // confronto 1-1 per quantità... genero i 2 set + Dictionary list2check = projectData.ResourceList.ToDictionary(x => x.RawItemCloudId, x => x.Qty); + Dictionary listSaved = lastResList.ToDictionary(x => x.RawItemId, x => x.Qty); + // comparazione finale! + isEqual = DictComparer(list2check, listSaved); + //isEqual= list2check.Count == listSaved.Count && !list2check.Except(listSaved).Any(); + } + } + } + } + } + } + answ = isEqual ? "EQUAL" : "CHANGED"; + } + return answ; + } + // GET api/Resources/5 [HttpGet] public async Task> Get() { - // se non ho chaive --> vuoto! + // se non ho chiave --> vuoto! List ListRecords = new List(); await Task.Delay(100); return ListRecords; } /// - /// Elenco Macchine dato RestToken + /// Elenco Macchine dato RestToken /// /// Rest Token cliente /// ID progetto @@ -147,5 +235,65 @@ namespace MagMan.UI.Controllers answ = fatto ? "OK" : "NO"; return answ; } + + #endregion Public Methods + + #region Private Fields + + private static JsonSerializerSettings? JSSettings; + + /// + /// Classe per logging + /// + private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); + + #endregion Private Fields + + #region Private Properties + + private MTAdminService MTAdmService { get; set; } = null!; + private TenantService TService { get; set; } = null!; + + #endregion Private Properties + + #region Private Methods + + /// + /// Utility method comparatore dizionari + /// + /// + /// + /// + private bool DictComparer(Dictionary dict1, Dictionary dict2) + { + // Test for equality. + bool isEqual = false; + if (dict1.Count == dict2.Count) // Require isEqual count. + { + isEqual = true; + foreach (var pair in dict1) + { + int value; + if (dict2.TryGetValue(pair.Key, out value)) + { + // Require value be isEqual. + if (value != pair.Value) + { + isEqual = false; + break; + } + } + else + { + // Require key be present. + isEqual = false; + break; + } + } + } + return isEqual; + } + + #endregion Private Methods } -} +} \ No newline at end of file diff --git a/MagMan.UI/Health/Checks.cs b/MagMan.UI/Health/Checks.cs index badd927..a708d7b 100644 --- a/MagMan.UI/Health/Checks.cs +++ b/MagMan.UI/Health/Checks.cs @@ -53,32 +53,25 @@ namespace MagMan.UI.Health } } - public static async Task DbPlantTable(string dbName) + public static async Task CustomersCount() { - using (var appDb = new MagManContext()) + string description = "Try check CUSTOMERS table"; + var healthCheckData = new Dictionary(); + using (MultiTenantContext localDbCtx = new MultiTenantContext()) { - string description = "Try check Table PlantLog"; - var healthCheckData = new Dictionary(); -#if false - List recordList = new List(); - try + var dbCount = localDbCtx + .DbSetCustomers + .Count(); + if (dbCount > 0) { - // provo a controllare se ho tab utenti - recordList = await Task.FromResult(appDb.DbSetPlant.ToList()).ConfigureAwait(false); - if (recordList.Count > 0) - { - description = $"Check PlantDetail table, found {recordList.Count} records"; - return HealthCheckResult.Healthy(description, healthCheckData); - } + description = $"Check CUSTOMERS table, found {dbCount} records"; + healthCheckData.Add("Count", dbCount); + return HealthCheckResult.Healthy(description, healthCheckData); } - catch (Exception exc) - { - Log.Error(exc, "Errore in esecuzione PlantDetail Table"); - } -#endif - - return HealthCheckResult.Degraded(description + $" {dbName}", null, healthCheckData); } + + await Task.Delay(1); + return HealthCheckResult.Unhealthy(description + $" NO RECORD found", null, healthCheckData); } public static async Task DbUserRoot(string dbName) diff --git a/MagMan.UI/MagMan.UI.csproj b/MagMan.UI/MagMan.UI.csproj index b8acb74..d7a0001 100644 --- a/MagMan.UI/MagMan.UI.csproj +++ b/MagMan.UI/MagMan.UI.csproj @@ -2,7 +2,7 @@ net6.0 - 1.0.2404.1208 + 1.0.2404.2711 enable enable true @@ -34,10 +34,11 @@ + - - + + @@ -46,10 +47,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + - - + + diff --git a/MagMan.UI/Pages/Index.razor b/MagMan.UI/Pages/Index.razor index cf76139..71b85ad 100644 --- a/MagMan.UI/Pages/Index.razor +++ b/MagMan.UI/Pages/Index.razor @@ -48,12 +48,15 @@ -
- - -

Dati Macchine

-
-
+ @if (isDebug) + { +
+ + +

Dati Macchine

+
+
+ }
diff --git a/MagMan.UI/Pages/Index.razor.cs b/MagMan.UI/Pages/Index.razor.cs index 9c551d5..0cc04a4 100644 --- a/MagMan.UI/Pages/Index.razor.cs +++ b/MagMan.UI/Pages/Index.razor.cs @@ -5,6 +5,16 @@ namespace MagMan.UI.Pages { public partial class Index { + #region Protected Fields + +#if DEBUG + protected bool isDebug = true; +#else + protected bool isDebug = false; +#endif + + #endregion Protected Fields + #region Protected Properties [Inject] @@ -23,5 +33,7 @@ namespace MagMan.UI.Pages } #endregion Protected Methods + + } } \ No newline at end of file diff --git a/MagMan.UI/Program.cs b/MagMan.UI/Program.cs index 7c03abb..61fa8fe 100644 --- a/MagMan.UI/Program.cs +++ b/MagMan.UI/Program.cs @@ -52,13 +52,11 @@ builder.Services.AddHealthChecks() .AddMySql(connStringDB, "MySql instance") .AddAsyncCheck($"DB PING ({dbServerAddr})", () => MagMan.UI.Health.Checks.PingCheck(dbServerAddr)) .AddAsyncCheck($"Redis PING ({redisSrvAddr})", () => MagMan.UI.Health.Checks.PingCheck(redisSrvAddr)) - .AddProcessAllocatedMemoryHealthCheck(512, "Max Process memory (<512MB)", failureStatus: HealthStatus.Degraded) // 512 MB max allocated memory + // 512 MB max allocated memory + .AddProcessAllocatedMemoryHealthCheck(512, "Max Process memory (<512MB)", failureStatus: HealthStatus.Degraded) .AddRedis(builder.Configuration.GetConnectionString("Redis"), "Redis", failureStatus: HealthStatus.Degraded) - .AddAsyncCheck($"MySql Root User", () => MagMan.UI.Health.Checks.DbUserRoot("MySql")) .AddAsyncCheck($"MySql Identity", () => MagMan.UI.Health.Checks.DbIdentity(MagMan.Data.Admin.DbConfig.DATABASE_NAME)) -#if false - .AddAsyncCheck($"MySql PlantLog", () => MagMan.UI.Health.Checks.DbPlantTable(DbConfig.DATABASE_NAME)) -#endif + .AddAsyncCheck($"MySql Customers", () => MagMan.UI.Health.Checks.CustomersCount()) ; builder.Services.AddHealthChecksUI(s => diff --git a/MagMan.UI/Shared/NavMenu.razor b/MagMan.UI/Shared/NavMenu.razor index 87ae57e..23223a2 100644 --- a/MagMan.UI/Shared/NavMenu.razor +++ b/MagMan.UI/Shared/NavMenu.razor @@ -28,7 +28,6 @@
- - - + @if (isDebug) + { + + } -@code { - - [CascadingParameter] - private Task AuthenticationStateTask { get; set; } - - private bool collapseNavMenu = true; - private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; - protected bool showText { get; set; } = true; - private string userName = ""; - - protected override async Task OnInitializedAsync() - { - var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); - var user = authState.User; - if (user.Identity.IsAuthenticated) - { - userName = $"{user.Identity.Name}"; - } - else - { - userName = "Non Autenticato"; - } - } - - private void ToggleNavMenu() - { - collapseNavMenu = !collapseNavMenu; - } - protected string hideText - { - get => showText ? "" : "invisible"; - } - - [Parameter] - public EventCallback EC_compressUpdated { get; set; } -} diff --git a/MagMan.UI/Shared/NavMenu.razor.cs b/MagMan.UI/Shared/NavMenu.razor.cs new file mode 100644 index 0000000..e09d8f2 --- /dev/null +++ b/MagMan.UI/Shared/NavMenu.razor.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; + +namespace MagMan.UI.Shared +{ + public partial class NavMenu + { + + + [CascadingParameter] + private Task AuthenticationStateTask { get; set; } + + private bool collapseNavMenu = true; + private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; + protected bool showText { get; set; } = true; + private string userName = ""; + + protected override async Task OnInitializedAsync() + { + var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + var user = authState.User; + if (user.Identity.IsAuthenticated) + { + userName = $"{user.Identity.Name}"; + } + else + { + userName = "Non Autenticato"; + } + } + + private void ToggleNavMenu() + { + collapseNavMenu = !collapseNavMenu; + } + protected string hideText + { + get => showText ? "" : "invisible"; + } + + [Parameter] + public EventCallback EC_compressUpdated { get; set; } + +#if DEBUG + protected bool isDebug = true; +#else + protected bool isDebug = false; +#endif + + } +} \ No newline at end of file diff --git a/MagMan.UI/appsettings.Staging.json b/MagMan.UI/appsettings.Staging.json new file mode 100644 index 0000000..663e863 --- /dev/null +++ b/MagMan.UI/appsettings.Staging.json @@ -0,0 +1,17 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "OptConf": { + "msRefresh": "4000", + "BaseAddr": "https://magman.ufficio/", + "BaseAppPath": "", + "QrRedirPage": "", + "jumpRedir": "~/../", + "CodModulo": "MagMan" + } +} diff --git a/Resources/ChangeLog.html b/Resources/ChangeLog.html index cd62366..309c328 100644 --- a/Resources/ChangeLog.html +++ b/Resources/ChangeLog.html @@ -1,6 +1,6 @@ MagMan - Wood Warehouse Management System -

Versione: 1.0.2404.1208

+

Versione: 1.0.2404.2711


Note di rilascio:
  • diff --git a/Resources/VersNum.txt b/Resources/VersNum.txt index c13284c..d9af166 100644 --- a/Resources/VersNum.txt +++ b/Resources/VersNum.txt @@ -1 +1 @@ -1.0.2404.1208 +1.0.2404.2711 diff --git a/Resources/manifest.xml b/Resources/manifest.xml index c2fd46e..12870df 100644 --- a/Resources/manifest.xml +++ b/Resources/manifest.xml @@ -1,6 +1,6 @@ - 1.0.2404.1208 + 1.0.2404.2711 http://nexus.steamware.net/repository/SWS/MagMan/stable/0/MagMan.UI.zip http://nexus.steamware.net/repository/SWS/MagMan/stable/0/ChangeLog.html false diff --git a/TestConsoleApp/Program.cs b/TestConsoleApp/Program.cs index c6d8226..60f4cd8 100644 --- a/TestConsoleApp/Program.cs +++ b/TestConsoleApp/Program.cs @@ -1,4 +1,5 @@ -using EgwProxy.MagMan; +using EgwProxy.DataLayer.Controllers; +using EgwProxy.MagMan; using EgwProxy.MagMan.DTO; using System; using System.Collections.Generic; @@ -14,7 +15,12 @@ namespace DemoApp static async Task Main(string[] args) { - + // num chiave + int keyNum = 470; + // id macchina cloud + int machCloudId = 4; + // id progetto cloud + int projCloud = 1; #if DEBUG // Indirizzo server (DEBUG) string servAddr = "localhost:7207"; @@ -104,8 +110,9 @@ namespace DemoApp Console.WriteLine("Enter to next step"); answ = Console.ReadLine(); + // leggo projectList - var projList = commLib.ProjectGet(470); + var projList = commLib.ProjectGet(keyNum); if (projList != null) { foreach (var itemProj in projList) @@ -188,6 +195,40 @@ namespace DemoApp alias2send.Add(new AliasDTO() { ValOrig = "Item02", ValAlias = "Gl24h", IsActive = true }); var resAliasSend = commLib.AliasSend(alias2send); + // carico dal DB primi 50 rec e li invio 10 alla volta... + LogMachineController lmc = new LogMachineController(); + int num2send = 20; + int batchSize = 10; + int numSent = 0; + var recList = lmc.GetUnsentAsc(num2send); + // ciclo! + while (numSent < num2send) + { + var currList = recList + .Skip(numSent) + .Take(batchSize) + .ToList(); + // converto il blocco + var listDto = currList + .Select(x => LogMachineController.ConvToItemDto(x, keyNum, machCloudId, projCloud)) + .ToList(); + // invio! + var res = commLib.LogMachineSend(listDto); + if (res) + { + // registro dati inviati... + lmc.SetDtSent(currList); + Console.WriteLine($"Inviati {batchSize}rec | {numSent} --> {numSent + batchSize}"); + numSent += batchSize; + } + else + { + Console.WriteLine($"Errore in invio logMacchina"); + } + } + Console.WriteLine(sep); + Console.WriteLine(); + Console.WriteLine("Enter to close"); answ = Console.ReadLine(); } diff --git a/TestConsoleApp/TestConsoleApp.csproj b/TestConsoleApp/TestConsoleApp.csproj index cd7b5a2..ca003f1 100644 --- a/TestConsoleApp/TestConsoleApp.csproj +++ b/TestConsoleApp/TestConsoleApp.csproj @@ -88,6 +88,10 @@ + + {87935fc9-c1bc-4984-83ca-a9edabbe2228} + EgwProxy.DataLayer + {1696d7a5-765a-4d25-8d29-ca7345023479} EgwProxy.MagMan