From e0bf2cb733d438a8de21b4a4055ae0713feeb3cf Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Fri, 25 Feb 2022 00:05:20 +0000 Subject: [PATCH] --- server/AyaNova/kpi/IAyaKPI.cs | 17 +++ server/AyaNova/kpi/KPIFactory.cs | 39 +++++ server/AyaNova/kpi/KPIFetcher.cs | 139 ++++++++++++++++++ .../kpi/WorkOrderItemLaborQuantitySummary.cs | 57 +++++++ 4 files changed, 252 insertions(+) create mode 100644 server/AyaNova/kpi/IAyaKPI.cs create mode 100644 server/AyaNova/kpi/KPIFactory.cs create mode 100644 server/AyaNova/kpi/KPIFetcher.cs create mode 100644 server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs diff --git a/server/AyaNova/kpi/IAyaKPI.cs b/server/AyaNova/kpi/IAyaKPI.cs new file mode 100644 index 00000000..d6dbf660 --- /dev/null +++ b/server/AyaNova/kpi/IAyaKPI.cs @@ -0,0 +1,17 @@ +using System; +using AyaNova.Biz; +namespace AyaNova.KPI +{ + internal interface IAyaKPI + { + //allowed roles to access this kpi + AuthorizationRoles AllowedRoles { get; } + + //build the data and meta queries based on the criteria and this kpi's standard query + void BuildQuery(string criteria, DateTimeOffset clientTimeStamp); + string MetaQuery{get;}//Query to fetch json meta data for report purposes mainly (lookup stuff like names etc where applicable) + string DataQuery{get;}//Query to fetch json format data for result set + string ErrorMessage{get;}//if there was a problem then this is set with the error message + + } +} \ No newline at end of file diff --git a/server/AyaNova/kpi/KPIFactory.cs b/server/AyaNova/kpi/KPIFactory.cs new file mode 100644 index 00000000..d0dfbcad --- /dev/null +++ b/server/AyaNova/kpi/KPIFactory.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using AyaNova.Biz; +using AyaNova.Models; + + +namespace AyaNova.KPI +{ + internal static class KPIFactory + { + + //Instantiate list object specified from type + internal static IAyaKPI GetAyaKPI(string name) + { + switch (name) + { + //CoreBizObject add here if it will be "picked" on any other form + case "WorkOrderItemLaborQuantitySummary": + return new WorkOrderItemLaborQuantitySummary() as IAyaKPI; + + //@##### WARNING: BE SURE TO ADD NEW TYPES BELOW OR USERS WON"T BE ABLE TO EDIT THE TEMPLATE FOR THEM + + default: + throw new System.NotImplementedException($"KPI {name} NOT IMPLEMENTED"); + + } + //return null; + } + + //List all the KPI types available + internal static List GetListOfAllKPI() + { + List ret = new List(); + + ret.Add("WorkOrderItemLaborQuantitySummary"); + + return ret; + } + }//eoc +}//eons \ No newline at end of file diff --git a/server/AyaNova/kpi/KPIFetcher.cs b/server/AyaNova/kpi/KPIFetcher.cs new file mode 100644 index 00000000..e9810964 --- /dev/null +++ b/server/AyaNova/kpi/KPIFetcher.cs @@ -0,0 +1,139 @@ +#define AYSHOWKPIQUERYINFO + +using System.Collections.Generic; +using System.Linq; +using AyaNova.Biz; +using Newtonsoft.Json.Linq; +using Microsoft.Extensions.Logging; +using AyaNova.Models; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using System; + +namespace AyaNova.KPI +{ + internal static class KPIFetcher + { + //////////////////////////////////////////////// + // Get the kpi data requested + // + // + internal static async Task GetResponseAsync(AyContext ct, string kpiName, string criteria, DateTimeOffset clientTimeStamp, AuthorizationRoles userRoles, ILogger log, long userId) + { + + /* + return a jobject like: + { + error: "if error this key present", + meta: {username:"joe blow","date range:blah to blah"} + data:[{r1},{r2},{r3}] + } + */ + //instantiate the list + var kpi = KPIFactory.GetAyaKPI(kpiName); + kpi.BuildQuery(criteria, clientTimeStamp); + + if (!string.IsNullOrWhiteSpace(kpi.ErrorMessage)) + { + return JObject.FromObject(new + { + error = kpi.ErrorMessage + }); + } + + + System.Text.StringBuilder sbData = new System.Text.StringBuilder(); + string sMeta = string.Empty; + +#if (DEBUG && AYSHOWKPIQUERYINFO) + System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); + +#endif + //QUERY THE DB + using (var command = ct.Database.GetDbConnection().CreateCommand()) + { + await ct.Database.OpenConnectionAsync(); + + //GET DATA RETURN ROWS + command.CommandText = kpi.DataQuery; + try + { +#if (DEBUG && AYSHOWKPIQUERYINFO) + stopWatch.Start(); +#endif + using (var dr = await command.ExecuteReaderAsync()) + { +#if (DEBUG && AYSHOWKPIQUERYINFO) + stopWatch.Stop(); + log.LogInformation($"(debug) KPIFetcher:GetResponse DATA query took {stopWatch.ElapsedMilliseconds}ms to execute: {kpi.DataQuery}"); + stopWatch.Reset(); +#endif + + while (dr.Read()) + { + //only one column and it's the zeroth json string column + if (!dr.IsDBNull(0)) + sbData.Append(dr.GetString(0)); + } + } + + + + if (!string.IsNullOrWhiteSpace(kpi.MetaQuery)) + { + //GET META DATA + command.CommandText = kpi.MetaQuery; +#if (DEBUG && AYSHOWQUERYINFO) + stopWatch.Start(); +#endif + using (var dr = await command.ExecuteReaderAsync()) + { +#if (DEBUG && AYSHOWQUERYINFO) + stopWatch.Stop(); + log.LogInformation($"(debug) KPIFetcher:GetResponse META query took {stopWatch.ElapsedMilliseconds}ms to execute: {qTotalRecordsQuery}"); +#endif + if (dr.Read()) + { + sMeta = dr.GetString(0); + } + } + } + + + } + catch (Npgsql.PostgresException e) + { + //log out the exception and the query + log.LogError("KPIFetcher:GetResponseAsync query failed. Data Query was:"); + log.LogError(kpi.DataQuery); + log.LogError("Meta Query was:"); + log.LogError(kpi.MetaQuery); + log.LogError(e, "DB Exception"); + throw new System.Exception("KPIFetcher:GetResponseAsync - Query failed see log"); + + } + catch (System.Exception e) + { + //ensure any other type of exception gets surfaced properly + //log out the exception and the query + log.LogError("KPIFetcher:GetResponseAsync unexpected failure. Data Query was:"); + log.LogError(kpi.DataQuery); + log.LogError("Meta Query was:"); + log.LogError(kpi.MetaQuery); + log.LogError(e, "Exception"); + throw new System.Exception("KPIFetcher:GetResponseAsync - unexpected failure see log"); + } + + return JObject.FromObject(new + { + meta = sMeta, + data = sbData + }); + } + } + + + + + }//eoc +}//eons \ No newline at end of file diff --git a/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs b/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs new file mode 100644 index 00000000..7af87df0 --- /dev/null +++ b/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using Newtonsoft.Json.Linq; +using AyaNova.Biz; +using System.Linq; +using System; + +namespace AyaNova.KPI +{ + internal class WorkOrderItemLaborQuantitySummary : IAyaKPI + { + private string _metaQuery = null; + private string _dataQuery = null; + private string _errorMessage=null; + + public AuthorizationRoles AllowedRoles { get => BizRoles.GetRoleSet(AyaType.WorkOrderItemLabor).ReadFullRecord; } + + public string MetaQuery => _metaQuery; + public string DataQuery => _dataQuery; + public string ErrorMessage => _errorMessage; + + public void BuildQuery(string criteria, DateTimeOffset clientTimeStamp) + { + //build data and meta queries + } + + // public string GetVariantCriteria(string variant) + // { + // //Currently the only variant is a object type and id to indicate headoffice + + // //ClientCriteria format for this list is "OBJECTID,AYATYPE" + // var crit = (variant ?? "").Split(',').Select(z => z.Trim()).ToArray(); + // if (crit.Length > 1) + // { + // int nType = 0; + // if (!int.TryParse(crit[1], out nType)) return string.Empty; + // AyaType forType = (AyaType)nType; + // if (forType != AyaType.HeadOffice) return string.Empty; + + // long lId = 0; + // if (!long.TryParse(crit[0], out lId)) return string.Empty; + // if (lId == 0) return string.Empty; + + // //Have valid type, have an id, so filter away + // switch (forType) + // { + // case AyaType.HeadOffice: + // { + // return $"acustomer.headofficeid = {lId}"; + // } + // } + // } + // return string.Empty; + // } + + + }//eoc +}//eons \ No newline at end of file