using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; /// /// Clinical order management: create, list, status transitions, and result recording. /// [ApiController] [Produces("application/json")] [Authorize] public class OrdersController : ControllerBase { private readonly IOrderService _orders; public OrdersController(IOrderService orders) => _orders = orders; /// /// Creates a new clinical order for an encounter. /// [HttpPost("api/v1/encounters/{encounterId:guid}/orders")] [AuthorizePermission(ClinicalPermissions.OrdersWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status201Created)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status409Conflict)] public async Task Create(Guid encounterId, [FromBody] CreateOrderRequest req) { var order = await _orders.CreateAsync(encounterId, req); return StatusCode(201, ApiResponse.Created(order)); } /// /// Lists orders for an encounter with optional status filter. /// [HttpGet("api/v1/encounters/{encounterId:guid}/orders")] [AuthorizePermission(ClinicalPermissions.EncountersRead)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status400BadRequest)] public async Task ListByEncounter( Guid encounterId, [FromQuery] string? status, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { OrderStatus? parsedStatus = null; if (!string.IsNullOrEmpty(status)) { try { parsedStatus = OrderStatusExtensions.FromDbString(status); } catch (ArgumentOutOfRangeException) { return BadRequest(ApiResponse.Fail(400, "Invalid status filter.", "INVALID_STATUS")); } } var result = await _orders.ListByEncounterAsync(encounterId, parsedStatus, page, pageSize); return Ok(ApiResponse.Ok(new { items = result.Items, page = result.Page, pageSize = result.PageSize, totalCount = result.TotalCount, totalPages = result.TotalPages })); } /// /// Gets a single order by id with its encounter. /// [HttpGet("api/v1/orders/{id:guid}")] [AuthorizePermission(ClinicalPermissions.EncountersRead)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] public async Task Get(Guid id) { var order = await _orders.GetByIdAsync(id); return Ok(ApiResponse.Ok(order)); } /// /// Transitions an order to a new status. /// [HttpPatch("api/v1/orders/{id:guid}/status")] [AuthorizePermission(ClinicalPermissions.OrdersWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status409Conflict)] public async Task TransitionStatus(Guid id, [FromBody] TransitionOrderStatusRequest req) { var order = await _orders.TransitionStatusAsync(id, req.Status); return Ok(ApiResponse.Ok(order)); } /// /// Records a result for an order, transitioning it to Resulted status. /// [HttpPatch("api/v1/orders/{id:guid}/result")] [AuthorizePermission(ClinicalPermissions.OrdersWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status409Conflict)] public async Task RecordResult(Guid id, [FromBody] RecordOrderResultRequest req) { var order = await _orders.RecordResultAsync(id, req); return Ok(ApiResponse.Ok(order)); } }