using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using AyaNova.Models; namespace AyaNova.Biz { internal class WorkOrderTemplateBiz : BizObject, ISearchAbleObject, INotifiableObject { internal WorkOrderTemplateBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; UserTranslationId = userTranslationId; CurrentUserRoles = UserRoles; BizType = AyaType.WorkOrderTemplate; } internal static WorkOrderTemplateBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) return new WorkOrderTemplateBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else//when called internally for internal ops there will be no context so need to set default values for that return new WorkOrderTemplateBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } //////////////////////////////////////////////////////////////////////////////////////////////// //EXISTS internal async Task ExistsAsync(long id) { return await ct.WorkOrderTemplate.AnyAsync(z => z.Id == id); } //////////////////////////////////////////////////////////////////////////////////////////////// /// GET /// /// internal async Task GetAsync(long fetchId, bool logTheGetEvent = true) { //This is simple so nothing more here, but often will be copying to a different output object or some other ops var ret = await ct.WorkOrderTemplate.SingleOrDefaultAsync(z => z.Id == fetchId); if (logTheGetEvent && ret != null) { //Log await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct); } return ret; } //################################################################################################################################################### //################################################################################################################################################### // WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED //################################################################################################################################################### //################################################################################################################################################### //////////////////////////////////////////////////////////////////////////////////////////////// //CREATE //Called from route and also seeder internal async Task CreateAsync(WorkOrderTemplate newObject) { await ValidateAsync(newObject, null); if (HasErrors) return null; else { //do stuff with WorkOrderTemplate WorkOrderTemplate outObj = newObject; outObj.Tags = TagBiz.NormalizeTags(outObj.Tags); outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields); //Save to db await ct.WorkOrderTemplate.AddAsync(outObj); await ct.SaveChangesAsync(); //Handle child and associated items: await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct); await SearchIndexAsync(outObj, true); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null); await HandlePotentialNotificationEvent(AyaEvent.Created, newObject); return outObj; } } //////////////////////////////////////////////////////////////////////////////////////////////// //DUPLICATE // internal async Task DuplicateAsync(WorkOrderTemplate dbObject) { WorkOrderTemplate newObject = new WorkOrderTemplate(); CopyObject.Copy(dbObject, newObject, "Wiki"); // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255); //generate unique name string newUniqueName = string.Empty; bool NotUnique = true; long l = 1; do { newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255); NotUnique = await ct.WorkOrderTemplate.AnyAsync(z => z.Name == newUniqueName); } while (NotUnique); newObject.Name = newUniqueName; newObject.Id = 0; newObject.Concurrency = 0; await ct.WorkOrderTemplate.AddAsync(newObject); await ct.SaveChangesAsync(); //Handle child and associated items: await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); await SearchIndexAsync(newObject, true); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await HandlePotentialNotificationEvent(AyaEvent.Created, newObject); return newObject; } //################################################################################################################################################### //################################################################################################################################################### // WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE PARTASSEMBLYBIZ / some of WORKORDERBIZ FOR HOW THIS SHOULD BE CODED //################################################################################################################################################### //################################################################################################################################################### //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // //put internal async Task PutAsync(WorkOrderTemplate dbObject, WorkOrderTemplate inObj) { //make a snapshot of the original for validation but update the original to preserve workflow WorkOrderTemplate SnapshotOfOriginalDBObj = new WorkOrderTemplate(); CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj); //Replace the db object with the PUT object CopyObject.Copy(inObj, dbObject, "Id"); dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); //Set "original" value of concurrency token to input token //this will allow EF to check it out ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency; await ValidateAsync(dbObject, SnapshotOfOriginalDBObj); if (HasErrors) return false; await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); await SearchIndexAsync(dbObject, false); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); await HandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj); return true; } //////////////////////////////////////////////////////////////////////////////////////////////// //SEARCH // private async Task SearchIndexAsync(WorkOrderTemplate 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.WorkOrderTemplate.SingleOrDefaultAsync(z => z.Id == id); var SearchParams = new Search.SearchIndexProcessObjectParameters(); DigestSearchText(obj, SearchParams); return SearchParams; } public void DigestSearchText(WorkOrderTemplate obj, Search.SearchIndexProcessObjectParameters searchParams) { if (obj != null) searchParams.AddText(obj.Notes) .AddText(obj.Name) .AddText(obj.Wiki) .AddText(obj.Tags) .AddCustomFields(obj.CustomFields); } //################################################################################################################################################### //################################################################################################################################################### // WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED //################################################################################################################################################### //################################################################################################################################################### //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // internal async Task DeleteAsync(WorkOrderTemplate dbObject) { //Determine if the object can be deleted, do the deletion tentatively //Probably also in here deal with tags and associated search text etc //NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObject); if (HasErrors) return false; ct.WorkOrderTemplate.Remove(dbObject); await ct.SaveChangesAsync(); //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct); await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); await HandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); return true; } //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // //Can save or update? private async Task ValidateAsync(WorkOrderTemplate proposedObj, WorkOrderTemplate currentObj) { //run validation and biz rules bool isNew = currentObj == null; //Name required if (string.IsNullOrWhiteSpace(proposedObj.Name)) AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name"); //If name is otherwise OK, check that name is unique if (!PropertyHasErrors("Name")) { //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false if (await ct.WorkOrderTemplate.AnyAsync(z => z.Name == proposedObj.Name && z.Id != proposedObj.Id)) { AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name"); } } //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderTemplate.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); //validate custom fields CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields); } } //Can delete? // private void ValidateCanDelete(WorkOrderTemplate inObj) // { // //whatever needs to be check to delete this object // } //////////////////////////////////////////////////////////////////////////////////////////////// // 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