Files
raven/server/AyaNova/biz/PickListBiz.cs
2021-09-09 00:06:16 +00:00

304 lines
12 KiB
C#

using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Models;
using AyaNova.PickList;
namespace AyaNova.Biz
{
internal class PickListBiz : BizObject
{
internal PickListBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserTranslationId = userTranslationId;
CurrentUserRoles = UserRoles;
BizType = AyaType.PickListTemplate;
}
internal static PickListBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
{
if (httpContext != null)
return new PickListBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
else
return new PickListBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
}
////////////////////////////////////////////////////////////////////////////////////////////////
/// GET
//Get one
internal async Task<PickListTemplate> GetAsync(AyaType ayaType, bool logTheGetEvent = true)
{
long lTypeId = (long)ayaType;
//first try to fetch from db
var ret = await ct.PickListTemplate.SingleOrDefaultAsync(z => z.Id == lTypeId);
if (logTheGetEvent && ret != null)
{
//Log
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, lTypeId, BizType, AyaEvent.Retrieved), ct);
}
//not in db then get the default
if (ret == null)
{
var PickList = PickListFactory.GetAyaPickList(ayaType);
if (PickList != null)
{
ret = new PickListTemplate();
ret.Id = lTypeId;
ret.Template = PickList.DefaultTemplate;
}
}
return ret;
}
//get picklist
internal async Task<List<NameIdActiveItem>> GetPickListAsync(IAyaPickList PickList, string query, bool inactive, long[] preIds, string variant, ILogger log, string template)
{
//Crack and validate the query part set a broken rule if not valid and return null
//else do the query
string TagSpecificQuery = null;
string AutoCompleteQuery = null;
//Here need to handle scenario of badly formed query so user knows they did it wrong and doesn't just assume it's not there
//determine if this is a tag query and extract it
bool HasQuery = !string.IsNullOrWhiteSpace(query);
if (HasQuery)
{
AutoCompleteQuery = query;
//is it a dual template and tag query?
if (AutoCompleteQuery.Contains(" "))
{
// split the query on space
var querySegments = AutoCompleteQuery.Split(' ');
if (querySegments.Length > 2)
{
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "query", await Translate("ErrorPickListQueryInvalid"));
return null;
}
//check the two query segments, it's valid for the user to put the tag first or the template query first
//we handle either way, but if there are no tas in either then it's not a valid query
if (querySegments[0].Contains(".."))
{
TagSpecificQuery = querySegments[0].Replace("..", "");
AutoCompleteQuery = querySegments[1];
}
else if (querySegments[1].Contains(".."))
{
TagSpecificQuery = querySegments[1].Replace("..", "");
AutoCompleteQuery = querySegments[0];
}
else
{
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "query", await Translate("ErrorPickListQueryInvalid"));
return null;
}
}
else
{
//is it a tag only query?
if (AutoCompleteQuery.Contains(".."))
{
TagSpecificQuery = AutoCompleteQuery.Replace("..", "");
AutoCompleteQuery = null;
}
}
}
//Final fixup if user specifies tag query but there are not tags on this object then
//rather than error just accept it as a no tag query
//Note: it's not valid to have more than one field with tags in the picklist definition so this works
if (PickList.ColumnDefinitions.FirstOrDefault(z => z.ColumnDataType == UiFieldDataType.Tags) == null)
{
TagSpecificQuery = null;
}
//Autocomplete and tagonly query terms now set for consumption by PickListFetcher, ready to fetch...
List<NameIdActiveItem> items = await PickListFetcher.GetResponseAsync(PickList, AutoCompleteQuery, TagSpecificQuery, inactive, preIds, variant, ct, log, template);
return items;
}
//get picklist display for a single item
//used to populate UI with picklist format display for items
internal async Task<string> GetTemplatedNameAsync(AyaType ayaType, long id, string variant, ILogger log, string template)
{
//short circuit for empty types
if (id == 0)
{
return string.Empty;
}
long[] preIds = { id };
var PickList = PickListFactory.GetAyaPickList(ayaType);
if (log == null)
log = AyaNova.Util.ApplicationLogging.CreateLogger("PickListBiz::GetTemplatedNameAsync");
//Autocomplete and tagonly query terms now set for consumption by PickListFetcher, ready to fetch...
List<NameIdActiveItem> items = await PickListFetcher.GetResponseAsync(PickList, null, null, true, preIds, variant, ct, log, template);
if (items.Count == 0)
{
return string.Empty;
}
return items[0].Name;
}
//get picklist templates, basically all the object types that support picklists
internal List<NameIdItem> GetListOfAllPickListTypes(long translationId)
{
return PickListFactory.GetListOfAllPickListTypes(translationId);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//UPDATE
//
//put
internal async Task<bool> ReplaceAsync(PickListTemplate template)
{
var o = await ct.PickListTemplate.FirstOrDefaultAsync(z => z.Id == (long)template.Id);
bool bAdd = false;
if (o == null)
{
o = new PickListTemplate();
bAdd = true;
}
o.Id = (long)template.Id;
o.Template = template.Template;
Validate(o);
if (HasErrors)
return false;
if (bAdd)
await ct.PickListTemplate.AddAsync(o);
await ct.SaveChangesAsync();
//Log modification and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, o.Id, BizType, AyaEvent.Modified), ct);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE (return to default template)
//
internal async Task<bool> DeleteAsync(AyaType ayaType)
{
//REMOVE ANY RECORD WITH SAME AYATYPE ID
long lTypeId = (long)ayaType;
var o = await ct.PickListTemplate.FirstOrDefaultAsync(z => z.Id == lTypeId);
if (o != null)
{
ct.PickListTemplate.Remove(o);
await ct.SaveChangesAsync();
//Event log process delete
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, lTypeId, ayaType.ToString(), ct);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//VALIDATION
//
//Can save or update?
private void Validate(PickListTemplate inObj)
{
//validate that the template is valid, the type is legit etc
var TemplateType = (AyaType)inObj.Id;
if (!TemplateType.HasAttribute(typeof(CoreBizObjectAttribute)))
{
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "ayaType", "AyaType specified is not a Core object type and doesn't support pick list templates");
return;
}
if (string.IsNullOrWhiteSpace(inObj.Template))
AddError(ApiErrorCode.VALIDATION_REQUIRED, "Template");
var PickList = PickListFactory.GetAyaPickList(TemplateType);
//Filter json must parse
//this is all automated normally so not going to do too much parsing here
//just ensure it's basically there
if (!string.IsNullOrWhiteSpace(inObj.Template))
{
try
{
var v = JArray.Parse(inObj.Template);
for (int i = 0; i < v.Count; i++)
{
var filterItem = v[i];
if (filterItem["fld"] == null)
AddError(ApiErrorCode.VALIDATION_REQUIRED, "Template", $"Template array item {i}, object is missing required \"fld\" property ");
else
{
var fld = filterItem["fld"].Value<string>();
if (string.IsNullOrWhiteSpace(fld))
AddError(ApiErrorCode.VALIDATION_REQUIRED, "Template", $"Template array item {i}, \"fld\" property is empty and required");
//validate the field name if we can
if (PickList != null)
{
var TheField = PickList.ColumnDefinitions.SingleOrDefault(z => z.FieldKey.ToLowerInvariant() == fld.ToLowerInvariant());
if (TheField == null)
{
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Template", $"Template array item {i}, fld property value \"{fld}\" is not a valid value for AyaType specified");
}
}
}
}
}
catch (Newtonsoft.Json.JsonReaderException ex)
{
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Template", "Template is not valid JSON string: " + ex.Message);
}
}
}
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons