using Api.SeaHavenIndustries.DTOs; using Api.SeaHavenIndustries.Helper; using Data.SeaHavenIndustries; using FluentValidation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using SeaHaven.DataServices.Models; using SeaHaven.Services.DTOs; using SeaHaven.Services.Exceptions; using SeaHaven.Services.Interfaces; using System.Security.Claims; namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] [Route("api/WorkOrder")] [Route("api/workorders")] public class WorkOrderController : Controller { private readonly IWorkOrderService _workOrderService; private readonly IWorkOrderAccountResolver _accountResolver; private readonly ILogger _logger; public WorkOrderController( IWorkOrderService workOrderService, IWorkOrderAccountResolver accountResolver, ILogger logger) { _workOrderService = workOrderService; _accountResolver = accountResolver; _logger = logger; } [HttpPost] [Route("AddWorkorder")] public async Task Addworkorder([FromForm] Workorder_DTO model) { try { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var input = new CreateWorkOrderWithDetailsInput { WorkerOrderTitle = model.WorkerOrderTitle ?? "", Description = model.Description, Priority = model.Priority?.ToString(), LocationId = model.LocationId, AssignTo = model.AssignTo, DueDate = model.DueDate, ContactIds = model.ContactIds, CategoryIds = model.CategoryIds, Attachments = model.Attachments, BeforPhotoAttachment = model.BeforPhotoAttachment, AfterPhotoAttachment = model.AfterPhotoAttachment, SignOffAttachment = model.SignOffAttachment, Customer = model.Customer }; var workOrderId = await _workOrderService.CreateWorkOrderWithDetailsAsync(input, User, userId!); return Ok(new DataResponse { Message = "Work order created successfully", Status = "200", Data = workOrderId }); } catch (ValidationException vex) { var errors = string.Join(", ", vex.Errors.Select(e => e.ErrorMessage)); return BadRequest(new Response { Status = "Validation Error", Message = errors }); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message }); } catch (WorkOrderBoardValidationException ex) { return UnprocessableEntity(new Response { Status = "Error", Message = ex.Message }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpPost] [HttpPut("{id:int}")] [Route("EditWorkorder")] public async Task Editworkorder([FromForm] EditWorkorder_DTO model) { try { if (!model.Id.HasValue) return BadRequest(new Response { Status = "Error", Message = "Work order ID is required" }); var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var input = new UpdateWorkOrderWithDetailsInput { Id = model.Id.Value, WorkerOrderTitle = model.WorkerOrderTitle, Description = model.Description, Status = model.Status?.ToString(), Priority = model.Priority?.ToString(), LocationId = model.LocationId, AssignTo = model.AssignTo, DueDate = model.DueDate, CompletedDate = model.CompletedDate, ContactIds = model.ContactIds, CategoryIds = model.CategoryIds, Attachments = model.Attachments, BeforPhotoAttachment = model.BeforPhotoAttachment, AfterPhotoAttachment = model.AfterPhotoAttachment, SignOffAttachment = model.SignOffAttachment }; var success = await _workOrderService.UpdateWorkOrderWithDetailsAsync(input, userId!); if (!success) return BadRequest(new Response { Status = "Error", Message = "Work order not found" }); return Ok(new DataResponse { Message = "Updated Successfully", Status = "200" }); } catch (ValidationException vex) { var errors = string.Join(", ", vex.Errors.Select(e => e.ErrorMessage)); return BadRequest(new Response { Status = "Validation Error", Message = errors }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpGet("GetWorkOrderList")] public async Task GetWorkOrderList(string? search = "", int page = 1, int pageSize = 12, string? sortBy = "lastUpdated", string? sortDir = "desc", string? status = "", string? assignee = "", int? locationId = null) { try { var accountId = _accountResolver.ResolveAccountFilter(User); var (data, totalCount) = await _workOrderService.GetWorkOrderListPagedAsync( page, pageSize, search, status, assignee, locationId, sortBy, sortDir, accountId); var viewModel = new Pagination_DTO { Data = data, PageNumber = page, PageSize = pageSize, TotalCount = totalCount, TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize) }; return Ok(viewModel); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message }); } } [Authorize(Roles = "Admin")] [HttpDelete] [Route("DeleteWorkorder")] public async Task Deleteworkorder([FromBody] EditWorkorder_DTO model) { int id = model.Id.HasValue ? model.Id.Value : 0; if (id == 0) return BadRequest("Id is required"); try { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var success = await _workOrderService.DeleteWorkOrderCascadeAsync(id, userId!); if (!success) return BadRequest("Work order not found!"); return Ok(new DataResponse { Message = "Removed Successfully", Status = "200" }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpGet] [Route("GetFilteredWorkorder")] public async Task GetFilteredWorkorder( [FromQuery] string[] assignto, [FromQuery] int[]? location, [FromQuery] string[]? priority, [FromQuery] string[]? status, [FromQuery] string[]? duedate, [FromQuery] string search = "", [FromQuery] string sort = "Sort Order", [FromQuery] string sortby = "Sort By", int page = 1, int pageSize = 10) { try { var result = await _workOrderService.GetFilteredWorkOrdersAsync( assignto, location, priority, status, duedate, search, sort, sortby, page, pageSize); return Ok(result); } catch (Exception) { return StatusCode(500, "Internal Server Error"); } } [HttpGet("{id:int}")] [HttpGet("GetWorkorderById")] public async Task GetWorkorderById(int id) { var detail = await _workOrderService.GetWorkOrderDetailAsync(id); if (detail == null) return BadRequest(new Response { Status = "Error", Message = "ID not found!" }); return Ok(detail); } [HttpGet] [Route("GetFilteredWorkorder2")] public async Task GetFilteredWorkorder2( [FromQuery] string[] assignto, [FromQuery] int[]? location, [FromQuery] string[]? priority, [FromQuery] string[]? status, [FromQuery] string[]? duedate, [FromQuery] string search = "", [FromQuery] string sort = "Sort Order", [FromQuery] string sortby = "Sort By", int page = 1, int pageSize = 10) { try { var result = await _workOrderService.GetFilteredWorkOrders2Async( assignto, location, priority, status, duedate, search, sort, sortby, page, pageSize); return Ok(result); } catch (Exception) { var totalCount = await _workOrderService.GetTotalWorkOrderCountAsync(); return Ok(new Pagination_DTO { Data = Array.Empty(), PageNumber = page, PageSize = pageSize, TotalCount = totalCount, TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize) }); } } [HttpPost] [Route("ChangeStatus")] public async Task ChangeStatus(int id, string status) { try { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var result = await _workOrderService.ChangeStatusAsync(id, status, userId!); if (result == null) return BadRequest(new Response { Status = "Error", Message = "Work order not found" }); return Ok(new DataResponse { Message = "Updated Successfully", Status = "200", Data = result }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpPost] [Route("ChangeAssignment")] public async Task ChangeAssignment(int id, string? assignTo) { try { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var result = await _workOrderService.ChangeAssignmentAsync(id, assignTo, userId!); if (result == null) return BadRequest(new Response { Status = "Error", Message = "Work order not found" }); return Ok(result); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpPost] [Route("AddComment")] public async Task AddComment([FromForm] Comments_DTO model) { try { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var input = new AddCommentInput { WorkorderId = model.WorkorderId, Text = model.Text, CommentType = model.CommentType, Document = model.Document }; var saved = await _workOrderService.AddCommentAsync(input, userId!); return Ok(new DataResponse { Message = "Updated Successfully", Status = "200", Data = saved }); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpPost] [Route("AddCommentJson")] public async Task AddCommentJson([FromBody] Comments_DTO model) { try { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var input = new AddCommentInput { WorkorderId = model.WorkorderId, Text = model.Text, CommentType = model.CommentType }; var result = await _workOrderService.AddCommentJsonAsync(input, userId!); return Ok(result); } catch (Exception ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpGet] [Route("GetComments")] public async Task GetComments() { var data = await _workOrderService.GetCommentsAsync(); return Ok(data); } [HttpGet] [Route("GetCommentsByWorkorderId")] public async Task GetCommentsByWorkorderId(int woid) { var data = await _workOrderService.GetCommentsByWorkorderIdAsync(woid); return Ok(data); } [HttpGet] [Route("GetworkordersDD")] public async Task GetworkordersDD() { var data = await _workOrderService.GetWorkordersDDAsync(); return Ok(data); } [HttpGet] [Route("Getworkorders")] public async Task Getworkorders() { var data = await _workOrderService.GetWorkordersAsync(); return Ok(data); } } }