Run initial test for Climate Resilience Verification Suite
Add first part of Alert Quality Analytics
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Authorize]
|
||||
public class AlertQualityMetricsController : ControllerBase
|
||||
{
|
||||
private readonly IAlertQualityMetricsService _metrics;
|
||||
|
||||
public AlertQualityMetricsController(IAlertQualityMetricsService metrics) =>
|
||||
_metrics = metrics;
|
||||
|
||||
/// <summary>
|
||||
/// Returns alert quality metric snapshots for a time range, optionally filtered by alert type.
|
||||
/// </summary>
|
||||
[HttpGet("api/v1/alerts/quality-metrics")]
|
||||
[AuthorizePermission(ClinicalPermissions.AnalyticsRead)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> List(
|
||||
[FromQuery] string? alertType,
|
||||
[FromQuery] DateTimeOffset? from,
|
||||
[FromQuery] DateTimeOffset? to)
|
||||
{
|
||||
AlertType? parsedType = null;
|
||||
if (!string.IsNullOrEmpty(alertType))
|
||||
{
|
||||
try
|
||||
{
|
||||
parsedType = AlertTypeExtensions.FromDbString(alertType);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return BadRequest(ApiResponse<object>.Fail(
|
||||
400, "Invalid alert type filter.", "INVALID_ALERT_TYPE"));
|
||||
}
|
||||
}
|
||||
|
||||
var periodEnd = to ?? DateTimeOffset.UtcNow;
|
||||
var periodStart = from ?? periodEnd.AddDays(-7);
|
||||
if (periodStart >= periodEnd)
|
||||
{
|
||||
return BadRequest(ApiResponse<object>.Fail(
|
||||
400, "'from' must be before 'to'.", "INVALID_DATE_RANGE"));
|
||||
}
|
||||
|
||||
var items = await _metrics.ListAsync(parsedType, periodStart, periodEnd);
|
||||
return Ok(ApiResponse<object>.Ok(new
|
||||
{
|
||||
periodStart,
|
||||
periodEnd,
|
||||
items
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns aggregate alert quality rates across all alert types for a time range.
|
||||
/// </summary>
|
||||
[HttpGet("api/v1/alerts/quality-metrics/summary")]
|
||||
[AuthorizePermission(ClinicalPermissions.AnalyticsRead)]
|
||||
[ProducesResponseType(typeof(ApiResponse<AlertQualitySummaryResponse>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Summary(
|
||||
[FromQuery] DateTimeOffset? from,
|
||||
[FromQuery] DateTimeOffset? to)
|
||||
{
|
||||
var periodEnd = to ?? DateTimeOffset.UtcNow;
|
||||
var periodStart = from ?? periodEnd.AddDays(-7);
|
||||
|
||||
var summary = await _metrics.GetSummaryAsync(periodStart, periodEnd);
|
||||
return Ok(ApiResponse<AlertQualitySummaryResponse>.Ok(summary));
|
||||
}
|
||||
}
|
||||
@@ -173,4 +173,30 @@ public class AlertsController : ControllerBase
|
||||
var alert = await _alerts.ResolveAsync(id);
|
||||
return Ok(ApiResponse<ClinicalAlert>.Ok(alert));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits clinician feedback for an acknowledged or resolved alert.
|
||||
/// One submission per user per alert.
|
||||
/// </summary>
|
||||
[HttpPost("api/v1/alerts/{id:guid}/feedback")]
|
||||
[AuthorizePermission(ClinicalPermissions.AlertsFeedback)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status201Created)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
|
||||
public async Task<IActionResult> SubmitFeedback(
|
||||
Guid id, [FromBody] SubmitAlertFeedbackRequest req)
|
||||
{
|
||||
var feedback = await _alerts.SubmitFeedbackAsync(id, req.FeedbackType, req.Comment);
|
||||
return Created(
|
||||
$"/api/v1/alerts/{id}/feedback/{feedback.Id}",
|
||||
ApiResponse<object>.Ok(new
|
||||
{
|
||||
id = feedback.Id,
|
||||
alertId = feedback.AlertId,
|
||||
feedbackType = feedback.FeedbackType.ToString(),
|
||||
comment = feedback.Comment,
|
||||
createdAt = feedback.CreatedAt
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user