From 7ab10cfe0f4d2dfaa1341056ad47bee6000516ab Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Tue, 25 Jan 2022 19:28:23 +0100 Subject: [PATCH] Completata prima bozza gestioen calcolo progetti "sforati" --- GPW.CORE.Api/Controllers/CheckProj.cs | 56 +++++++++++++++-- GPW.CORE.Api/Data/ApiDataService.cs | 73 ++++++++++++++++++++-- GPW.CORE.Data/Controllers/GPWController.cs | 3 +- GPW.CORE.Data/DbModels/CalcOreFasiModel.cs | 1 + GPW.CORE.UI/Data/GpwDataService.cs | 4 +- GPW.CORE.UI/GPW.CORE.UI.csproj | 2 +- Resources/ChangeLog.html | 2 +- Resources/VersNum.txt | 2 +- Resources/manifest.xml | 2 +- 9 files changed, 130 insertions(+), 15 deletions(-) diff --git a/GPW.CORE.Api/Controllers/CheckProj.cs b/GPW.CORE.Api/Controllers/CheckProj.cs index 6ae55cb..de3ef6e 100644 --- a/GPW.CORE.Api/Controllers/CheckProj.cs +++ b/GPW.CORE.Api/Controllers/CheckProj.cs @@ -28,14 +28,62 @@ namespace GPW.CORE.Api.Controllers public async Task Get() { string answ = "ND"; - StringBuilder sb = new StringBuilder(); - + StringBuilder sbLog = new StringBuilder(); + StringBuilder sbActions = new StringBuilder(); + // recupero progetti attivi... var currProj = await dataService.AnagProjActiv(); - sb.Append($"Found {currProj.Count} Active Projects"); + sbLog.AppendLine("-----------------------"); + sbLog.AppendLine($"Found {currProj.Count} Active Projects"); + // leggo fasi attive + var currFasiAct = await dataService.AnagFasiActiv(); + sbLog.AppendLine($"Found {currFasiAct.Count} Active Phases"); - answ = sb.ToString(); + sbLog.AppendLine("-----------------------"); + // ciclo elenco fasi ancestor di ognuno... + foreach (var itemProj in currProj) + { + // cerco le sue fasi PARENT... + var subsetFasi = currFasiAct + .Where(x => x.IdxProgetto == itemProj.IdxProgetto && x.IdxFaseAncest == 0) + .ToList(); + sbLog.AppendLine("----------"); + string projData = $"[{itemProj.IdxProgetto}] {itemProj.ClienteNav.RagSociale} - {itemProj.NomeProj} | Found {subsetFasi.Count} Phases"; + sbLog.AppendLine(projData); + + // ciclo x ogni fase Parent + foreach (var parentFase in subsetFasi) + { + // cerco la prima child del parent... + var firstChild = currFasiAct + .Where(x => x.IdxFaseAncest == parentFase.IdxFase) + .FirstOrDefault(); + if (firstChild != null) + { + // se ne trovo valuto le ore impiegate... + var statoFase = await dataService.CalcOreFase(parentFase.IdxFase); + + // se ore usate > (ore budget x %) --> CHIUDO! + if (statoFase != null && statoFase.percUsed >= (decimal)statoFase.percOpen) + { + // x ora LOG... poi chiudo... + string currAction = $"!!! [{parentFase.IdxFase}] Budget exhausted for Phase {parentFase.NomeFase} {statoFase.totOre:N2}h used, {statoFase.percUsed:P1} vs {statoFase.percOpen:P1}"; + sbLog.AppendLine(currAction); + sbActions.AppendLine("----------"); + sbActions.AppendLine(projData); + sbActions.AppendLine(currAction); + + } + } + } + } + + // LOG esteso locale + _logger.LogInformation(sbLog.ToString()); + + // ritorno solo LOG azioni + answ = sbActions.ToString(); return answ; } } diff --git a/GPW.CORE.Api/Data/ApiDataService.cs b/GPW.CORE.Api/Data/ApiDataService.cs index ec341d7..fccd9e8 100644 --- a/GPW.CORE.Api/Data/ApiDataService.cs +++ b/GPW.CORE.Api/Data/ApiDataService.cs @@ -31,7 +31,10 @@ namespace GPW.CORE.Api.Data #region Protected Fields - protected const string rKeyProjAct = "Cache:ProjAct"; + protected const string rKeyProjAct = "Check:ProjAct"; + protected const string rKeyFasiAct = "Check:FasiAct"; + protected const string rKeyCalcOreFase = "Check:OreFasi"; + /// /// TTL da 1 min x cache Redis @@ -141,7 +144,7 @@ namespace GPW.CORE.Api.Data #region Public Methods /// - /// Recupera l'elenco progetti (tutti) + /// Recupera l'elenco progetti (ATTIVI) /// /// public async Task> AnagProjActiv() @@ -159,16 +162,78 @@ namespace GPW.CORE.Api.Data Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.AnagProjAll(true); - rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings(){ ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); + rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); await setRSV(cacheKey, rawData, shortTTL); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; - Log.Trace($"Effettuata lettura da DB per AttivazioniByLic: {ts.TotalMilliseconds} ms"); + Log.Trace($"Effettuata lettura da DB per AnagProjActiv: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } + /// + /// Recupera l'elenco fasi (ATTIVE) + /// + /// + public async Task> AnagFasiActiv() + { + List dbResult = new List(); + string cacheKey = $"{rKeyFasiAct}"; + trackCache(cacheKey); + string rawData = await getRSV(cacheKey); + if (!string.IsNullOrEmpty(rawData)) + { + dbResult = JsonConvert.DeserializeObject>(rawData); + } + else + { + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + dbResult = dbController.AnagFasiAll(true); + rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); + await setRSV(cacheKey, rawData, shortTTL); + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Trace($"Effettuata lettura da DB per AnagFasiActiv: {ts.TotalMilliseconds} ms"); + } + + return await Task.FromResult(dbResult); + } + + /// + /// Vista dati per FASE (tipicamente master...) con totalizzaizone ore budget/real e stato fase + /// + /// + /// + public async Task CalcOreFase(int idxFase) + { + CalcOreFasiModel? dbResult = new CalcOreFasiModel(); + string cacheKey = $"{rKeyCalcOreFase}:{idxFase}"; + trackCache(cacheKey); + string rawData = await getRSV(cacheKey); + if (!string.IsNullOrEmpty(rawData)) + { + dbResult = JsonConvert.DeserializeObject(rawData); + } + else + { + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + dbResult = dbController.CalcOreFase(idxFase); + rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); + await setRSV(cacheKey, rawData, shortTTL); + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Trace($"Effettuata lettura da DB per CalcOreFase: {ts.TotalMilliseconds} ms"); + } + if (dbResult == null) + { + dbResult = new CalcOreFasiModel(); + } + return await Task.FromResult(dbResult); + } + /// /// invalida tutta la cache in caso di update /// diff --git a/GPW.CORE.Data/Controllers/GPWController.cs b/GPW.CORE.Data/Controllers/GPWController.cs index 50fd8cc..2e24479 100644 --- a/GPW.CORE.Data/Controllers/GPWController.cs +++ b/GPW.CORE.Data/Controllers/GPWController.cs @@ -58,7 +58,7 @@ namespace GPW.CORE.Data.Controllers /// Recupera l'elenco delle fasi (tutte) /// /// - public List AnagFasiAll() + public List AnagFasiAll(bool onlyActive) { // init dati necessari List dbResult = new List(); @@ -70,6 +70,7 @@ namespace GPW.CORE.Data.Controllers // recupero intero set... dbResult = localDbCtx .DbSetAnagFasi + .Where(x => ((bool)x.Attivo == true && onlyActive == true) || !onlyActive) .ToList(); } catch (Exception exc) diff --git a/GPW.CORE.Data/DbModels/CalcOreFasiModel.cs b/GPW.CORE.Data/DbModels/CalcOreFasiModel.cs index dd3c226..f540336 100644 --- a/GPW.CORE.Data/DbModels/CalcOreFasiModel.cs +++ b/GPW.CORE.Data/DbModels/CalcOreFasiModel.cs @@ -23,6 +23,7 @@ namespace GPW.CORE.Data.DbModels public bool? Attivo { get; set; } public decimal budgetTime { get; set; } = 0; public decimal budgetMoney { get; set; } = 0; + public double percOpen { get; set; } = 1; public string CodClasse { get; set; } = ""; public string CodExt { get; set; } = ""; public decimal totOre { get; set; } = 0; diff --git a/GPW.CORE.UI/Data/GpwDataService.cs b/GPW.CORE.UI/Data/GpwDataService.cs index 4fc67c9..070a944 100644 --- a/GPW.CORE.UI/Data/GpwDataService.cs +++ b/GPW.CORE.UI/Data/GpwDataService.cs @@ -233,7 +233,7 @@ namespace GPW.CORE.UI.Data { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - dbResult = dbController.AnagFasiAll(); + dbResult = dbController.AnagFasiAll(false); rawData = JsonConvert.SerializeObject(dbResult, JSSettings); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(currKey, redisDataList, cacheOpt(true)); @@ -358,7 +358,7 @@ namespace GPW.CORE.UI.Data public async Task CalcOreFase(int idxFase) { CalcOreFasiModel? dbResult = new CalcOreFasiModel(); - string currKey = $"{rKeyCalcOreProj}:{idxFase}"; + string currKey = $"{rKeyCalcOreFase}:{idxFase}"; trackCache(currKey); string rawData; diff --git a/GPW.CORE.UI/GPW.CORE.UI.csproj b/GPW.CORE.UI/GPW.CORE.UI.csproj index 851b507..34e1eee 100644 --- a/GPW.CORE.UI/GPW.CORE.UI.csproj +++ b/GPW.CORE.UI/GPW.CORE.UI.csproj @@ -2,7 +2,7 @@ net6.0 - 3.0.2201.2517 + 3.0.2201.2519 enable enable diff --git a/Resources/ChangeLog.html b/Resources/ChangeLog.html index 8a42b81..533215e 100644 --- a/Resources/ChangeLog.html +++ b/Resources/ChangeLog.html @@ -1,6 +1,6 @@ GPW - Gestione Presenze Web -

Versione: 3.0.2201.2517

+

Versione: 3.0.2201.2519


Note di rilascio:
  • diff --git a/Resources/VersNum.txt b/Resources/VersNum.txt index 704b23c..6a23cac 100644 --- a/Resources/VersNum.txt +++ b/Resources/VersNum.txt @@ -1 +1 @@ -3.0.2201.2517 +3.0.2201.2519 diff --git a/Resources/manifest.xml b/Resources/manifest.xml index a1735dc..24bbfd9 100644 --- a/Resources/manifest.xml +++ b/Resources/manifest.xml @@ -1,6 +1,6 @@ - 3.0.2201.2517 + 3.0.2201.2519 http://nexus.steamware.net/repository/SWS/GWMS/stable/0/GWMS.UI.zip http://nexus.steamware.net/repository/SWS/GWMS/stable/0/ChangeLog.html false