diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 19128196..bcce2bd5 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -25,6 +25,8 @@ namespace AyaNova.Biz todo: Don't all *child items require a transaction to be passed for *any* crud op, i.e. including put and etc? As they might be called from a parent transaction? + + todo: search for singleordefaultasync to find any missed *GetAsync items using old direct fetch */ @@ -2415,7 +2417,7 @@ namespace AyaNova.Biz return null; } await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); - // await PartRequestSearchIndexAsync(putObject, false); + // await PartRequestSearchIndexAsync(putObject, false); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); await PartRequestHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); return putObject; @@ -2426,19 +2428,19 @@ namespace AyaNova.Biz // internal async Task PartRequestDeleteAsync(long id, Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction parentTransaction = null) { - Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = null; + Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = null; if (parentTransaction == null) transaction = await ct.Database.BeginTransactionAsync(); try { - var dbObject = await PartRequestGetAsync(id,false); - PartRequestValidateCanDelete(dbObject); - if (HasErrors) - return false; - ct.WorkOrderItemPartRequest.Remove(dbObject); - await ct.SaveChangesAsync(); + var dbObject = await PartRequestGetAsync(id, false); + PartRequestValidateCanDelete(dbObject); + if (HasErrors) + return false; + ct.WorkOrderItemPartRequest.Remove(dbObject); + await ct.SaveChangesAsync(); - //Log event + //Log event await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); @@ -2577,7 +2579,7 @@ namespace AyaNova.Biz //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemScheduledUser.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemScheduledUser, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); //await ScheduledUserSearchIndexAsync(newObject, true); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Created, newObject); @@ -2590,41 +2592,32 @@ namespace AyaNova.Biz // internal async Task ScheduledUserGetAsync(long id, bool logTheGetEvent = true) { - //Note: there could be rules checking here in future, i.e. can only get own workorder or something - //if so, then need to implement AddError and in route handle Null return with Error check just like PUT route does now - - //https://docs.microsoft.com/en-us/ef/core/querying/related-data - //docs say this will not query twice but will recognize the duplicate woitem bit which is required for multiple grandchild collections - var ret = - await ct.WorkOrderItemScheduledUser - .SingleOrDefaultAsync(z => z.Id == id); + var ret = await ct.WorkOrderItemScheduledUser.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, AyaType.WorkOrderItemScheduledUser, AyaEvent.Retrieved), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, ret.AyaType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // - internal async Task ScheduledUserPutAsync(WorkOrderItemScheduledUser dtPutObject) + internal async Task ScheduledUserPutAsync(WorkOrderItemScheduledUser putObject) { - WorkOrderItemScheduledUser dbObject = await ct.WorkOrderItemScheduledUser.SingleOrDefaultAsync(z => z.Id == dtPutObject.Id); + WorkOrderItemScheduledUser dbObject = await ScheduledUserGetAsync(putObject.Id, false); if (dbObject == null) { AddError(ApiErrorCode.NOT_FOUND, "id"); return null; } - - // make a snapshot of the original for validation but update the original to preserve workflow - WorkOrderItemScheduledUser SnapshotOfOriginalDBObj = new WorkOrderItemScheduledUser(); - CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj); - CopyObject.Copy(dtPutObject, dbObject, "Id"); + if (dbObject.Concurrency != putObject.Concurrency) + { + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); - - ct.Entry(dbObject).OriginalValues["Concurrency"] = dtPutObject.Concurrency; - await ScheduledUserValidateAsync(dbObject, SnapshotOfOriginalDBObj); + await ScheduledUserValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); try @@ -2633,37 +2626,50 @@ namespace AyaNova.Biz } catch (DbUpdateConcurrencyException) { - if (!await ScheduledUserExistsAsync(dtPutObject.Id)) + if (!await ScheduledUserExistsAsync(putObject.Id)) AddError(ApiErrorCode.NOT_FOUND); else AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, AyaType.WorkOrderItemScheduledUser, AyaEvent.Modified), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); // await ScheduledUserSearchIndexAsync(dbObject, false); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); - await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj); - return dbObject; + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); + return putObject; } //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // - internal async Task ScheduledUserDeleteAsync(long id) + internal async Task ScheduledUserDeleteAsync(long id, Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction parentTransaction = null) { - WorkOrderItemScheduledUser dbObject = await ct.WorkOrderItemScheduledUser.SingleOrDefaultAsync(z => z.Id == id); - ScheduledUserValidateCanDelete(dbObject); - if (HasErrors) - return false; - ct.WorkOrderItemScheduledUser.Remove(dbObject); - await ct.SaveChangesAsync(); + Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = null; + if (parentTransaction == null) + transaction = await ct.Database.BeginTransactionAsync(); + try + { + var dbObject = await ct.WorkOrderItemScheduledUser.SingleOrDefaultAsync(z => z.Id == id); + ScheduledUserValidateCanDelete(dbObject); + if (HasErrors) + return false; + ct.WorkOrderItemScheduledUser.Remove(dbObject); + await ct.SaveChangesAsync(); - //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemScheduledUser, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//FIX woitem text?? - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemScheduledUser, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); - await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); + //Log event + await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? + await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); + //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); + //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + if (parentTransaction == null) + await transaction.CommitAsync(); + await ScheduledUserHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); + } + catch + { + //Just re-throw for now, let exception handler deal, but in future may want to deal with this more here + throw; + } return true; } @@ -2672,6 +2678,9 @@ namespace AyaNova.Biz // private async Task ScheduledUserValidateAsync(WorkOrderItemScheduledUser proposedObj, WorkOrderItemScheduledUser currentObj) { + //skip validation if seeding + // if (ServerBootConfig.SEEDING) return; + //run validation and biz rules bool isNew = currentObj == null; @@ -2787,7 +2796,7 @@ namespace AyaNova.Biz //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemTask.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemTask, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await TaskSearchIndexAsync(newObject, true); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await TaskHandlePotentialNotificationEvent(AyaEvent.Created, newObject); @@ -2800,41 +2809,31 @@ namespace AyaNova.Biz // internal async Task TaskGetAsync(long id, bool logTheGetEvent = true) { - //Note: there could be rules checking here in future, i.e. can only get own workorder or something - //if so, then need to implement AddError and in route handle Null return with Error check just like PUT route does now - - //https://docs.microsoft.com/en-us/ef/core/querying/related-data - //docs say this will not query twice but will recognize the duplicate woitem bit which is required for multiple grandchild collections - var ret = - await ct.WorkOrderItemTask - .SingleOrDefaultAsync(z => z.Id == id);//FIX asnotracking + var ret = await ct.WorkOrderItemTask.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, AyaType.WorkOrderItemTask, AyaEvent.Retrieved), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, newObject.AyaType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // - internal async Task TaskPutAsync(WorkOrderItemTask dtPutObject) + internal async Task TaskPutAsync(WorkOrderItemTask putObject) { - WorkOrderItemTask dbObject = await ct.WorkOrderItemTask.SingleOrDefaultAsync(z => z.Id == dtPutObject.Id); + WorkOrderItemTask dbObject = await TaskGetAsync(putObject.Id, false); if (dbObject == null) { AddError(ApiErrorCode.NOT_FOUND, "id"); return null; } - - // make a snapshot of the original for validation but update the original to preserve workflow - WorkOrderItemTask SnapshotOfOriginalDBObj = new WorkOrderItemTask(); - CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);//FIX not using copyobject anymore - CopyObject.Copy(dtPutObject, dbObject, "Id"); - + if (dbObject.Concurrency != putObject.Concurrency) + { + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); //dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); - - ct.Entry(dbObject).OriginalValues["Concurrency"] = dtPutObject.Concurrency; - await TaskValidateAsync(dbObject, SnapshotOfOriginalDBObj); + await TaskValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); try @@ -2843,45 +2842,85 @@ namespace AyaNova.Biz } catch (DbUpdateConcurrencyException) { - if (!await TaskExistsAsync(dtPutObject.Id)) + if (!await TaskExistsAsync(putObject.Id)) AddError(ApiErrorCode.NOT_FOUND); else AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, AyaType.WorkOrderItemTask, AyaEvent.Modified), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); await TaskSearchIndexAsync(dbObject, false); // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); - await TaskHandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj); - return dbObject; + await TaskHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); + return putObject; } //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // - internal async Task TaskDeleteAsync(long id) + internal async Task TaskDeleteAsync(long id, Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction parentTransaction = null) { - WorkOrderItemTask dbObject = await ct.WorkOrderItemTask.SingleOrDefaultAsync(z => z.Id == id); - TaskValidateCanDelete(dbObject); - if (HasErrors) - return false; - ct.WorkOrderItemTask.Remove(dbObject); - await ct.SaveChangesAsync(); + Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = null; + if (parentTransaction == null) + transaction = await ct.Database.BeginTransactionAsync(); + try + { + var dbObject = await TaskGetAsync(id, false); + TaskValidateCanDelete(dbObject); + if (HasErrors) + return false; + ct.WorkOrderItemTask.Remove(dbObject); + await ct.SaveChangesAsync(); - //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemTask, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemTask, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); - await TaskHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); + //Log event + await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//Fix?? + await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); + //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); + //await FileUtil.DeleteAttachmentsForObjectAsync(dbObject.AyaType, dbObject.Id, ct); + if (parentTransaction == null) + await transaction.CommitAsync(); + await TaskHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); + } + catch + { + //Just re-throw for now, let exception handler deal, but in future may want to deal with this more here + throw; + } return true; } + ////////////////////////////////////////////// + //INDEXING + // + private async Task TaskSearchIndexAsync(WorkOrderItemTask obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, obj.AyaType); + SearchParams.AddText(obj.Task);//some are manually entered so this is worthwhile for that at least, also I guess predefined tasks that are more rare + + if (isNew) + await Search.ProcessNewObjectKeywordsAsync(SearchParams); + else + await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); + } + + public async Task TaskGetSearchResultSummary(long id) + { + var obj = await TaskGetAsync(id, false); + var SearchParams = new Search.SearchIndexProcessObjectParameters(); + if (obj != null) + SearchParams.AddText(obj.Task); + return SearchParams; + } + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // private async Task TaskValidateAsync(WorkOrderItemTask proposedObj, WorkOrderItemTask currentObj) { + //skip validation if seeding + // if (ServerBootConfig.SEEDING) return; + //run validation and biz rules bool isNew = currentObj == null; @@ -2924,31 +2963,6 @@ namespace AyaNova.Biz } - ////////////////////////////////////////////// - //INDEXING - // - private async Task TaskSearchIndexAsync(WorkOrderItemTask obj, bool isNew) - { - //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItemTask); - SearchParams.AddText(obj.Task);//some are manually entered so this is worthwhile for that at least, also I guess predefined tasks that are more rare - - if (isNew) - await Search.ProcessNewObjectKeywordsAsync(SearchParams); - else - await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); - } - - public async Task TaskGetSearchResultSummary(long id) - { - var obj = await ct.WorkOrderItemTask.SingleOrDefaultAsync(z => z.Id == id); - var SearchParams = new Search.SearchIndexProcessObjectParameters(); - if (obj != null) - SearchParams.AddText(obj.Task); - return SearchParams; - } - - //////////////////////////////////////////////////////////////////////////////////////////////// // NOTIFICATION PROCESSING // @@ -3020,7 +3034,7 @@ namespace AyaNova.Biz //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemTravel.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemTravel, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await TravelSearchIndexAsync(newObject, true); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await TravelHandlePotentialNotificationEvent(AyaEvent.Created, newObject); @@ -3033,41 +3047,32 @@ namespace AyaNova.Biz // internal async Task TravelGetAsync(long id, bool logTheGetEvent = true) { - //Note: there could be rules checking here in future, i.e. can only get own workorder or something - //if so, then need to implement AddError and in route handle Null return with Error check just like PUT route does now - - //https://docs.microsoft.com/en-us/ef/core/querying/related-data - //docs say this will not query twice but will recognize the duplicate woitem bit which is required for multiple grandchild collections - var ret = - await ct.WorkOrderItemTravel - .SingleOrDefaultAsync(z => z.Id == id);//FIX asnotracking + var ret = await ct.WorkOrderItemTravel.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, AyaType.WorkOrderItemTravel, AyaEvent.Retrieved), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, ret.AyaType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // - internal async Task TravelPutAsync(WorkOrderItemTravel dtPutObject) + internal async Task TravelPutAsync(WorkOrderItemTravel putObject) { - WorkOrderItemTravel dbObject = await ct.WorkOrderItemTravel.SingleOrDefaultAsync(z => z.Id == dtPutObject.Id); + WorkOrderItemTravel dbObject = await TravelGetAsync(putObject.Id, false); if (dbObject == null) { AddError(ApiErrorCode.NOT_FOUND, "id"); return null; } - - // make a snapshot of the original for validation but update the original to preserve workflow - WorkOrderItemTravel SnapshotOfOriginalDBObj = new WorkOrderItemTravel(); - CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj); - CopyObject.Copy(dtPutObject, dbObject, "Id");//FIX outdated method + if (dbObject.Concurrency != putObject.Concurrency) + { + AddError(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } //dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags); // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); - - ct.Entry(dbObject).OriginalValues["Concurrency"] = dtPutObject.Concurrency; - await TravelValidateAsync(dbObject, SnapshotOfOriginalDBObj); + await TravelValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); try @@ -3076,45 +3081,87 @@ namespace AyaNova.Biz } catch (DbUpdateConcurrencyException) { - if (!await TravelExistsAsync(dtPutObject.Id)) + if (!await TravelExistsAsync(putObject.Id)) AddError(ApiErrorCode.NOT_FOUND); else AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, AyaType.WorkOrderItemTravel, AyaEvent.Modified), ct); - await TravelSearchIndexAsync(dbObject, false); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); + await TravelSearchIndexAsync(putObject, false); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); - await TravelHandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj); - return dbObject; + await TravelHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); + return putObject; } //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // - internal async Task TravelDeleteAsync(long id) + internal async Task TravelDeleteAsync(long id, Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction parentTransaction = null) { - WorkOrderItemTravel dbObject = await ct.WorkOrderItemTravel.SingleOrDefaultAsync(z => z.Id == id); - TravelValidateCanDelete(dbObject); - if (HasErrors) - return false; - ct.WorkOrderItemTravel.Remove(dbObject); - await ct.SaveChangesAsync(); + Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = null; + if (parentTransaction == null) + transaction = await ct.Database.BeginTransactionAsync(); + try + { + var dbObject = await TravelGetAsync(id, false); + TravelValidateCanDelete(dbObject); + if (HasErrors) + return false; + ct.WorkOrderItemTravel.Remove(dbObject); + await ct.SaveChangesAsync(); - //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemTravel, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemTravel, ct); - // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); - await TravelHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); + //Log event + await EventLogProcessor.DeleteObjectLogAsync(UserId, dbObject.AyaType, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); + await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, dbObject.AyaType, ct); + // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); + //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); + if (parentTransaction == null) + await transaction.CommitAsync(); + await TravelHandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject); + } + catch + { + //Just re-throw for now, let exception handler deal, but in future may want to deal with this more here + throw; + } return true; } + + ////////////////////////////////////////////// + //INDEXING + // + private async Task TravelSearchIndexAsync(WorkOrderItemTravel obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, obj.AyaType); + SearchParams.AddText(obj.Notes).AddText(obj.TravelDetails); + + if (isNew) + await Search.ProcessNewObjectKeywordsAsync(SearchParams); + else + await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); + } + + public async Task TravelGetSearchResultSummary(long id) + { + var obj = await TravelGetAsync(id, false); + var SearchParams = new Search.SearchIndexProcessObjectParameters(); + if (obj != null) + SearchParams.AddText(obj.Notes).AddText(obj.TravelDetails); + return SearchParams; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // private async Task TravelValidateAsync(WorkOrderItemTravel proposedObj, WorkOrderItemTravel currentObj) { + //skip validation if seeding + // if (ServerBootConfig.SEEDING) return; + //run validation and biz rules bool isNew = currentObj == null; @@ -3157,30 +3204,6 @@ namespace AyaNova.Biz } - ////////////////////////////////////////////// - //INDEXING - // - private async Task TravelSearchIndexAsync(WorkOrderItemTravel obj, bool isNew) - { - //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItemTravel); - SearchParams.AddText(obj.Notes).AddText(obj.TravelDetails); - - if (isNew) - await Search.ProcessNewObjectKeywordsAsync(SearchParams); - else - await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); - } - - public async Task TravelGetSearchResultSummary(long id) - { - var obj = await ct.WorkOrderItemTravel.SingleOrDefaultAsync(z => z.Id == id); - var SearchParams = new Search.SearchIndexProcessObjectParameters(); - if (obj != null) - SearchParams.AddText(obj.Notes).AddText(obj.TravelDetails); - return SearchParams; - } - //////////////////////////////////////////////////////////////////////////////////////////////// // NOTIFICATION PROCESSING @@ -3219,7 +3242,7 @@ namespace AyaNova.Biz }//end of process notifications - #endregion work order item LABOR level + #endregion work order item TRAVEL level /*