Clinical Sync Batch Engine: first commit

This commit is contained in:
voltsrage
2026-06-23 03:02:30 +08:00
parent 90b8baa2a1
commit c9994b1ba2
60 changed files with 3547 additions and 31 deletions
@@ -0,0 +1,48 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using VigilCare.ClinicalContracts.Sync;
[ApiController]
[Produces("application/json")]
public class ClinicalSyncController : ControllerBase
{
private readonly IClinicalSyncService _sync;
public ClinicalSyncController(IClinicalSyncService sync) => _sync = sync;
/// <summary>Upload a buffered sync batch from a ward gateway.</summary>
[HttpPost("api/v1/sync/batches")]
[Authorize(AuthenticationSchemes = GatewayApiKeyAuthenticationHandler.SchemeName)]
[ProducesResponseType(typeof(ApiResponse<ClinicalBatchUploadResponse>), StatusCodes.Status201Created)]
public async Task<IActionResult> UploadBatch(
[FromBody] ClinicalSyncBatchRequest request, CancellationToken ct)
{
var result = await _sync.UploadBatchAsync(request, ct);
return StatusCode(201, ApiResponse<ClinicalBatchUploadResponse>.Created(result));
}
/// <summary>Poll batch processing status and conflicts.</summary>
[HttpGet("api/v1/sync/batches/{batchId:guid}")]
[Authorize(AuthenticationSchemes =
$"{JwtBearerDefaults.AuthenticationScheme},{GatewayApiKeyAuthenticationHandler.SchemeName}")]
[ProducesResponseType(typeof(ApiResponse<ClinicalBatchStatusResponse>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetBatchStatus(Guid batchId, CancellationToken ct)
{
var result = await _sync.GetBatchStatusAsync(batchId, ct);
return Ok(ApiResponse<ClinicalBatchStatusResponse>.Ok(result));
}
/// <summary>Last 50 sync batches for a gateway (admin JWT).</summary>
[HttpGet("api/v1/sites/{siteId:guid}/gateways/{gatewayId:guid}/sync-history")]
[Authorize]
[AuthorizePermission(ClinicalPermissions.UsersAdmin)]
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<ClinicalSyncHistoryItem>>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetSyncHistory(
Guid siteId, Guid gatewayId, CancellationToken ct)
{
var history = await _sync.GetSyncHistoryAsync(siteId, gatewayId, 50, ct);
return Ok(ApiResponse<IReadOnlyList<ClinicalSyncHistoryItem>>.Ok(history));
}
}