feature: Degraded Operations Visibility
This commit is contained in:
@@ -12,8 +12,15 @@ using Microsoft.AspNetCore.Mvc;
|
||||
public class EncountersController : ControllerBase
|
||||
{
|
||||
private readonly IEncounterService _encounters;
|
||||
private readonly IDischargeSummaryService _dischargeSummary;
|
||||
|
||||
public EncountersController(IEncounterService encounters) => _encounters = encounters;
|
||||
public EncountersController(
|
||||
IEncounterService encounters,
|
||||
IDischargeSummaryService dischargeSummary)
|
||||
{
|
||||
_encounters = encounters;
|
||||
_dischargeSummary = dischargeSummary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists encounters for ward dashboards with denormalized clinical summary fields.
|
||||
@@ -115,4 +122,31 @@ public class EncountersController : ControllerBase
|
||||
var timeline = await _encounters.GetTimelineAsync(id);
|
||||
return Ok(ApiResponse<object>.Ok(timeline));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns discharge summary availability for a discharged encounter.
|
||||
/// </summary>
|
||||
[HttpGet("{id:guid}/discharge-summary")]
|
||||
[AuthorizePermission(ClinicalPermissions.EncountersRead)]
|
||||
[ProducesResponseType(typeof(ApiResponse<DischargeSummaryInfo>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> GetDischargeSummary(Guid id)
|
||||
{
|
||||
var info = await _dischargeSummary.GetInfoAsync(id);
|
||||
return Ok(ApiResponse<DischargeSummaryInfo>.Ok(info));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the generated discharge summary document.
|
||||
/// </summary>
|
||||
[HttpGet("{id:guid}/discharge-summary/content")]
|
||||
[AuthorizePermission(ClinicalPermissions.EncountersRead)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
|
||||
public async Task<IActionResult> DownloadDischargeSummary(Guid id)
|
||||
{
|
||||
var content = await _dischargeSummary.GetContentAsync(id);
|
||||
return File(content.Stream, content.ContentType, content.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
/// <summary>
|
||||
/// Gateway fleet operations: fleet listing, gateway detail, and site summaries.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/v1/operations")]
|
||||
[Authorize]
|
||||
[Produces("application/json")]
|
||||
public class OperationsController : ControllerBase
|
||||
{
|
||||
private readonly IOperationsService _operations;
|
||||
|
||||
public OperationsController(IOperationsService operations) => _operations = operations;
|
||||
|
||||
/// <summary>
|
||||
/// Lists registered gateways with optional status and site filters.
|
||||
/// </summary>
|
||||
/// <param name="status">Optional gateway status filter (DB literal, e.g. DEGRADED).</param>
|
||||
/// <param name="siteId">Optional site id filter.</param>
|
||||
/// <returns>Gateway fleet items.</returns>
|
||||
[HttpGet("gateways")]
|
||||
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<GatewayFleetItem>>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> ListGateways(
|
||||
[FromQuery] string? status,
|
||||
[FromQuery] Guid? siteId,
|
||||
CancellationToken ct)
|
||||
{
|
||||
var items = await _operations.GetGatewayFleetAsync(
|
||||
new GatewayFleetFilter(status, siteId), ct);
|
||||
return Ok(ApiResponse<IReadOnlyList<GatewayFleetItem>>.Ok(items));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single gateway by id with buffer depth, heartbeat metadata, and sync history.
|
||||
/// </summary>
|
||||
/// <param name="gatewayId">Gateway id.</param>
|
||||
/// <returns>Gateway detail.</returns>
|
||||
[HttpGet("gateways/{gatewayId:guid}")]
|
||||
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
|
||||
[ProducesResponseType(typeof(ApiResponse<GatewayDetailResponse>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> GetGateway(Guid gatewayId, CancellationToken ct)
|
||||
{
|
||||
var detail = await _operations.GetGatewayDetailAsync(gatewayId, ct);
|
||||
return Ok(ApiResponse<GatewayDetailResponse>.Ok(detail));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an aggregate gateway summary for a site.
|
||||
/// </summary>
|
||||
/// <param name="siteId">Site id.</param>
|
||||
/// <returns>Site gateway summary.</returns>
|
||||
[HttpGet("sites/{siteId:guid}/summary")]
|
||||
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
|
||||
[ProducesResponseType(typeof(ApiResponse<SiteGatewaySummaryResponse>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> GetSiteSummary(Guid siteId, CancellationToken ct)
|
||||
{
|
||||
var summary = await _operations.GetSiteSummaryAsync(siteId, ct);
|
||||
return Ok(ApiResponse<SiteGatewaySummaryResponse>.Ok(summary));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
/// <summary>
|
||||
/// Clinical user account management for hospital IT administrators.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/v1/users")]
|
||||
[Produces("application/json")]
|
||||
[Authorize]
|
||||
public class UsersController : ControllerBase
|
||||
{
|
||||
private readonly IUserService _users;
|
||||
|
||||
public UsersController(IUserService users) => _users = users;
|
||||
|
||||
/// <summary>Lists all clinical user accounts.</summary>
|
||||
[HttpGet]
|
||||
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
|
||||
[ProducesResponseType(typeof(ApiResponse<List<ClinicalUserResponse>>), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> List()
|
||||
{
|
||||
var users = await _users.ListAsync();
|
||||
return Ok(ApiResponse<List<ClinicalUserResponse>>.Ok(users));
|
||||
}
|
||||
|
||||
/// <summary>Creates a new clinical user account.</summary>
|
||||
[HttpPost]
|
||||
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
|
||||
[ProducesResponseType(typeof(ApiResponse<ClinicalUserResponse>), StatusCodes.Status201Created)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
|
||||
public async Task<IActionResult> Create([FromBody] CreateUserRequest req)
|
||||
{
|
||||
var user = await _users.CreateAsync(req);
|
||||
return StatusCode(201, ApiResponse<ClinicalUserResponse>.Created(user));
|
||||
}
|
||||
|
||||
/// <summary>Updates role, display name, or active status for a user.</summary>
|
||||
[HttpPatch("{id:guid}")]
|
||||
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
|
||||
[ProducesResponseType(typeof(ApiResponse<ClinicalUserResponse>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateUserRequest req)
|
||||
{
|
||||
var user = await _users.UpdateAsync(id, req);
|
||||
return Ok(ApiResponse<ClinicalUserResponse>.Ok(user));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user