From 4f77ee532e12619eb9cd9c22839bb80f807bc239 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Sat, 9 May 2020 16:51:00 +0000 Subject: [PATCH] --- .../Controllers/WorkOrderController.cs | 150 ++++++++++++------ server/AyaNova/biz/WorkOrderBiz.cs | 110 ++++++++++++- 2 files changed, 213 insertions(+), 47 deletions(-) diff --git a/server/AyaNova/Controllers/WorkOrderController.cs b/server/AyaNova/Controllers/WorkOrderController.cs index abca5c1a..aa3ea648 100644 --- a/server/AyaNova/Controllers/WorkOrderController.cs +++ b/server/AyaNova/Controllers/WorkOrderController.cs @@ -128,7 +128,7 @@ namespace AyaNova.Api.Controllers WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); - var o = await biz.PutAsync(id, updatedObject); + var o = await biz.PutAsync(id, updatedObject);//In future may need to return entire object, for now just concurrency token if (o == null) { if (biz.Errors.Exists(m => m.Code == ApiErrorCode.CONCURRENCY_CONFLICT)) @@ -173,6 +173,12 @@ namespace AyaNova.Api.Controllers #endregion WorkOrderTopLevel routes + + + + + + #region WorkOrderItem /// /// Create WorkOrderItem @@ -209,7 +215,7 @@ namespace AyaNova.Api.Controllers if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); - if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType)) + if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.WorkOrderItem)) return StatusCode(403, new ApiNotAuthorizedResponse()); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); @@ -221,46 +227,32 @@ namespace AyaNova.Api.Controllers - // /// - // /// Put (update) WorkOrderItem - // /// - // /// - // /// - // /// - // [HttpPut("items/{WorkOrderItemId}")] - // public async Task PutWorkOrderItem([FromRoute] long id, [FromBody] WorkOrderItem updatedObject) - // { - // if (!serverState.IsOpen) - // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - - // if (!ModelState.IsValid) - // return BadRequest(new ApiErrorResponse(ModelState)); - - // //Instantiate the business object handler - // WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); - - // var o = await biz.GetAsync(id, false); - // if (o == null) - // return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); - - // if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType)) - // return StatusCode(403, new ApiNotAuthorizedResponse()); - - // // try - // // { - // // if (!await biz.PutAsync(o, updatedObject)) - // // return BadRequest(new ApiErrorResponse(biz.Errors)); - // // } - // // catch (DbUpdateConcurrencyException) - // // { - // // if (!await biz.ExistsAsync(id)) - // // return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); - // // else - // // return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT)); - // // } - // // return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true)); - // return StatusCode(501); - // } + /// + /// Put (update) WorkOrderItem + /// (Descendent objects must be updated via their individual routes seperately) + /// + /// WorkOrderItem - top level only, no descendents + /// New concurrency token + [HttpPut("items/")] + public async Task PutWorkOrderItem([FromBody] dtWorkOrderItem updatedObject) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + if (!ModelState.IsValid) + return BadRequest(new ApiErrorResponse(ModelState)); + WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); + if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.WorkOrderItem)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + var o = await biz.ItemPutAsync(updatedObject);//In future may need to return entire object, for now just concurrency token + if (o == null) + { + if (biz.Errors.Exists(m => m.Code == ApiErrorCode.CONCURRENCY_CONFLICT)) + return StatusCode(409, new ApiErrorResponse(biz.Errors)); + else + return BadRequest(new ApiErrorResponse(biz.Errors)); + } + return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true)); + } @@ -318,6 +310,12 @@ namespace AyaNova.Api.Controllers #endregion workorderitem + + + + + + #region WorkOrderItemLabor /// @@ -336,7 +334,7 @@ namespace AyaNova.Api.Controllers return StatusCode(403, new ApiNotAuthorizedResponse()); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - WorkOrderItemLabor o = await biz.CreateLaborAsync(newObject); + WorkOrderItemLabor o = await biz.LaborCreateAsync(newObject); if (o == null) return BadRequest(new ApiErrorResponse(biz.Errors)); else @@ -359,16 +357,51 @@ namespace AyaNova.Api.Controllers return StatusCode(403, new ApiNotAuthorizedResponse()); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - var o = await biz.GetLaborAsync(WorkOrderItemLaborId); + var o = await biz.LaborGetAsync(WorkOrderItemLaborId); if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); return Ok(ApiOkResponse.Response(o, !Authorized.HasModifyRole(HttpContext.Items, AyaType.WorkOrderItemLabor))); } + + + /// + /// Put (update) WorkOrderItemLabor + /// (Descendent objects must be updated via their individual routes seperately) + /// + /// WorkOrderItemLabor - top level only, no descendents + /// New concurrency token + [HttpPut("items/")] + public async Task PutWorkOrderItemLabor([FromBody] WorkOrderItemLabor updatedObject) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + if (!ModelState.IsValid) + return BadRequest(new ApiErrorResponse(ModelState)); + WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); + if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.WorkOrderItemLabor)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + var o = await biz.LaborPutAsync(updatedObject);//In future may need to return entire object, for now just concurrency token + if (o == null) + { + if (biz.Errors.Exists(m => m.Code == ApiErrorCode.CONCURRENCY_CONFLICT)) + return StatusCode(409, new ApiErrorResponse(biz.Errors)); + else + return BadRequest(new ApiErrorResponse(biz.Errors)); + } + return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true)); + } + + #endregion WorkOrderItemLabor - #region WorkOrderItemPart + + + + + #region WorkOrderItemPart + /// /// Create WorkOrderItemPart /// @@ -414,6 +447,33 @@ namespace AyaNova.Api.Controllers return Ok(ApiOkResponse.Response(o, !Authorized.HasModifyRole(HttpContext.Items, AyaType.WorkOrderItemPart))); } + /// + /// Put (update) WorkOrderItemPart + /// (Descendent objects must be updated via their individual routes seperately) + /// + /// WorkOrderItemPart - top level only, no descendents + /// New concurrency token + [HttpPut("items/")] + public async Task PutWorkOrderItemPart([FromBody] WorkOrderItemPart updatedObject) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + if (!ModelState.IsValid) + return BadRequest(new ApiErrorResponse(ModelState)); + WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); + if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.WorkOrderItemPart)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + var o = await biz.PartPutAsync(updatedObject);//In future may need to return entire object, for now just concurrency token + if (o == null) + { + if (biz.Errors.Exists(m => m.Code == ApiErrorCode.CONCURRENCY_CONFLICT)) + return StatusCode(409, new ApiErrorResponse(biz.Errors)); + else + return BadRequest(new ApiErrorResponse(biz.Errors)); + } + return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true)); + } + #endregion WorkOrderItemPart //------------ diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index b79705a9..13fe5f95 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -268,6 +268,12 @@ namespace AyaNova.Biz } #endregion workorder level + + + + + + #region WorkOrderItem level //////////////////////////////////////////////////////////////////////////////////////////////// //EXISTS @@ -321,6 +327,53 @@ namespace AyaNova.Biz } + //////////////////////////////////////////////////////////////////////////////////////////////// + //UPDATE + // + internal async Task ItemPutAsync(dtWorkOrderItem dtPutObject) + { + + WorkOrderItem dbObject = await ct.WorkOrderItem.SingleOrDefaultAsync(m => m.Id == dtPutObject.Id); + 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 + WorkOrderItem SnapshotOfOriginalDBObj = new WorkOrderItem(); + CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj); + + //Replace the db object with the PUT object + CopyObject.Copy(dtPutObject, dbObject, "Id"); + + dbObject.Tags = TagUtil.NormalizeTags(dbObject.Tags); + dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + ct.Entry(dbObject).OriginalValues["ConcurrencyToken"] = dtPutObject.ConcurrencyToken; + await ItemValidateAsync(dbObject, SnapshotOfOriginalDBObj); + if (HasErrors) + return null; + + try + { + await ct.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await ItemExistsAsync(dtPutObject.Id)) + AddError(ApiErrorCode.NOT_FOUND); + else + new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); + await ItemSearchIndexAsync(dbObject, false); + await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + return dbObject; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -380,6 +433,12 @@ namespace AyaNova.Biz } #endregion work order item level + + + + + + #region WorkOrderItemLabor level //////////////////////////////////////////////////////////////////////////////////////////////// //EXISTS @@ -391,7 +450,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// //CREATE // - internal async Task CreateLaborAsync(WorkOrderItemLabor newObject) + internal async Task LaborCreateAsync(WorkOrderItemLabor newObject) { await LaborValidateAsync(newObject, null); if (HasErrors) @@ -412,7 +471,7 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// // GET // - internal async Task GetLaborAsync(long id, bool logTheGetEvent = true) + 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 @@ -427,6 +486,47 @@ namespace AyaNova.Biz return ret; } + //////////////////////////////////////////////////////////////////////////////////////////////// + //UPDATE + // + internal async Task LaborPutAsync(WorkOrderItemLabor dtPutObject) + { + WorkOrderItemLabor dbObject = await ct.WorkOrderItemLabor.SingleOrDefaultAsync(m => m.Id == dtPutObject.Id); + 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"); + + dbObject.Tags = TagUtil.NormalizeTags(dbObject.Tags); + dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); + + ct.Entry(dbObject).OriginalValues["ConcurrencyToken"] = dtPutObject.ConcurrencyToken; + await LaborValidateAsync(dbObject, SnapshotOfOriginalDBObj); + if (HasErrors) return null; + try + { + await ct.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!await LaborExistsAsync(dtPutObject.Id)) + AddError(ApiErrorCode.NOT_FOUND); + else + new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT); + return null; + } + await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); + await LaborSearchIndexAsync(dbObject, false); + await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags); + return dbObject; + } + //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -485,6 +585,12 @@ namespace AyaNova.Biz } #endregion work order item LABOR level + + + + + + #region WorkOrderItemPart level //////////////////////////////////////////////////////////////////////////////////////////////// //EXISTS