diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 03286ca1..19128196 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -2362,7 +2362,7 @@ namespace AyaNova.Biz //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); await ct.WorkOrderItemPartRequest.AddAsync(newObject); await ct.SaveChangesAsync(); - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, AyaType.WorkOrderItemPartRequest, AyaEvent.Created), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, newObject.AyaType, AyaEvent.Created), ct); //await PartRequestSearchIndexAsync(newObject, true); //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); await PartRequestHandlePotentialNotificationEvent(AyaEvent.Created, newObject); @@ -2375,41 +2375,31 @@ namespace AyaNova.Biz // internal async Task PartRequestGetAsync(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.WorkOrderItemPartRequest - .SingleOrDefaultAsync(z => z.Id == id);//FIX this GetAsync not using AsNoTracking and neither are any of the others!! + var ret = await ct.WorkOrderItemPartRequest.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, AyaType.WorkOrderItemPartRequest, AyaEvent.Retrieved), ct); + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, ret.AyaType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //UPDATE // - internal async Task PartRequestPutAsync(WorkOrderItemPartRequest dtPutObject) + internal async Task PartRequestPutAsync(WorkOrderItemPartRequest putObject) { - WorkOrderItemPartRequest dbObject = await ct.WorkOrderItemPartRequest.SingleOrDefaultAsync(z => z.Id == dtPutObject.Id); + WorkOrderItemPartRequest dbObject = await PartRequestGetAsync(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 - WorkOrderItemPartRequest SnapshotOfOriginalDBObj = new WorkOrderItemPartRequest(); - 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 PartRequestValidateAsync(dbObject, SnapshotOfOriginalDBObj); + await PartRequestValidateAsync(putObject, dbObject); if (HasErrors) return null; ct.Replace(dbObject, putObject); try @@ -2418,37 +2408,50 @@ namespace AyaNova.Biz } catch (DbUpdateConcurrencyException) { - if (!await PartRequestExistsAsync(dtPutObject.Id)) + if (!await PartRequestExistsAsync(putObject.Id)) AddError(ApiErrorCode.NOT_FOUND); else AddError(ApiErrorCode.CONCURRENCY_CONFLICT); return null; } - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, AyaType.WorkOrderItemPartRequest, AyaEvent.Modified), ct); - // await PartRequestSearchIndexAsync(dbObject, false); - //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); - await PartRequestHandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj); - return dbObject; + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, putObject.Id, putObject.AyaType, AyaEvent.Modified), ct); + // await PartRequestSearchIndexAsync(putObject, false); + //await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags); + await PartRequestHandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject); + return putObject; } //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // - internal async Task PartRequestDeleteAsync(long id) + internal async Task PartRequestDeleteAsync(long id, Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction parentTransaction = null) { - WorkOrderItemPartRequest dbObject = await ct.WorkOrderItemPartRequest.SingleOrDefaultAsync(z => z.Id == id); + 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(); - //Log event - await EventLogProcessor.DeleteObjectLogAsync(UserId, AyaType.WorkOrderItemPartRequest, dbObject.Id, "woitem:" + dbObject.WorkOrderItemId.ToString(), ct);//FIX "woitem"?? - await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, AyaType.WorkOrderItemPartRequest, ct); - // await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags); - //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); - await PartRequestHandlePotentialNotificationEvent(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 ExpenseHandlePotentialNotificationEvent(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; } @@ -2457,6 +2460,9 @@ namespace AyaNova.Biz // private async Task PartRequestValidateAsync(WorkOrderItemPartRequest proposedObj, WorkOrderItemPartRequest currentObj) { + //skip validation if seeding + // if (ServerBootConfig.SEEDING) return; + //run validation and biz rules bool isNew = currentObj == null;