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 GetResponseAsync(string DataListKey, AyContext ct, ListOptions listOptions, long UserId, AuthorizationRoles UserRoles) { 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.UnauthorizedAccessException("User roles insufficient for this datalist"); //do we need to default the listView? if (string.IsNullOrWhiteSpace(listOptions.ListView)) { listOptions.ListView = DataList.DefaultListView; } //parse the list view var ListViewArray = JArray.Parse(listOptions.ListView); //Get the field key names in a list from the listview List ListViewFieldList = DataList.GetFieldListFromListView(ListViewArray); //BUILD THE QUERY //SELECT FRAGMENT COLUMNS FROM TEMPLATE var qSelectColumns = DataListSqlSelectBuilder.Build(DataList.FieldDefinitions, ListViewFieldList); //FROM CLAUSE var qFrom = DataList.SQLFrom; var qWhere = string.Empty; var qOrderBy = string.Empty; //WHERE CLAUSE - FILTER qWhere = DataListSqlFilterCriteriaBuilder.DataFilterToSQLCriteria(DataList.FieldDefinitions, ListViewArray, UserId); //ORDER BY CLAUSE - SORT //BUILD ORDER BY qOrderBy = DataListSqlFilterOrderByBuilder.DataFilterToSQLOrderBy(DataList.FieldDefinitions, ListViewArray); //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; qDataQuery = $"{qSelectColumns} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}".Replace(" ", " "); qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}".Replace(" ", " "); //RETURN OBJECTS int returnRowColumnCount = ListViewFieldList.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()) { await ct.Database.OpenConnectionAsync(); //GET DATA RETURN ROWS command.CommandText = qDataQuery; using (var dr = await command.ExecuteReaderAsync()) { 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 if (!dr.IsDBNull(0)) { row.Add(new AyaFieldData() { v = dr.GetInt64(0) }); } else { #if (DEBUG) throw new System.ArgumentNullException($"DEV ERROR in DataListFetcher.cs: fetching df column for {DataListKey} df value is null, expecting long int record value"); #endif } //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 ListViewFieldList) { if (TemplateField == "df") continue; //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 { if (!await dr.IsDBNullAsync(nCurrentColumnPointer)) AyaField.i = dr.GetInt64(nCurrentColumnPointer); nCurrentColumnPointer++; } row.Add(AyaField); } rows.Add(row); } } //GET TOTAL RECORD COUNT command.CommandText = qTotalRecordsQuery; using (var dr = await command.ExecuteReaderAsync()) { if (dr.Read()) { totalRecordCount = dr.GetInt64(0); } } } //BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT Newtonsoft.Json.Linq.JArray ColumnsJSON = null; ColumnsJSON = DataList.GenerateListColumnsJSONFromListView(ListViewArray); return new ApiDataListResponse(rows, totalRecordCount, ColumnsJSON); } }//eoc }//eons