From 50dc5982441b68818fc4d6c7d48e65b00d82d57c Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 3 Nov 2022 18:12:15 +0000 Subject: [PATCH] case 4232 --- docs/8.0/ayanova/docs/changelog.md | 1 + server/AyaNova/biz/WorkOrderBiz.cs | 49 +++++++++++++++++++------ server/AyaNova/models/WorkOrder.cs | 1 + server/AyaNova/models/WorkOrderState.cs | 1 + 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/docs/8.0/ayanova/docs/changelog.md b/docs/8.0/ayanova/docs/changelog.md index 31731f59..b69f3483 100644 --- a/docs/8.0/ayanova/docs/changelog.md +++ b/docs/8.0/ayanova/docs/changelog.md @@ -15,6 +15,7 @@ See the [upgrade instructions](ops-upgrade.md) section of this manual for detail #### Fixed - UI,Server: Unit Model form implemented "Workorders", "Quotes", "Preventive Maintenance" menu items features to view list of those items for the open Unit Model +- Server: Work order, Quote some Roles _with_ Role permission to do so would incorrecty get permission denied when changing status and saving #### Added diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 5498417d..9ec4fd70 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -9,6 +9,7 @@ using System.Linq; using System; using Newtonsoft.Json.Linq; using System.Collections.Generic; +using EnumsNET; namespace AyaNova.Biz { @@ -1711,7 +1712,9 @@ namespace AyaNova.Biz // internal async Task StateCreateAsync(WorkOrderState newObject) { - await StateValidateAsync(newObject, null); + //first validate if this is even a possibility before getting into the further validation + //for roles can select, can remove etc + await StatePreliminaryValidateCanAddAsync(newObject); if (HasErrors) return null; else @@ -1719,17 +1722,36 @@ namespace AyaNova.Biz if (newObject.UserId == 0) newObject.UserId = UserId; - await ct.WorkOrderState.AddAsync(newObject); var wo = await ct.WorkOrder.FirstOrDefaultAsync(x => x.Id == newObject.WorkOrderId); - var newStatusInfo = await ct.WorkOrderStatus.AsNoTracking().FirstOrDefaultAsync(x => x.Id == newObject.WorkOrderStatusId); + var NewStatusInfo = await ct.WorkOrderStatus.AsNoTracking().FirstOrDefaultAsync(x => x.Id == newObject.WorkOrderStatusId); + WorkOrderStatus LastStatusInfo = null; + if (wo.LastStatusId != null) + LastStatusInfo = await ct.WorkOrderStatus.AsNoTracking().FirstOrDefaultAsync(x => x.Id == wo.LastStatusId); + //Level 2 validation - Work order status RemoveRoles, SelectRoles and User roles + + //If we have a last role, can it be removed by this User? + if (LastStatusInfo != null && CurrentUserRoles.HasAnyFlags(LastStatusInfo.RemoveRoles) == false) + { + AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror", "User roles don't align with status Remove roles"); + return null; + } + //Can the new role be selected by this user? + if (CurrentUserRoles.HasAnyFlags(NewStatusInfo.SelectRoles) == false) + { + AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror", "User roles don't align with status Select roles"); + return null; + } + //Seems legit, we'll allow it + + await ct.WorkOrderState.AddAsync(newObject); //Set duration to completed in workorder header //Clear it if set and not completed state //or //Set it if not set and completed state - if (newStatusInfo.Completed && wo.DurationToCompleted == TimeSpan.Zero) + if (NewStatusInfo.Completed && wo.DurationToCompleted == TimeSpan.Zero) wo.DurationToCompleted = DateTime.UtcNow - wo.CreatedDate; - else if (wo.DurationToCompleted != TimeSpan.Zero && !newStatusInfo.Completed) + else if (wo.DurationToCompleted != TimeSpan.Zero && !NewStatusInfo.Completed) wo.DurationToCompleted = TimeSpan.Zero; wo.LastStatusId = newObject.WorkOrderStatusId; await ct.SaveChangesAsync(); @@ -1806,10 +1828,14 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION - // - private async Task StateValidateAsync(WorkOrderState proposedObj, WorkOrderState currentObj) + // + //NOTE: states are only ever *added* to a work order when validation is called + //never deleted, there is deeper validation needed for states related to roles etc + //so this validation just does the preliminary check to see if a change of state is even possible + //before further processing inside the actual update code in the caller + // + private async Task StatePreliminaryValidateCanAddAsync(WorkOrderState proposedObj) { - //of all restricted users, only a restricted tech can change status if (UserIsSubContractorFull || UserIsSubContractorRestricted) { @@ -1817,9 +1843,6 @@ namespace AyaNova.Biz return; } - //run validation and biz rules - bool isNew = currentObj == null; - //does it have a valid workorder id if (proposedObj.WorkOrderId == 0) AddError(ApiErrorCode.VALIDATION_REQUIRED, "WorkOrderId"); @@ -1827,6 +1850,8 @@ namespace AyaNova.Biz { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderId"); } + + } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -7047,7 +7072,7 @@ namespace AyaNova.Biz return mCurrentWorkOrderStatus; } - + diff --git a/server/AyaNova/models/WorkOrder.cs b/server/AyaNova/models/WorkOrder.cs index dbdd0859..29fc252d 100644 --- a/server/AyaNova/models/WorkOrder.cs +++ b/server/AyaNova/models/WorkOrder.cs @@ -110,6 +110,7 @@ namespace AyaNova.Models [NotMapped] public bool LastStateLockedViz { get; set; } + [NotMapped] public bool IsCompleteRecord { get; set; } = true;//indicates if some items were removed due to user role / type restrictions (i.e. woitems they are not scheduled on) diff --git a/server/AyaNova/models/WorkOrderState.cs b/server/AyaNova/models/WorkOrderState.cs index 83a39283..b55f2acd 100644 --- a/server/AyaNova/models/WorkOrderState.cs +++ b/server/AyaNova/models/WorkOrderState.cs @@ -32,6 +32,7 @@ namespace AyaNova.Models [NotMapped] public bool LockedViz { get; set; } + //workaround for notification [NotMapped, JsonIgnore] public List Tags { get; set; } = new List();