From d85497aab6bb037dd715e08599c672eada096d69 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Sun, 17 May 2020 14:57:53 +0000 Subject: [PATCH] --- server/AyaNova/biz/UserBiz.cs | 2 +- server/AyaNova/biz/WidgetBiz.cs | 6 +- server/AyaNova/biz/WorkOrderBiz.cs | 117 +++++++++++++++++- server/AyaNova/models/ICoreBizObjectModel.cs | 19 +++ server/AyaNova/models/User.cs | 4 +- server/AyaNova/models/Widget.cs | 2 +- server/AyaNova/models/WorkOrder.cs | 4 +- server/AyaNova/models/WorkOrderItem.cs | 4 +- server/AyaNova/models/WorkOrderItemExpense.cs | 2 +- 9 files changed, 145 insertions(+), 15 deletions(-) create mode 100644 server/AyaNova/models/ICoreBizObjectModel.cs diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index 0ef5ec31..471f93b4 100644 --- a/server/AyaNova/biz/UserBiz.cs +++ b/server/AyaNova/biz/UserBiz.cs @@ -572,7 +572,7 @@ namespace AyaNova.Biz await ProcessBulkJobAsync(job); break; default: - throw new System.ArgumentOutOfRangeException($"UserBiz.HandleJob-> Invalid job type{job.JobType.ToString()}"); + throw new System.ArgumentOutOfRangeException($"User.HandleJob-> Invalid job type{job.JobType.ToString()}"); } } diff --git a/server/AyaNova/biz/WidgetBiz.cs b/server/AyaNova/biz/WidgetBiz.cs index c63ba008..e794e4c7 100644 --- a/server/AyaNova/biz/WidgetBiz.cs +++ b/server/AyaNova/biz/WidgetBiz.cs @@ -321,8 +321,6 @@ namespace AyaNova.Biz } - - private async Task ProcessBulkJobAsync(OpsJob job) { await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running, ct); @@ -366,7 +364,7 @@ namespace AyaNova.Biz ClearErrors(); //Fetch - var o = await GetAsync(id, false); + var o = (ICoreBizObjectModel)await GetAsync(id, false); //call out processor for each item in turn switch (job.SubType) { @@ -397,7 +395,7 @@ namespace AyaNova.Biz if (SaveIt) { - o = await PutAsync(o); + o = await PutAsync((Widget)o); if (o == null) await JobsBiz.LogJobAsync(job.GId, $"Error processing item {id}: {GetErrorsAsString()}", ct); else diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index af48599b..eedcbce0 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -4,11 +4,14 @@ using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using AyaNova.Models; using System.Linq; +using System; +using Newtonsoft.Json.Linq; +using System.Collections.Generic; namespace AyaNova.Biz { - internal class WorkOrderBiz : BizObject, ISearchAbleObject + internal class WorkOrderBiz : BizObject, IJobObject, ISearchAbleObject { //Feature specific roles internal static AuthorizationRoles RolesAllowedToChangeSerial = AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.AccountingFull; @@ -2343,12 +2346,122 @@ namespace AyaNova.Biz + //////////////////////////////////////////////////////////////////////////////////////////////// //JOB / OPERATIONS // + public async Task HandleJobAsync(OpsJob job) + { + switch (job.JobType) + { + case JobType.BulkCoreBizObjectOperation: + await ProcessBulkJobAsync(job); + break; + default: + throw new System.ArgumentOutOfRangeException($"WorkOrder.HandleJob-> Invalid job type{job.JobType.ToString()}"); + } + } + + + + private async Task ProcessBulkJobAsync(OpsJob job) + { + await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running, ct); + await JobsBiz.LogJobAsync(job.GId, $"Bulk job {job.SubType} started...", ct); + + List idList = new List(); + long ProcessedObjectCount = 0; + JObject jobData = JObject.Parse(job.JobInfo); + + + //TAGS? + string ToTag = null; + string Tag = null; + if (jobData.ContainsKey("tag")) + Tag = (string)jobData["tag"]; + + if (jobData.ContainsKey("toTag")) + ToTag = (string)jobData["toTag"]; + + if (jobData.ContainsKey("idList")) + { + idList = ((JArray)jobData["idList"]).ToObject>(); + // jobData["idList"].Value>(); + } + else + { + //we need to fetch a list of them all because ALL items was selected + //If they wanted to filter (say by Active=true) they can do that from a grid list mass op + idList = await ct.Widget.Select(m => m.Id).ToListAsync(); + } + + + bool SaveIt = false; + //Iterate the list fetching each in turn and sending to the processor to handle + foreach (long id in idList) + { + try + { + SaveIt = false; + //errors would pile up here if not cleared on each iteration + ClearErrors(); + + //Fetch + var o = (ICoreBizObjectModel)await WorkOrderGetAsync(id, false); + //call out processor for each item in turn + switch (job.SubType) + { + case JobSubType.TagAddAny: + case JobSubType.TagAdd: + if (!o.Tags.Contains(Tag)) + { + o.Tags.Add(Tag); + SaveIt = true; + } + break; + case JobSubType.TagRemoveAny: + case JobSubType.TagRemove: + SaveIt = o.Tags.Remove(Tag); + break; + case JobSubType.TagReplaceAny: + case JobSubType.TagReplace: + int index = o.Tags.IndexOf(Tag); + if (index != -1) + { + o.Tags[index] = ToTag; + SaveIt = true; + } + break; + default: + throw new System.ArgumentOutOfRangeException($"ProcessBulkJob -> Invalid job Subtype{job.SubType}"); + } + + if (SaveIt) + { + o = await WorkOrderPutAsync((dtWorkOrder)o); + if (o == null) + await JobsBiz.LogJobAsync(job.GId, $"Error processing item {id}: {GetErrorsAsString()}", ct); + else + ProcessedObjectCount++; + } + else + { + + ProcessedObjectCount++; + } + + } + catch (Exception ex) + { + await JobsBiz.LogJobAsync(job.GId, $"Error processing item {id}", ct); + await JobsBiz.LogJobAsync(job.GId, ExceptionUtil.ExtractAllExceptionMessages(ex), ct); + } + } + await JobsBiz.LogJobAsync(job.GId, $"Bulk job {job.SubType} processed {ProcessedObjectCount} of {idList.Count}", ct); + await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Completed, ct); + } - //Other job handlers here... ///////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/models/ICoreBizObjectModel.cs b/server/AyaNova/models/ICoreBizObjectModel.cs new file mode 100644 index 00000000..7c476361 --- /dev/null +++ b/server/AyaNova/models/ICoreBizObjectModel.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +namespace AyaNova.Models +{ + /// + /// Interface for biz object models with standard fields + /// used for bulk operations etc + /// + internal interface ICoreBizObjectModel + { + public long Id {get;set;} + public uint Concurrency { get; set; } + + public string Wiki { get; set; } + public string CustomFields { get; set; } + public List Tags { get; set; } + + } + +} \ No newline at end of file diff --git a/server/AyaNova/models/User.cs b/server/AyaNova/models/User.cs index e0f3415d..c2dff4cb 100644 --- a/server/AyaNova/models/User.cs +++ b/server/AyaNova/models/User.cs @@ -6,7 +6,7 @@ using Newtonsoft.Json; namespace AyaNova.Models { - public class dtUser//used to return user object without auth related fields in UserGet route + public class dtUser : ICoreBizObjectModel//used to return user object without auth related fields in UserGet route { public dtUser() { @@ -29,7 +29,7 @@ namespace AyaNova.Models public List Tags { get; set; } }//eoc - public class User + public class User : ICoreBizObjectModel { public long Id { get; set; } public uint Concurrency { get; set; } diff --git a/server/AyaNova/models/Widget.cs b/server/AyaNova/models/Widget.cs index 2c609e41..fc4a3170 100644 --- a/server/AyaNova/models/Widget.cs +++ b/server/AyaNova/models/Widget.cs @@ -9,7 +9,7 @@ namespace AyaNova.Models //NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal, otherwise the server will call it an invalid record if the field isn't sent from client //NOTE: In Widget DB schema only name and serial are not nullable - public class Widget + public class Widget : ICoreBizObjectModel { public long Id { get; set; } public uint Concurrency { get; set; } diff --git a/server/AyaNova/models/WorkOrder.cs b/server/AyaNova/models/WorkOrder.cs index 21824af9..e91fbee7 100644 --- a/server/AyaNova/models/WorkOrder.cs +++ b/server/AyaNova/models/WorkOrder.cs @@ -7,7 +7,7 @@ namespace AyaNova.Models { //Data transfer no child collections - public class dtWorkOrder + public class dtWorkOrder : ICoreBizObjectModel { public dtWorkOrder() { @@ -27,7 +27,7 @@ namespace AyaNova.Models }//eoc - public class WorkOrder + public class WorkOrder : ICoreBizObjectModel { public WorkOrder() { diff --git a/server/AyaNova/models/WorkOrderItem.cs b/server/AyaNova/models/WorkOrderItem.cs index 689c427a..13f31112 100644 --- a/server/AyaNova/models/WorkOrderItem.cs +++ b/server/AyaNova/models/WorkOrderItem.cs @@ -5,7 +5,7 @@ using Newtonsoft.Json; namespace AyaNova.Models { - public class dtWorkOrderItem + public class dtWorkOrderItem : ICoreBizObjectModel { public dtWorkOrderItem() { @@ -23,7 +23,7 @@ namespace AyaNova.Models public long WorkOrderId { get; set; } }//eoc - public class WorkOrderItem + public class WorkOrderItem : ICoreBizObjectModel { public WorkOrderItem() { diff --git a/server/AyaNova/models/WorkOrderItemExpense.cs b/server/AyaNova/models/WorkOrderItemExpense.cs index 83a40412..fbfbfd03 100644 --- a/server/AyaNova/models/WorkOrderItemExpense.cs +++ b/server/AyaNova/models/WorkOrderItemExpense.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json; namespace AyaNova.Models { - public class WorkOrderItemExpense + public class WorkOrderItemExpense { public WorkOrderItemExpense() {