From 4b72acff49222cd9cc0a0296ecd6c8a207b92b49 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Wed, 31 Mar 2021 20:41:25 +0000 Subject: [PATCH] --- server/AyaNova/biz/WorkOrderBiz.cs | 149 +++++++++++++++-------------- 1 file changed, 77 insertions(+), 72 deletions(-) diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 16de0a86..a10ea197 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -1155,7 +1155,7 @@ namespace AyaNova.Biz // newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemExpense.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemExpense, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await ExpenseSearchIndexAsync(newObject, true); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await ExpenseHandlePotentialNotificationEvent(AyaEvent.Created, newObject); @@ -1168,11 +1168,6 @@ namespace AyaNova.Biz // internal async Task ExpenseGetAsync(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.WorkOrderItemExpense.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, ret.AyaType, AyaEvent.Retrieved), ct); @@ -1228,7 +1223,7 @@ namespace AyaNova.Biz transaction = await ct.Database.BeginTransactionAsync(); try { - WorkOrderItemExpense dbObject = await ct.WorkOrderItemExpense.SingleOrDefaultAsync(z => z.Id == id); + var dbObject = await ExpenseGetAsync(id, false); ExpenseValidateCanDelete(dbObject); if (HasErrors) return false; @@ -1236,8 +1231,8 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemExpense, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemExpense, ct); + 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(BizType, dbObject.Id, ct); if (parentTransaction == null) @@ -1258,7 +1253,7 @@ namespace AyaNova.Biz private async Task ExpenseSearchIndexAsync(WorkOrderItemExpense obj, bool isNew) { //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItemExpense); + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, obj.AyaType); SearchParams.AddText(obj.Name).AddText(obj.Description); if (isNew) @@ -1269,7 +1264,7 @@ namespace AyaNova.Biz public async Task ExpenseGetSearchResultSummary(long id) { - var obj = await ExpenseGetAsync(id, false); + var obj = await ExpenseGetAsync(id, false); var SearchParams = new Search.SearchIndexProcessObjectParameters(); if (obj != null) SearchParams.AddText(obj.Description).AddText(obj.Name); @@ -1393,7 +1388,7 @@ namespace AyaNova.Biz //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemLabor.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemLabor, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); await LaborSearchIndexAsync(newObject, true); // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await LaborHandlePotentialNotificationEvent(AyaEvent.Created, newObject); @@ -1406,41 +1401,33 @@ namespace AyaNova.Biz // internal async Task LaborGetAsync(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.WorkOrderItemLabor - .SingleOrDefaultAsync(z => z.Id == id); + var ret = await ct.WorkOrderItemLabor.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, AyaType.WorkOrderItemLabor, AyaEvent.Retrieved), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, ret.AyaType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // - internal async Task LaborPutAsync(WorkOrderItemLabor dtPutObject) + internal async Task LaborPutAsync(WorkOrderItemLabor putObject) { - WorkOrderItemLabor dbObject = await ct.WorkOrderItemLabor.SingleOrDefaultAsync(z => z.Id == dtPutObject.Id); + var dbObject = await LaborGetAsync(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 - WorkOrderItemLabor SnapshotOfOriginalDBObj = new WorkOrderItemLabor(); - 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 LaborValidateAsync(dbObject, SnapshotOfOriginalDBObj); + await LaborValidateAsync(putObject, dbObject); if (HasErrors) return null; try { @@ -1448,45 +1435,86 @@ namespace AyaNova.Biz } catch (DbUpdateConcurrencyException) { - if (!await LaborExistsAsync(dtPutObject.Id)) + if (!await LaborExistsAsync(putObject.Id)) AddError(ApiErrorCode.NOT_FOUND); else AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, AyaType.WorkOrderItemLabor, AyaEvent.Modified), ct); - await LaborSearchIndexAsync(dbObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); - await LaborHandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj); - return dbObject; + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, putObject.AyaType, AyaEvent.Modified), ct); + await LaborSearchIndexAsync(putObject, false); + //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await LaborHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); + return putObject; } //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // - internal async Task LaborDeleteAsync(long id) + internal async Task LaborDeleteAsync(long id, Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction parentTransaction = null) { - WorkOrderItemLabor dbObject = await ct.WorkOrderItemLabor.SingleOrDefaultAsync(z => z.Id == id); - LaborValidateCanDelete(dbObject); - if (HasErrors) - return false; - ct.WorkOrderItemLabor.Remove(dbObject); - await ct.SaveChangesAsync(); + Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction transaction = null; + if (parentTransaction == null) + transaction = await ct.Database.BeginTransactionAsync(); + try + { + var dbObject = await LaborGetAsync(id, false); + LaborValidateCanDelete(dbObject); + if (HasErrors) + return false; + ct.WorkOrderItemLabor.Remove(dbObject); + await ct.SaveChangesAsync(); - //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemLabor, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct); - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemLabor, ct); - //await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); - await LaborHandlePotentialNotificationEvent(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(BizType, dbObject.Id, ct); + if (parentTransaction == null) + await transaction.CommitAsync(); + await LaborHandlePotentialNotificationEvent(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 LaborSearchIndexAsync(WorkOrderItemLabor obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, obj.AyaType); + SearchParams.AddText(obj.ServiceDetails); + + if (isNew) + await Search.ProcessNewObjectKeywordsAsync(SearchParams); + else + await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); + } + + public async Task LaborGetSearchResultSummary(long id) + { + var obj = await LaborGetAsync(id, false); + var SearchParams = new Search.SearchIndexProcessObjectParameters(); + if (obj != null) + SearchParams.AddText(obj.ServiceDetails); + return SearchParams; + } + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // private async Task LaborValidateAsync(WorkOrderItemLabor proposedObj, WorkOrderItemLabor currentObj) { + //skip validation if seeding + // if (ServerBootConfig.SEEDING) return; + //run validation and biz rules bool isNew = currentObj == null; @@ -1529,29 +1557,6 @@ namespace AyaNova.Biz } - ////////////////////////////////////////////// - //INDEXING - // - private async Task LaborSearchIndexAsync(WorkOrderItemLabor obj, bool isNew) - { - //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, AyaType.WorkOrderItemLabor); - SearchParams.AddText(obj.ServiceDetails); - - if (isNew) - await Search.ProcessNewObjectKeywordsAsync(SearchParams); - else - await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); - } - - public async Task LaborGetSearchResultSummary(long id) - { - var obj = await ct.WorkOrderItemLabor.SingleOrDefaultAsync(z => z.Id == id); - var SearchParams = new Search.SearchIndexProcessObjectParameters(); - if (obj != null) - SearchParams.AddText(obj.ServiceDetails); - return SearchParams; - } //////////////////////////////////////////////////////////////////////////////////////////////// // NOTIFICATION PROCESSING