using System; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using System.Linq; using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using Microsoft.Extensions.Logging; using AyaNova.Models; using Newtonsoft.Json.Linq; using System.Collections.Generic; using Newtonsoft.Json; namespace AyaNova.Biz { internal class ServiceBankBiz : BizObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject, INotifiableObject { internal ServiceBankBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; UserTranslationId = userTranslationId; CurrentUserRoles = UserRoles; BizType = AyaType.ServiceBank; } internal static ServiceBankBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) return new ServiceBankBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else return new ServiceBankBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } //////////////////////////////////////////////////////////////////////////////////////////////// //EXISTS internal async Task ExistsAsync(long id) { return await ct.ServiceBank.AnyAsync(z => z.Id == id); } //////////////////////////////////////////////////////////////////////////////////////////////// //CREATE // internal async Task CreateAsync(ServiceBank newObject) { await ValidateAsync(newObject, null); if (HasErrors) return null; else { await ct.ServiceBank.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); await SearchIndexAsync(newObject, true); await HandlePotentialNotificationEvent(AyaEvent.Created, newObject); return newObject; } } //////////////////////////////////////////////////////////////////////////////////////////////// //GET // internal async Task GetAsync(long id, bool logTheGetEvent = true) { var ret = await ct.ServiceBank.SingleOrDefaultAsync(m => m.Id == id); if (logTheGetEvent && ret != null) await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, BizType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //SEARCH // private async Task SearchIndexAsync(ServiceBank obj, bool isNew) { var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, BizType); DigestSearchText(obj, SearchParams); if (isNew) await Search.ProcessNewObjectKeywordsAsync(SearchParams); else await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); } public async Task GetSearchResultSummary(long id) { var obj = await ct.ServiceBank.SingleOrDefaultAsync(z => z.Id == id); var SearchParams = new Search.SearchIndexProcessObjectParameters(); DigestSearchText(obj, SearchParams); return SearchParams; } public void DigestSearchText(ServiceBank obj, Search.SearchIndexProcessObjectParameters searchParams) { if (obj != null) searchParams.AddText(obj.Name); } //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // private async Task ValidateAsync(ServiceBank proposedObj, ServiceBank currentObj) { bool isNew = currentObj == null; //Name required if (string.IsNullOrWhiteSpace(proposedObj.Name)) AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name"); //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(x => x.FormKey == AyaType.ServiceBank.ToString()); if (FormCustomization != null) { //Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required //validate users choices for required non custom fields RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj); } } //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // public async Task GetReportData(long[] idList) { JArray ReportData = new JArray(); while (idList.Any()) { var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE); idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray(); //query for this batch, comes back in db natural order unfortunately var batchResults = await ct.ServiceBank.Where(z => batch.Contains(z.Id)).ToArrayAsync(); //order the results back into original var orderedList = from id in batch join z in batchResults on id equals z.Id select z; foreach (ServiceBank w in orderedList) { var jo = JObject.FromObject(w); if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"])) jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]); ReportData.Add(jo); } } return ReportData; } //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // public async Task GetExportData(long[] idList) { //for now just re-use the report data code //this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time return await GetReportData(idList); } //////////////////////////////////////////////////////////////////////////////////////////////// // NOTIFICATION PROCESSING // public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null) { ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger(); if (ServerBootConfig.SEEDING) return; log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]"); bool isNew = currentObj == null; //STANDARD EVENTS FOR ALL OBJECTS await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct); //SPECIFIC EVENTS FOR THIS OBJECT }//end of process notifications ///////////////////////////////////////////////////////////////////// }//eoc }//eons