mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 22:23:12 +00:00
The route contract keeps the poc endpoint from main and the uplift evidence routes from this branch. Create still passes the scanned evidence document through the locked mutation.
295 lines
13 KiB
C#
295 lines
13 KiB
C#
using Api.SeaHavenIndustries.DTOs;
|
|
using Api.SeaHavenIndustries.Helper;
|
|
using Data.SeaHavenIndustries;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Logging;
|
|
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 WorkOrderDetailController : Controller
|
|
{
|
|
private readonly IWorkOrderDetailService _workOrderDetailService;
|
|
private readonly IWorkOrderCommentService _workOrderCommentService;
|
|
private readonly IWorkOrderUpliftService _workOrderUpliftService;
|
|
private readonly IWorkOrderUpliftEvidenceService _workOrderUpliftEvidenceService;
|
|
private readonly ILogger<WorkOrderDetailController> _logger;
|
|
|
|
public WorkOrderDetailController(
|
|
IWorkOrderDetailService workOrderDetailService,
|
|
IWorkOrderCommentService workOrderCommentService,
|
|
IWorkOrderUpliftService workOrderUpliftService,
|
|
IWorkOrderUpliftEvidenceService workOrderUpliftEvidenceService,
|
|
ILogger<WorkOrderDetailController> logger)
|
|
{
|
|
_workOrderDetailService = workOrderDetailService;
|
|
_workOrderCommentService = workOrderCommentService;
|
|
_workOrderUpliftService = workOrderUpliftService;
|
|
_workOrderUpliftEvidenceService = workOrderUpliftEvidenceService;
|
|
_logger = logger;
|
|
}
|
|
|
|
[HttpGet("{id:int}/detail")]
|
|
public async Task<IActionResult> GetDetail(int id)
|
|
{
|
|
try
|
|
{
|
|
var detail = await _workOrderDetailService.GetDetailAsync(id, User);
|
|
if (detail == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(detail);
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden")
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
[HttpGet("{id:int}/audit")]
|
|
public async Task<IActionResult> GetAudit(int id, [FromQuery] int limit = 50)
|
|
{
|
|
try
|
|
{
|
|
var audit = await _workOrderDetailService.GetAuditAsync(id, User, limit);
|
|
if (audit == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(audit);
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden")
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
[HttpGet("{id:int}/comments")]
|
|
public async Task<IActionResult> GetBoardComments(int id)
|
|
{
|
|
try
|
|
{
|
|
var comments = await _workOrderCommentService.GetCommentsAsync(id, User);
|
|
if (comments == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(comments);
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden")
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden,
|
|
new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
[HttpPost("{id:int}/comments")]
|
|
public async Task<IActionResult> AddBoardComment(int id, [FromBody] WorkOrderCommentCreateDto request)
|
|
{
|
|
try
|
|
{
|
|
var actorId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
|
var comment = await _workOrderCommentService.AddCommentAsync(id, request, User, actorId);
|
|
return Ok(comment);
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "NotFound")
|
|
{
|
|
return NotFound(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden")
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden,
|
|
new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
catch (WorkOrderBoardValidationException ex)
|
|
{
|
|
return UnprocessableEntity(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
[HttpPatch("{id:int}/comments/{commentId:int}")]
|
|
public async Task<IActionResult> UpdateBoardComment(
|
|
int id,
|
|
int commentId,
|
|
[FromBody] WorkOrderCommentCreateDto request)
|
|
{
|
|
try
|
|
{
|
|
var actorId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
|
var comment = await _workOrderCommentService.UpdateCommentAsync(
|
|
id, commentId, request, User, actorId);
|
|
return Ok(comment);
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "NotFound")
|
|
{
|
|
return NotFound(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden")
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden,
|
|
new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
catch (WorkOrderBoardValidationException ex)
|
|
{
|
|
return UnprocessableEntity(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
[HttpGet("{id:int}/uplifts")]
|
|
public async Task<IActionResult> ListUplifts(int id, CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var items = await _workOrderUpliftService.ListAsync(id, User, cancellationToken);
|
|
if (items == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(new DataResponse { Status = "Success", Data = new WorkOrderUpliftListDto { Items = items.ToList() } });
|
|
}
|
|
catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden")
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message });
|
|
}
|
|
}
|
|
|
|
[HttpPost("{id:int}/uplifts")]
|
|
public async Task<IActionResult> CreateUplift(
|
|
int id,
|
|
[FromBody] CreateWorkOrderUpliftRequestDto request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var created = await _workOrderUpliftService.CreateAsync(id, request, User, cancellationToken);
|
|
if (created == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(new DataResponse { Status = "Success", Data = created });
|
|
}
|
|
catch (UpliftConflictException ex)
|
|
{
|
|
return Conflict(new Response { Status = "Error", Message = ex.Message });
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Resource not found") });
|
|
}
|
|
catch (UpliftForbiddenException ex)
|
|
{
|
|
var message = ex.Message == UpliftForbiddenException.RequestUpliftsDeniedMessage
|
|
? UpliftForbiddenException.RequestUpliftsDeniedMessage
|
|
: _logger.Sanitize(ex, "You are not authorized to perform this action");
|
|
return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = message });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The uplift request could not be created") });
|
|
}
|
|
}
|
|
|
|
[HttpPost("{id:int}/uplift-evidence")]
|
|
[RequestSizeLimit(10_000_000)]
|
|
public async Task<IActionResult> UploadUpliftEvidence(
|
|
int id,
|
|
[FromForm] IFormFile file,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var uploaded = await _workOrderUpliftEvidenceService.UploadAsync(id, file, User, cancellationToken);
|
|
if (uploaded == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(new DataResponse { Status = "Success", Data = uploaded });
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Resource not found") });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The evidence file could not be uploaded") });
|
|
}
|
|
}
|
|
|
|
[HttpGet("{id:int}/uplift-evidence/{documentId:int}")]
|
|
public async Task<IActionResult> GetUpliftEvidenceStatus(
|
|
int id,
|
|
int documentId,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var status = await _workOrderUpliftEvidenceService.GetStatusAsync(id, documentId, User, cancellationToken);
|
|
if (status == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Evidence document not found." });
|
|
return Ok(new DataResponse { Status = "Success", Data = status });
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Resource not found") });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The evidence file could not be read") });
|
|
}
|
|
}
|
|
|
|
[HttpPost("{id:int}/uplifts/{upliftId:int}/cancel")]
|
|
public async Task<IActionResult> CancelUplift(int id, int upliftId, CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var cancelled = await _workOrderUpliftService.CancelAsync(id, upliftId, User, cancellationToken);
|
|
if (cancelled == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(new DataResponse { Status = "Success", Data = cancelled });
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Uplift request not found") });
|
|
}
|
|
catch (UpliftForbiddenException ex)
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action") });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The uplift request cannot be cancelled in its current state") });
|
|
}
|
|
}
|
|
|
|
[HttpPost("{id:int}/uplifts/{upliftId:int}/revoke")]
|
|
public async Task<IActionResult> RevokeUplift(
|
|
int id,
|
|
int upliftId,
|
|
[FromBody] RevokeWorkOrderUpliftRequestDto? request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var revoked = await _workOrderUpliftService.RevokeAsync(
|
|
id,
|
|
upliftId,
|
|
request ?? new RevokeWorkOrderUpliftRequestDto(),
|
|
User,
|
|
cancellationToken);
|
|
if (revoked == null)
|
|
return NotFound(new Response { Status = "Error", Message = "Work order not found." });
|
|
return Ok(new DataResponse { Status = "Success", Data = revoked });
|
|
}
|
|
catch (KeyNotFoundException ex)
|
|
{
|
|
return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Uplift request not found") });
|
|
}
|
|
catch (UpliftForbiddenException ex)
|
|
{
|
|
return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action") });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The uplift request cannot be revoked in its current state") });
|
|
}
|
|
}
|
|
}
|
|
}
|