This commit is contained in:
2020-09-01 17:59:01 +00:00
parent 55c673c48d
commit 84a8b7f05a
3 changed files with 218 additions and 9 deletions

View File

@@ -186,18 +186,28 @@ namespace AyaNova.Api.Controllers
public class ObjectReportDataParameter
{
public AyaType ObjectType { get; set; }
public long[] ObjectIdArray { get; set; }
public long[] SelectedRowIds { get; set; }
public string DataListKey { get; set; }
public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList
}
/// <summary>
/// Get data from id list in format used by report designer
/// </summary>
/// <param name="reportDataParam">report id and object id values for object type specified in report template</param>
/// <param name="reportDataParam">Data required for report</param>
/// <param name="apiVersion">From route path</param>
/// <returns></returns>
[HttpPost("object-report-data")]
public async Task<IActionResult> GetReportData([FromBody] ObjectReportDataParameter reportDataParam, ApiVersion apiVersion)
{
/*{
public AyaType ObjectType { get; set; }
public long[] SelectedRowIds { get; set; }
public string DataListKey { get; set; }
public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList
}*/
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
ReportBiz biz = ReportBiz.GetBiz(ct, HttpContext);
@@ -205,7 +215,22 @@ namespace AyaNova.Api.Controllers
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
var reportData = await biz.GetReportData(reportDataParam.ObjectType, reportDataParam.ObjectIdArray);
Newtonsoft.Json.Linq.JArray reportData = null;
if (reportDataParam.SelectedRowIds.Length > 0)
{
//pre-selected id values
reportData = await biz.GetReportData(reportDataParam.ObjectType, reportDataParam.SelectedRowIds);
}
else
{
//get from datalist values
//get the list of id's from the data list view
var rowIds = await AyaNova.DataList.DataListFetcher.GetIdListResponseAsync(reportDataParam.DataListKey, reportDataParam.ListView, ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items), log);
//now get the report data
reportData = await biz.GetReportData(reportDataParam.ObjectType, rowIds);
}
if (reportData == null)
return BadRequest(new ApiErrorResponse(biz.Errors));
else

View File

@@ -191,6 +191,195 @@ namespace AyaNova.DataList
//BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT
Newtonsoft.Json.Linq.JArray ColumnsJSON = null;
ColumnsJSON = DataList.GenerateListColumnsJSONFromListView(ListViewArray);
return new ApiDataListResponse(rows, totalRecordCount, ColumnsJSON);
}
//Get a list of id's for reporting
internal static async Task<long[]> GetIdListResponseAsync(string DataListKey, string ListView, AyContext ct, long UserId, AuthorizationRoles UserRoles, ILogger log)
{
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<string> ListViewFieldList = DataList.GetFieldListFromListView(ListViewArray);
//BUILD THE QUERY
//SELECT FRAGMENT COLUMNS FROM TEMPLATE
var SelectBuild = 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 = $"{SelectBuild.Select} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}".Replace(" ", " ");
qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}".Replace(" ", " ");
//RETURN OBJECTS
int returnRowColumnCount = ListViewFieldList.Count();
List<List<AyaFieldData>> rows = new List<List<AyaFieldData>>();
long totalRecordCount = 0;
//QUERY THE DB
using (var command = ct.Database.GetDbConnection().CreateCommand())
{
await ct.Database.OpenConnectionAsync();
//GET DATA RETURN ROWS
command.CommandText = qDataQuery;
try
{
using (var dr = await command.ExecuteReaderAsync())
{
while (dr.Read())
{
List<AyaFieldData> row = new List<AyaFieldData>(returnRowColumnCount);
//INSERT REMAINING FIELDS FROM TEMPLATE INTO THE RETURN ROWS LIST
foreach (string TemplateField in ListViewFieldList)
{
//get the AyaObjectFieldDefinition
AyaDataListFieldDefinition f = DataList.FieldDefinitions.FirstOrDefault(z => z.FieldKey == TemplateField);
if (f.IsCustomField)
{
AyaFieldData AyaField = new AyaFieldData();
var cust = dr.GetString(SelectBuild.map[f.GetSqlValueColumnName()]);
if (!string.IsNullOrWhiteSpace(cust))
{
JObject j = JObject.Parse(cust);
//convert field name to cust name then get value
var InternalCustomFieldName = AyaFormFieldDefinitions.TranslateLTCustomFieldToInternalCustomFieldName(TemplateField);
//Sometimes a custom field is specified but doesn't exist in the collection so don't assume it's there
// AyaField.v = j[InternalCustomFieldName].Value<object>();
JToken o = j[InternalCustomFieldName];
if (o != null)
AyaField.v = o.Value<object>();
else
AyaField.v = null;
row.Add(AyaField);
}
/*
TODO: Custom field handling
GetName works just not with multipart identifiers
I could force naming by making all fields and AS, or
I could map the ordinal when generating the Select fields so that I have a map to refer to here
mapping in advance actually makes a lot of sense, then no more of this fragility of going by pointer index and hoping for the best
it would just be premapped out.
dr.GetOrdinal(f.SqlValueColumnName)
'dr.GetOrdinal(f.SqlValueColumnName)' threw an exception of type 'System.IndexOutOfRangeException'
f.SqlValueColumnName
"awidget.customfields"
dr.GetName(nCurrentColumnPointer)
"customfields"
dr.GetOrdinal("customfields");
5
*/
}
else
{
AyaFieldData AyaField = new AyaFieldData();
AyaField.v = dr.GetValue(SelectBuild.map[f.GetSqlValueColumnName()]);
if (f.IsRowId)
{
AyaField.rid = true;
}
else
{
AyaField.rid = null;
}
if (f.SqlIdColumnName != null)
{
var ordinal = SelectBuild.map[f.SqlIdColumnName];
if (!await dr.IsDBNullAsync(ordinal))
AyaField.i = dr.GetInt64(ordinal);
}
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);
}
}
}
catch (Npgsql.PostgresException e)
{
//log out the exception and the query
log.LogInformation("DataList query failed unexpectedly. Data Query was:");
log.LogInformation(qDataQuery);
log.LogInformation("Count Query was:");
log.LogInformation(qTotalRecordsQuery);
log.LogInformation(e, "DB Exception");
throw new System.Exception("DataListFetcher - Query failed see log");
}
}
//BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT
Newtonsoft.Json.Linq.JArray ColumnsJSON = null;

View File

@@ -15,17 +15,12 @@ namespace AyaNova.DataList
[FromBody]
public int? Limit { get; set; }
[FromBody, Required]
public string DataListKey { get; set; }
[FromBody]
public string ListView { get; set; }//optional, if null or empty will use default list view built into DataList
}
}
}