diff --git a/.Net Capstone Project/ConditionsController.cs b/.Net Capstone Project/ConditionsController.cs new file mode 100644 index 0000000..148f7e1 --- /dev/null +++ b/.Net Capstone Project/ConditionsController.cs @@ -0,0 +1,330 @@ +using ClinicalInsightsPro.API.Data; +using ClinicalInsightsPro.API.DTOs; +using ClinicalInsightsPro.API.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using ClinicalInsightsPro.API.Services.Interfaces; + +namespace ClinicalInsightsPro.API.Controllers; + +[ApiController] +[Route("api/patients/{patientId}/[controller]")] +[Authorize] +public class ConditionsController : ControllerBase +{ + private readonly ApplicationDbContext _db; +private readonly IMedplumFhirService _medplumFhirService; + + public ConditionsController( + ApplicationDbContext db, + IMedplumFhirService medplumFhirService) +{ + _db = db; + _medplumFhirService = medplumFhirService; +} + + private async Task PatientExists(string patientId) + { + return await _db.Patient.AnyAsync(x => x.Id == patientId); + } + + [HttpGet("/api/conditions")] + public async Task GetAll() + { + var conditions = await _db.Condition + .Include(x => x.Patient) + .Select(condition => new ConditionListDto + { + Id = condition.Id, + + PatientId = condition.PatientId, + + PatientName = + condition.Patient != null + ? $"{condition.Patient.GivenName} {condition.Patient.FamilyName}" + : string.Empty, + + ConditionCode = condition.ConditionCode, + + ConditionDisplay = condition.ConditionDisplay, + + ClinicalStatusDisplay = + condition.ClinicalStatusDisplay, + + VerificationStatusDisplay = + condition.VerificationStatusDisplay, + + SeverityDisplay = + condition.SeverityDisplay, + + RecordedDate = + condition.RecordedDate + }) + .ToListAsync(); + +return Ok(conditions); + + } + + [HttpGet] + public async Task GetByPatient(string patientId) + { + if (!await PatientExists(patientId)) + return NotFound(new + { + error = $"Patient '{patientId}' was not found." + }); + + var conditions = await _db.Condition + .Where(x => x.PatientId == patientId) + .AsNoTracking() + .ToListAsync(); + + return Ok(conditions); + } + + [HttpGet("{id}")] + public async Task Get( + string patientId, + string id) + { + var condition = await _db.Condition + .AsNoTracking() + .FirstOrDefaultAsync(x => + x.Id == id && + x.PatientId == patientId); + + if (condition == null) + return NotFound(new + { + error = $"Condition '{id}' was not found." + }); + + return Ok(condition); + } + + [HttpPost] + public async Task Create( + string patientId, + [FromBody] ConditionRequestDto request) + { + if (!await PatientExists(patientId)) + return NotFound(new + { + error = $"Patient '{patientId}' was not found." + }); + + var condition = new Condition + { + ConditionId = Guid.NewGuid().ToString(), + + ResourceType = "Condition", + + PatientId = patientId, + + ClinicalStatusCode = + request.ClinicalStatusCode, + + ClinicalStatusDisplay = + request.ClinicalStatusDisplay, + + VerificationStatusCode = + request.VerificationStatusCode, + + VerificationStatusDisplay = + request.VerificationStatusDisplay, + + SeverityCode = + request.SeverityCode, + + SeverityDisplay = + request.SeverityDisplay, + + ConditionCode = + request.ConditionCode, + + ConditionDisplay = + request.ConditionDisplay, + + OnsetDateTime = + request.OnsetDateTime, + + AbatementDateTime = + request.AbatementDateTime, + + RecordedDate = + request.RecordedDate, + + RecorderId = + request.RecorderId, + + AsserterId = + request.AsserterId, + + CreatedBy = "System", + CreatedDate = DateTime.UtcNow, + + VersionId = Guid.NewGuid().ToString(), + LastUpdated = DateTime.UtcNow + }; + + _db.Condition.Add(condition); + + await _db.SaveChangesAsync(); + + return CreatedAtAction( + nameof(Get), + new + { + patientId, + id = condition.Id + }, + condition); + } + + [HttpPut("{id}")] + public async Task Update( + string patientId, + string id, + [FromBody] ConditionRequestDto request) + { + var condition = await _db.Condition + .FirstOrDefaultAsync(x => + x.Id == id && + x.PatientId == patientId); + + if (condition == null) + return NotFound(new + { + error = $"Condition '{id}' was not found." + }); + + condition.ClinicalStatusCode = + request.ClinicalStatusCode; + + condition.ClinicalStatusDisplay = + request.ClinicalStatusDisplay; + + condition.VerificationStatusCode = + request.VerificationStatusCode; + + condition.VerificationStatusDisplay = + request.VerificationStatusDisplay; + + condition.SeverityCode = + request.SeverityCode; + + condition.SeverityDisplay = + request.SeverityDisplay; + + condition.ConditionCode = + request.ConditionCode; + + condition.ConditionDisplay = + request.ConditionDisplay; + + condition.OnsetDateTime = + request.OnsetDateTime; + + condition.AbatementDateTime = + request.AbatementDateTime; + + condition.RecordedDate = + request.RecordedDate; + + condition.RecorderId = + request.RecorderId; + + condition.AsserterId = + request.AsserterId; + + condition.UpdatedBy = "System"; + condition.UpdatedDate = DateTime.UtcNow; + condition.LastUpdated = DateTime.UtcNow; + + await _db.SaveChangesAsync(); + + return Ok(condition); + } + + [HttpDelete("{id}")] + public async Task Delete( + string patientId, + string id) + { + var condition = await _db.Condition + .FirstOrDefaultAsync(x => + x.Id == id && + x.PatientId == patientId); + + if (condition == null) + return NotFound(new + { + error = $"Condition '{id}' was not found." + }); + + _db.Condition.Remove(condition); + + await _db.SaveChangesAsync(); + + return NoContent(); + } + + [HttpPost("/api/conditions/sync-from-medplum")] +public async Task SyncFromMedplum() +{ + var conditions = + await _medplumFhirService.PullAllConditionsFromMedplumAsync(); + + int imported = 0; + + foreach (var condition in conditions) + { + // Medplum Patient Id -> Local Patient Id mapping. Falls back to + // matching the local Patient's own Id too — a patient that was + // seeded locally (or pulled from Medplum without MedplumId being + // set for some reason) but whose id happens to equal the Medplum + // patient id would otherwise be silently skipped here. + var localPatient = await _db.Patient + .FirstOrDefaultAsync(p => + p.MedplumId == condition.PatientId || + p.Id == condition.PatientId); + + if (localPatient == null) + { + continue; + } + + // Local Patient Id save karo + condition.PatientId = localPatient.Id; + + var exists = await _db.Condition + .AnyAsync(x => x.MedplumId == condition.MedplumId); + + if (!exists) + { + condition.Id = Guid.NewGuid().ToString(); + + if (string.IsNullOrWhiteSpace(condition.ConditionId)) + { + condition.ConditionId = Guid.NewGuid().ToString(); + } + + condition.CreatedDate = DateTime.UtcNow; + condition.LastUpdated = DateTime.UtcNow; + condition.VersionId = Guid.NewGuid().ToString(); + + _db.Condition.Add(condition); + imported++; + } + } + + await _db.SaveChangesAsync(); + + return Ok(new + { + Imported = imported + }); +} +} \ No newline at end of file