using System.Collections.Generic; using System.Linq; using AyaNova.Biz; using Newtonsoft.Json.Linq; using AyaNova.Api.ControllerHelpers; using Microsoft.AspNetCore.Mvc; using AyaNova.Models; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using EnumsNET; namespace AyaNova.DataList { internal static class DataListFetcher { internal static async Task GetResponse(string DataListKey, AyContext ct, IUrlHelper Url, string routeName, ListOptions listOptions, long UserId, AuthorizationRoles UserRoles) { // var AyaObjectFields = AyaObjectFieldDefinitions.AyaObjectFields(AyaObjectFieldDefinitions.TEST_WIDGET_USER_EMAIL_ADDRESS_LIST_KEY); var DataList = DataListFactory.GetAyaDataList(DataListKey); //was the name not found as a list? if (DataList == null) { throw new System.ArgumentOutOfRangeException($"DataList \"{DataListKey}\" specified does not exist"); } //check rights if (!UserRoles.HasAnyFlags(DataList.AllowedRoles)) { throw new System.NotSupportedException("User roles insufficient for this datalist"); } //TODO: FETCH DATALISTTEMPLATE HERE OR USE DEFAULT IF FAULTY OR NOT FOUND var JSONDataListTemplate = DataList.DefaultDataListDisplayTemplate; //PARSE THE TEMPLATE INTO A STRING ARRAY //SO WE KNOW WHICH FIELDS TO RETURN FROM QUERY var jtemplate = JObject.Parse(JSONDataListTemplate); //convert to strings array (https://stackoverflow.com/a/33836599/8939) string[] templateFieldList; if (listOptions.Mini) { templateFieldList = ((JArray)jtemplate["mini"]).ToObject(); } else { templateFieldList = ((JArray)jtemplate["full"]).ToObject(); } //BUILD THE QUERY //SELECT FRAGMENT COLUMNS FROM TEMPLATE var qSelectColumns = DataListSqlSelectBuilder.Build(DataList.FieldDefinitions, JSONDataListTemplate, listOptions.Mini); //FROM CLAUSE var qFrom = DataList.SQLFrom; //FILTERED? DataFilter TheFilter = null; var qWhere = string.Empty; var qOrderBy = string.Empty; if (listOptions.DataFilterId > 0) { TheFilter = await ct.DataFilter.FirstOrDefaultAsync(x => x.Id == listOptions.DataFilterId); //WHERE CLAUSE - FILTER qWhere = DataListSqlFilterCriteriaBuilder.DataFilterToSQLCriteria(TheFilter, DataList.FieldDefinitions, UserId); //ORDER BY CLAUSE - SORT //BUILD ORDER BY AND APPEND IT qOrderBy = DataListSqlFilterOrderByBuilder.DataFilterToSQLOrderBy(TheFilter); } //LIMIT AND OFFSET CLAUSE - PAGING listOptions.Offset = listOptions.Offset ?? ListOptions.DefaultOffset; listOptions.Limit = listOptions.Limit ?? ListOptions.DefaultLimit; var qLimitOffset = $"LIMIT {listOptions.Limit} OFFSET {listOptions.Offset}"; //PUT IT ALL TOGETHER string qDataQuery = string.Empty; string qTotalRecordsQuery = string.Empty; if (TheFilter != null) { qDataQuery = $"{qSelectColumns} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}"; qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}"; } else { qDataQuery = $"{qSelectColumns} {qFrom} {qLimitOffset}"; qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom}"; } //RETURN OBJECTS int returnRowColumnCount = templateFieldList.Count() + 1;//Templates don't have the DF column in them but we need it and it's in the query so plus one List> rows = new List>(); long totalRecordCount = 0; //QUERY THE DB using (var command = ct.Database.GetDbConnection().CreateCommand()) { ct.Database.OpenConnection(); //GET DATA RETURN ROWS command.CommandText = qDataQuery; using (var dr = command.ExecuteReader()) { while (dr.Read()) { List row = new List(returnRowColumnCount); //PROCESS THE DF DEFAULT FIRST COLUMN //first column is always the underlying id value of the default record to open for this row in the client ui row.Add(new AyaFieldData() { v = dr.GetInt64(0) }); //GetOrdinal by name is flakey in npgsql so just going by field definition and ordinal numerically int nCurrentColumnPointer = 1;//start at 1 //INSERT REMAINING FIELDS FROM TEMPLATE INTO THE RETURN ROWS LIST foreach (string TemplateField in templateFieldList) { //get the AyaObjectFieldDefinition AyaDataListFieldDefinition f = DataList.FieldDefinitions.FirstOrDefault(x => x.FieldKey == TemplateField); AyaFieldData AyaField = new AyaFieldData(); AyaField.v = dr.GetValue(nCurrentColumnPointer); nCurrentColumnPointer++; if (f.SqlIdColumnName != null)//skip over df column id, it's not there { AyaField.i = dr.GetInt64(nCurrentColumnPointer); nCurrentColumnPointer++; } row.Add(AyaField); } rows.Add(row); } } //GET TOTAL RECORD COUNT command.CommandText = qTotalRecordsQuery; using (var dr = command.ExecuteReader()) { if (dr.Read()) { totalRecordCount = dr.GetInt64(0); } } } //BUILD THE PAGING LINKS PORTION var pageLinks = new PaginationLinkBuilder(Url, routeName, null, listOptions, totalRecordCount).PagingLinksObject(); //BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT string ColumnsJSON = string.Empty; if (listOptions.Mini) { ColumnsJSON = DataList.GenerateMINIListColumnsJSON(); } else { ColumnsJSON = DataList.GenerateListColumnsJSONFromTemplate(JSONDataListTemplate); } ApiPagedResponse pr = new ApiPagedResponse(rows, pageLinks, ColumnsJSON); return pr; } }//eoc }//eons