using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; /// /// CRUD for clinical alert thresholds with Redis cache invalidation on writes. /// [ApiController] [Route("api/v1/alert-thresholds")] [Produces("application/json")] [Authorize] public class AlertThresholdsController : ControllerBase { private readonly IAlertThresholdService _thresholds; public AlertThresholdsController(IAlertThresholdService thresholds) => _thresholds = thresholds; /// /// Creates a new alert threshold for an observation code. /// /// Threshold bounds and display metadata. /// The created threshold. [HttpPost] [AuthorizePermission(ClinicalPermissions.ThresholdsWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status201Created)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status409Conflict)] public async Task Create([FromBody] AlertThresholdRequest req) { var threshold = await _thresholds.CreateAsync(req); return StatusCode(201, ApiResponse.Created(threshold)); } /// /// Lists all alert thresholds ordered by observation code. /// /// All configured thresholds. [HttpGet] [AuthorizePermission(ClinicalPermissions.ThresholdsRead)] [ProducesResponseType(typeof(ApiResponse>), StatusCodes.Status200OK)] public async Task List() { var thresholds = await _thresholds.ListAsync(); return Ok(ApiResponse>.Ok(thresholds)); } /// /// Gets a single alert threshold by id. /// /// Threshold id. /// The threshold record. [HttpGet("{id:guid}")] [AuthorizePermission(ClinicalPermissions.ThresholdsRead)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] public async Task Get(Guid id) { var threshold = await _thresholds.GetByIdAsync(id); return Ok(ApiResponse.Ok(threshold)); } /// /// Updates an existing alert threshold and invalidates the Redis cache entry. /// /// Threshold id. /// Updated threshold bounds and display metadata. /// The updated threshold. [HttpPut("{id:guid}")] [AuthorizePermission(ClinicalPermissions.ThresholdsWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] public async Task Update(Guid id, [FromBody] AlertThresholdRequest req) { var threshold = await _thresholds.UpdateAsync(id, req); return Ok(ApiResponse.Ok(threshold)); } /// /// Deletes an alert threshold. Clinical entities (patients, encounters, observations, /// alerts, scores) are immutable by design and do not support deletion. /// /// Threshold id. [HttpDelete("{id:guid}")] [AuthorizePermission(ClinicalPermissions.ThresholdsWrite)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] public async Task Delete(Guid id) { await _thresholds.DeleteAsync(id); return NoContent(); } }