using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using AyaNova.Models; using AyaNova.Api.ControllerHelpers; using AyaNova.Biz; namespace AyaNova.Api.Controllers { [ApiController] [ApiVersion("8.0")] [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class WorkOrderController : ControllerBase { private readonly AyContext ct; private readonly ILogger log; private readonly ApiServerState serverState; /// /// ctor /// /// /// /// public WorkOrderController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; serverState = apiServerState; } #region WorkOrder top level routes /// /// Get full WorkOrder object /// /// /// A single WorkOrder [HttpGet("{id}")] public async Task GetWorkOrder([FromRoute] long id) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); //Instantiate the business object handler WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); //NOTE: This is the first check and often the only check but in some cases with some objects this will also need to check biz object rules if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); var o = await biz.GetAsync(id); if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); // NOTE: HERE would be the second check of biz rules before returning the object // in cases where there is also a business rule to affect retrieval on top of basic rights return Ok(ApiOkResponse.Response(o, !Authorized.HasModifyRole(HttpContext.Items, biz.BizType))); } //TODO: GET BY RELATIVE //get by descendent type and id /// /// Put (update) WorkOrder /// /// /// /// [HttpPut("{id}")] public async Task PutWorkOrder([FromRoute] long id, [FromBody] WorkOrder inObj) { 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, inObj)) 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)); } /// /// Post Workorder /// /// /// Automatically filled from route path, no need to specify in body /// [HttpPost] public async Task PostWorkOrder([FromBody] WorkOrder inObj, ApiVersion apiVersion) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); //Instantiate the business object handler WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); //If a user has change roles if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); //Create and validate WorkOrder o = await biz.CreateAsync(inObj); 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)); } // /// // /// Post WorkOrder // /// // /// // /// // /// force a workorder number, leave null to autogenerate the next one in sequence (mostly used for import) // /// Automatically filled from route path, no need to specify in body // /// A created workorder ready to fill out // [HttpPost("Create")] // public async Task PostWorkOrder([FromQuery] long? workorderTemplateId, long? customerId, uint? serial, ApiVersion apiVersion) // { // if (!serverState.IsOpen) // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); // //Instantiate the business object handler // WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); // //If a user has change roles // if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) // return StatusCode(403, new ApiNotAuthorizedResponse()); // if (!ModelState.IsValid) // return BadRequest(new ApiErrorResponse(ModelState)); // //Create and validate // WorkOrder o = await biz.CreateAsync(workorderTemplateId,customerId, serial); // 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)); // } //TODO: CreateFromTemplate(templateid) //TODO: Createfromquote(quoteid) //todo: createfrompm(pmid) /// /// Duplicate WorkOrder /// /// Create a duplicate of this items id /// Automatically filled from route path, no need to specify in body /// [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)); //Instantiate the business object handler WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); //If a user has change roles if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); var oSrc = await biz.GetAsync(id, false); if (oSrc == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); //Create and validate WorkOrder o = await biz.DuplicateAsync(oSrc); 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)); } /// /// Delete WorkOrder /// /// /// Ok [HttpDelete("{id}")] public async Task DeleteWorkOrder([FromRoute] long id) { 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.HasDeleteRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); if (!await biz.DeleteAsync(o)) return BadRequest(new ApiErrorResponse(biz.Errors)); return NoContent(); } #endregion WorkorderTopLevel routes #region WorkOrder Item //TODO: Plot exact routes needed here, not all are needed, particularly the collection ones //but maybe handy? Like do I need delete on entire woitems collection? //WorkOrder/{woid}/WorkorderItems <- all workorderitems, post to add new, put to update all as a collection //WorkOrder/{woid}/WorkOrderItems/{woitemid} <- CRUD single woitemid // /// // /// Get full WorkOrder object // /// // /// // /// A single WorkOrder // [HttpGet("{id}")] // public async Task GetWorkOrder([FromRoute] long id) // { // if (!serverState.IsOpen) // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); // //Instantiate the business object handler // WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); // //NOTE: This is the first check and often the only check but in some cases with some objects this will also need to check biz object rules // if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType)) // return StatusCode(403, new ApiNotAuthorizedResponse()); // if (!ModelState.IsValid) // return BadRequest(new ApiErrorResponse(ModelState)); // var o = await biz.GetAsync(id); // if (o == null) // return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); // // NOTE: HERE would be the second check of biz rules before returning the object // // in cases where there is also a business rule to affect retrieval on top of basic rights // return Ok(ApiOkResponse.Response(o, !Authorized.HasModifyRole(HttpContext.Items, biz.BizType))); // } // //TODO: GET BY RELATIVE // //get by descendent type and id // /// // /// Put (update) WorkOrder // /// // /// // /// // /// // [HttpPut("{id}")] // public async Task PutWorkOrder([FromRoute] long id, [FromBody] WorkOrder inObj) // { // 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, inObj)) // 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)); // } // /// // /// Post Workorder // /// // /// // /// Automatically filled from route path, no need to specify in body // /// // [HttpPost] // public async Task PostWorkOrder([FromBody] WorkOrder inObj, ApiVersion apiVersion) // { // if (!serverState.IsOpen) // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); // //Instantiate the business object handler // WorkOrderBiz biz = WorkOrderBiz.GetBiz(ct, HttpContext); // //If a user has change roles // if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) // return StatusCode(403, new ApiNotAuthorizedResponse()); // if (!ModelState.IsValid) // return BadRequest(new ApiErrorResponse(ModelState)); // //Create and validate // WorkOrder o = await biz.CreateAsync(inObj); // 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)); // } /// /// Delete WorkOrderItems /// /// /// Ok [HttpDelete("{WorkOrderId}/WorkorderItems/")] public async Task DeleteWorkOrderItems([FromRoute] long workOrderId) { ////WorkOrder/{woid}/WorkorderItems <- all workorderitems, post to add new, put to update all as a collection ///WorkOrder/{WorkOrderId}/WorkorderItems 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(workOrderId, false); if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); //stubbed out for now just to see routes // if (!await biz.DeleteItemsAsync(o)) // return BadRequest(new ApiErrorResponse(biz.Errors)); return NoContent(); } /// /// Delete WorkOrderItems /// /// /// /// Ok [HttpDelete("{WorkOrderId}/WorkorderItems/{WorkOrderItemId}")] public async Task DeleteWorkOrderItem([FromRoute] long workOrderId, [FromRoute] long workOrderItemId) { ////WorkOrder/{woid}/WorkorderItems <- all workorderitems, post to add new, put to update all as a collection ///WorkOrder/{WorkOrderId}/WorkorderItems 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); if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); var o = await biz.GetAsync(workOrderId, false); if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); //Make sure the item exists first before getting into it if (!o.WorkorderItems.Exists(m => m.Id == workOrderItemId)) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); //stubbed out for now just to see routes // if (!await biz.DeleteItemsAsync(o)) // return BadRequest(new ApiErrorResponse(biz.Errors)); return NoContent(); } #endregion workorderitem #region WorkOrderItemLabor #endregion WorkOrderItemLabor #region WorkOrderItemPart #endregion WorkOrderItemPart //------------ }//eoc }//eons