From ec3dc68dbdb72b232e724392ceddfe1c07a5768a Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 16 Sep 2021 23:00:50 +0000 Subject: [PATCH] --- .../Controllers/WorkOrderController.cs | 48 ++-- server/AyaNova/biz/WorkOrderBiz.cs | 272 +++++++++++++++++- server/AyaNova/models/WorkOrder.cs | 6 +- server/AyaNova/models/WorkOrderItem.cs | 10 + server/AyaNova/models/WorkOrderState.cs | 8 + 5 files changed, 312 insertions(+), 32 deletions(-) diff --git a/server/AyaNova/Controllers/WorkOrderController.cs b/server/AyaNova/Controllers/WorkOrderController.cs index bf5c8424..776dc79e 100644 --- a/server/AyaNova/Controllers/WorkOrderController.cs +++ b/server/AyaNova/Controllers/WorkOrderController.cs @@ -78,31 +78,6 @@ namespace AyaNova.Api.Controllers } - // /// - // /// Duplicate WorkOrder - // /// (Wiki and Attachments are not duplicated) - // /// - // /// Source object id - // /// From route path - // /// WorkOrder - // [HttpPost("duplicate/{id}")] - // public async Task DuplicateWorkOrder([FromRoute] long id, ApiVersion apiVersion) - // { - // if (!serverState.IsOpen) - // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - // WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); - // if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) - // return StatusCode(403, new ApiNotAuthorizedResponse()); - // if (!ModelState.IsValid) - // return BadRequest(new ApiErrorResponse(ModelState)); - // WorkOrder o = await biz.WorkOrderDuplicateAsync(id); - // if (o == null) - // return BadRequest(new ApiErrorResponse(biz.Errors)); - // else - // return CreatedAtAction(nameof(WorkOrderController.GetWorkOrder), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o)); - // } - - /// /// Get WorkOrder /// @@ -1127,6 +1102,29 @@ namespace AyaNova.Api.Controllers return NoContent(); } + + + /// + /// Get WorkOrderItemScheduledUser schedule info + /// + /// + /// Information to display in schedule when selected for more info + [HttpGet("items/scheduled-users/sched-info/{WorkOrderItemScheduledUserId}")] + public async Task GetScheduledUserScheduleInfoView([FromRoute] long WorkOrderItemScheduledUserId) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); + if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.WorkOrderItemScheduledUser)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + if (!ModelState.IsValid) + return BadRequest(new ApiErrorResponse(ModelState)); + var o = await biz.ScheduledUserGetScheduleInfoViewAsync(WorkOrderItemScheduledUserId); + if (o == null) + return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); + return Ok(ApiOkResponse.Response(o)); + } + #endregion WorkOrderItemScheduledUser diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 6e748cf9..180dc10f 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -816,7 +816,7 @@ namespace AyaNova.Biz return await WorkOrderGetAsync(id, true, false, populateForReporting); var wid = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); //get header only - var ret = await ct.WorkOrder.AsNoTracking().SingleOrDefaultAsync(x => x.Id == wid.ParentId); + var ret = await ct.WorkOrder.AsNoTracking().Include(s => s.States).SingleOrDefaultAsync(x => x.Id == wid.ParentId); //not found don't bomb, just return null if (ret == null) return ret; //explicit load subitems as required... @@ -840,10 +840,8 @@ namespace AyaNova.Biz } else { - //get the single workorder item required woitem = await ct.WorkOrderItem.AsNoTracking().SingleOrDefaultAsync(x => x.Id == wid.ChildItemId); - switch (ayaType) { case AyaType.WorkOrderItemExpense: @@ -1445,6 +1443,12 @@ namespace AyaNova.Biz private async Task StatePopulateVizFields(WorkOrderState o) { o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync(); + var StateInfo = await ct.WorkOrderStatus.AsNoTracking().Where(x => x.Id == o.WorkOrderStatusId).FirstOrDefaultAsync(); + o.NameViz = StateInfo.Name; + o.ColorViz = StateInfo.Color; + o.CompletedViz = StateInfo.Completed; + o.LockedViz = StateInfo.Locked; + } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -1776,7 +1780,7 @@ namespace AyaNova.Biz CustomerServiceRequestBiz biz = CustomerServiceRequestBiz.GetBiz(ct); var csr = await biz.GetAsync((long)newObject.FromCSRId, false); csr.WorkOrderItemId = newObject.Id; - csr.Status=CustomerServiceRequestStatus.Accepted; + csr.Status = CustomerServiceRequestStatus.Accepted; await biz.PutAsync(csr); } @@ -1981,6 +1985,20 @@ namespace AyaNova.Biz if (o.FromCSRId != null) o.FromCSRViz = await ct.CustomerServiceRequest.AsNoTracking().Where(x => x.Id == o.FromCSRId).Select(x => x.Name).FirstOrDefaultAsync(); + if (o.WorkOrderItemStatusId != null) + { + var StatusInfo = await ct.WorkOrderItemStatus.AsNoTracking().FirstOrDefaultAsync(x => x.Id == o.WorkOrderItemStatusId); + o.WorkOrderItemStatusNameViz = StatusInfo.Name; + o.WorkOrderItemStatusColorViz = StatusInfo.Color; + } + + if (o.WorkOrderItemPriorityId != null) + { + var PriorityInfo = await ct.WorkOrderItemPriority.AsNoTracking().FirstOrDefaultAsync(x => x.Id == o.WorkOrderItemPriorityId); + o.WorkOrderItemPriorityNameViz = PriorityInfo.Name; + o.WorkOrderItemPriorityColorViz = PriorityInfo.Color; + } + foreach (var v in o.Expenses) await ExpensePopulateVizFields(v); foreach (var v in o.Labors) @@ -4874,6 +4892,252 @@ namespace AyaNova.Biz return true; } + //////////////////////////////////////////////////////////////////////////////////////////////// + // GET Schedule view "more info" display values + // + internal async Task ScheduledUserGetScheduleInfoViewAsync(long id, bool logTheGetEvent = true) + { + /* + MORE INFO DISPLAY + Summary info to display for woitem when open dialog (MUST check at server if restricted tech and not send / show some if not all of this) + No controls to change the time / date for now + + wosummary + wostatus + woitemsummary + woitemstatus + woitempriority + tech + estimated qty + rate + tags + + */ + var w = await WorkOrderGetPartialAsync(AyaType.WorkOrderItemScheduledUser, id, false, true); + + if (UserIsRestrictedType && w.Items[0].ScheduledUsers[0].UserId != UserId)//restricted users can only see their own + return null; + + /* + { + "data": { + "id": 6, + "concurrency": 14171235, + "serial": 6, + "notes": "Esse aut totam adipisci minima optio rerum sed qui.", + "wiki": null, + "customFields": null, + "tags": [ + "black", + "jade", + "zebra", + "zone0", + "zone6" + ], + "customerId": 11, + "customerViz": "Parker, Ryan and Denesik", + "customerTechNotesViz": null, + "projectId": null, + "projectViz": null, + "internalReferenceNumber": "irf-5922", + "customerReferenceNumber": "crf-8231", + "customerContactName": null, + "fromQuoteId": null, + "fromPMId": null, + "createdDate": "2021-09-16T13:58:46.481767Z", + "serviceDate": "2021-11-11T23:00:00Z", + "completeByDate": "2021-11-16T23:00:00Z", + "durationToCompleted": "00:00:00", + "invoiceNumber": null, + "customerSignature": null, + "customerSignatureName": null, + "customerSignatureCaptured": null, + "techSignature": null, + "techSignatureName": null, + "techSignatureCaptured": null, + "onsite": false, + "contractId": null, + "contractViz": "-", + "lastStatusId": 1, + "postAddress": "014 Roberts Garden", + "postCity": "Chesterborough", + "postRegion": "California", + "postCountry": "Nauru", + "postCode": "66467", + "address": "0844 Zieme Prairie", + "city": "Chesterborough", + "region": "California", + "country": "Nauru", + "latitude": -2.527, + "longitude": 132.4754, + "items": [ + { + "id": 14, + "concurrency": 14171235, + "notes": "itemnotes - 2 ", + "wiki": null, + "customFields": null, + "tags": [], + "workOrderId": 6, + "techNotes": "technotes - 2", + "workOrderItemStatusId": 1, + "workOrderItemStatusNameViz": "Item is completed", + "workOrderItemStatusColorViz": "#c00000", + "workOrderItemPriorityId": 1, + "workOrderItemPriorityNameViz": "Immediately", + "workOrderItemPriorityColorViz": "#c00000", + "requestDate": "2021-11-11T23:02:00Z", + "warrantyService": false, + "sequence": 3, + "fromCSRId": null, + "fromCSRViz": null, + "expenses": [], + "labors": [], + "loans": [], + "parts": [], + "partRequests": [], + "scheduledUsers": [ + { + "id": 33, + "concurrency": 14171866, + "userId": 10, + "userViz": "Eliza Hartmann - Tech", + "estimatedQuantity": 1, + "startDate": "2021-11-09T21:00:00Z", + "stopDate": "2021-11-09T22:00:00Z", + "serviceRateId": null, + "serviceRateViz": null, + "workOrderItemId": 14 + } + ], + "tasks": [], + "travels": [], + "units": [], + "outsideServices": [] + } + ], + "states": [ + { + "id": 26, + "concurrency": 14171235, + "workOrderId": 6, + "workOrderStatusId": 2, + "created": "2021-11-11T23:05:00Z", + "userId": 25, + "userViz": "Carroll Miller", + "nameViz": "Needs to be assigned", + "colorViz": "#80ffff", + "completedViz": false, + "lockedViz": false + }, + { + "id": 27, + "concurrency": 14171235, + "workOrderId": 6, + "workOrderStatusId": 3, + "created": "2021-11-12T00:00:00Z", + "userId": 10, + "userViz": "Eliza Hartmann - Tech", + "nameViz": "Scheduled", + "colorViz": "#00ff00", + "completedViz": false, + "lockedViz": false + }, + { + "id": 28, + "concurrency": 14171235, + "workOrderId": 6, + "workOrderStatusId": 1, + "created": "2021-11-12T00:05:00Z", + "userId": 10, + "userViz": "Eliza Hartmann - Tech", + "nameViz": "Manager approval required", + "colorViz": "#c00000", + "completedViz": false, + "lockedViz": true + }, + { + "id": 29, + "concurrency": 14171235, + "workOrderId": 6, + "workOrderStatusId": 3, + "created": "2021-11-12T01:00:00Z", + "userId": 10, + "userViz": "Eliza Hartmann - Tech", + "nameViz": "Scheduled", + "colorViz": "#00ff00", + "completedViz": false, + "lockedViz": false + }, + { + "id": 30, + "concurrency": 14171235, + "workOrderId": 6, + "workOrderStatusId": 1, + "created": "2021-11-12T01:00:00Z", + "userId": 10, + "userViz": "Eliza Hartmann - Tech", + "nameViz": "Manager approval required", + "colorViz": "#c00000", + "completedViz": false, + "lockedViz": true + } + ], + "isLockedAtServer": false, + "alertViz": null, + "fromQuoteViz": null, + "fromPMViz": null, + "isCompleteRecord": true, + "userIsRestrictedType": false, + "userIsTechRestricted": false, + "userIsSubContractorFull": false, + "userIsSubContractorRestricted": false, + "userCanViewPartCosts": false, + "userCanViewLaborOrTravelRateCosts": false, + "userCanViewLoanerCosts": false + } +} + wosummary + wostatus + woitemsummary + woitemstatus + woitempriority + tech + estimated qty + rate + tags + */ + string WoStatusName = string.Empty; + string WoStatusColor = string.Empty; + if (w.States.Count > 0) + { + WoStatusName = w.States[w.States.Count - 1].NameViz; + WoStatusColor = w.States[w.States.Count - 1].ColorViz; + } + + return new + { + serial = w.Serial, + w.CustomerViz, + wosummary = w.Notes, + wostatus = WoStatusName, + wostatuscolor = WoStatusColor, + woitemnotes = w.Items[0].Notes, + woitemtechnotes = w.Items[0].TechNotes, + woitemstatus = w.Items[0].WorkOrderItemStatusNameViz, + woitemstatuscolor = w.Items[0].WorkOrderItemStatusColorViz, + woitempriority = w.Items[0].WorkOrderItemPriorityNameViz, + woitemprioritycolor = w.Items[0].WorkOrderItemPriorityColorViz, + scheduser = w.Items[0].ScheduledUsers[0].UserViz, + qty = w.Items[0].ScheduledUsers[0].EstimatedQuantity, + rate = w.Items[0].ScheduledUsers[0].ServiceRateViz, + wotags = w.Tags, + woitemtags = w.Items[0].Tags + }; + + + } + //////////////////////////////////////////////////////////////////////////////////////////////// //VIZ POPULATE // diff --git a/server/AyaNova/models/WorkOrder.cs b/server/AyaNova/models/WorkOrder.cs index 019fceb7..cc40f402 100644 --- a/server/AyaNova/models/WorkOrder.cs +++ b/server/AyaNova/models/WorkOrder.cs @@ -36,7 +36,7 @@ namespace AyaNova.Models public string CustomerContactName { get; set; } public long? FromQuoteId { get; set; } public long? FromPMId { get; set; } - + public DateTime CreatedDate { get; set; } = DateTime.UtcNow; public DateTime? ServiceDate { get; set; } public DateTime? CompleteByDate { get; set; } @@ -86,7 +86,7 @@ namespace AyaNova.Models public string FromQuoteViz { get; set; } [NotMapped] public string FromPMViz { 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) @@ -110,7 +110,7 @@ namespace AyaNova.Models [NotMapped, JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public AyaTypeId GenCopyAttachmentsFrom { get; set; }//INTERNAL, USED TO SIGNIFY ATTACHMENTS NEED TO BE COPIED ON SAVE - + [NotMapped, JsonIgnore] public AyaType AyaType { get => AyaType.WorkOrder; } diff --git a/server/AyaNova/models/WorkOrderItem.cs b/server/AyaNova/models/WorkOrderItem.cs index 147938a1..53d12d94 100644 --- a/server/AyaNova/models/WorkOrderItem.cs +++ b/server/AyaNova/models/WorkOrderItem.cs @@ -26,7 +26,17 @@ namespace AyaNova.Models public long WorkOrderId { get; set; } public string TechNotes { get; set; } public long? WorkOrderItemStatusId { get; set; } + [NotMapped] + public string WorkOrderItemStatusNameViz { get; set; } + [NotMapped] + public string WorkOrderItemStatusColorViz { get; set; } + public long? WorkOrderItemPriorityId { get; set; } + [NotMapped] + public string WorkOrderItemPriorityNameViz { get; set; } + [NotMapped] + public string WorkOrderItemPriorityColorViz { get; set; } + public DateTime? RequestDate { get; set; } public bool WarrantyService { get; set; } = false; public int Sequence { get; set; } diff --git a/server/AyaNova/models/WorkOrderState.cs b/server/AyaNova/models/WorkOrderState.cs index 57aad7b9..98caa4a1 100644 --- a/server/AyaNova/models/WorkOrderState.cs +++ b/server/AyaNova/models/WorkOrderState.cs @@ -23,6 +23,14 @@ namespace AyaNova.Models public long UserId { get; set; } [NotMapped] public string UserViz { get; set; } + [NotMapped] + public string NameViz { get; set; } + [NotMapped] + public string ColorViz { get; set; } + [NotMapped] + public bool CompletedViz { get; set; } + [NotMapped] + public bool LockedViz { get; set; } //workaround for notification [NotMapped, JsonIgnore]