304 lines
12 KiB
C#
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 Sockeye.Util;
|
|
using Sockeye.Api.ControllerHelpers;
|
|
using Sockeye.Models;
|
|
using Sockeye.PickList;
|
|
|
|
namespace Sockeye.Biz
|
|
{
|
|
|
|
|
|
internal class PickListBiz : BizObject
|
|
{
|
|
|
|
internal PickListBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
|
|
{
|
|
ct = dbcontext;
|
|
UserId = currentUserId;
|
|
UserTranslationId = userTranslationId;
|
|
CurrentUserRoles = UserRoles;
|
|
BizType = SockType.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.SOCKEYE_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// GET
|
|
|
|
//Get one
|
|
internal async Task<PickListTemplate> GetAsync(SockType sockType, bool logTheGetEvent = true)
|
|
{
|
|
long lTypeId = (long)sockType;
|
|
|
|
//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, SockEvent.Retrieved), ct);
|
|
}
|
|
|
|
//not in db then get the default
|
|
if (ret == null)
|
|
{
|
|
var PickList = PickListFactory.GetAyaPickList(sockType);
|
|
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(SockType sockType, 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(sockType);
|
|
|
|
if (log == null)
|
|
log = Sockeye.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, SockEvent.Modified), ct);
|
|
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//DELETE (return to default template)
|
|
//
|
|
internal async Task<bool> DeleteAsync(SockType sockType)
|
|
{
|
|
//REMOVE ANY RECORD WITH SAME AYATYPE ID
|
|
long lTypeId = (long)sockType;
|
|
|
|
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, sockType.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 = (SockType)inObj.Id;
|
|
if (!TemplateType.HasAttribute(typeof(CoreBizObjectAttribute)))
|
|
{
|
|
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "sockType", "SockType 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 SockType specified");
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
catch (Newtonsoft.Json.JsonReaderException ex)
|
|
{
|
|
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Template", "Template is not valid JSON string: " + ex.Message);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
}//eoc
|
|
|
|
|
|
}//eons
|
|
|