- Timestamp:
- 09/04/26 19:36:17 (11 days ago)
- Branches:
- master
- Children:
- 99ab276
- Parents:
- 9af201e
- Location:
- backend/src
- Files:
-
- 6 added
- 4 deleted
- 55 edited
- 12 moved
-
main/java/medora/Medora5Application.java (deleted)
-
main/java/medora/MedoraApplication.java (added)
-
main/java/medora/config/AuthorizationInterceptor.java (modified) (2 diffs)
-
main/java/medora/config/SecurityConfig.java (modified) (1 diff)
-
main/java/medora/config/WebConfig.java (modified) (1 diff)
-
main/java/medora/controller/AuthController.java (modified) (4 diffs)
-
main/java/medora/controller/BillingController.java (modified) (2 diffs)
-
main/java/medora/controller/DepartmentController.java (modified) (1 diff)
-
main/java/medora/controller/DiagnosisController.java (modified) (1 diff)
-
main/java/medora/controller/DiagnosticController.java (added)
-
main/java/medora/controller/DoctorController.java (modified) (1 diff)
-
main/java/medora/controller/LabController.java (modified) (1 diff)
-
main/java/medora/controller/MedicalRecordController.java (modified) (1 diff)
-
main/java/medora/controller/MedicalReportController.java (modified) (1 diff)
-
main/java/medora/controller/PatientController.java (modified) (1 diff)
-
main/java/medora/controller/PrescriptionController.java (modified) (1 diff)
-
main/java/medora/controller/ProcedureController.java (modified) (1 diff)
-
main/java/medora/dto/BillingDetailDTO.java (modified) (1 diff)
-
main/java/medora/dto/CreateDoctorRequest.java (modified) (1 diff)
-
main/java/medora/dto/LabResultDTO.java (modified) (1 diff)
-
main/java/medora/dto/MedicalRecordDTO.java (modified) (1 diff)
-
main/java/medora/dto/PrescriptionDTO.java (modified) (1 diff)
-
main/java/medora/dto/ProcedureRequestDTO.java (modified) (1 diff)
-
main/java/medora/dto/ProcedureResultDTO.java (modified) (1 diff)
-
main/java/medora/dto/RequestLabTestRequest.java (modified) (1 diff)
-
main/java/medora/dto/SubmitLabResultRequest.java (modified) (1 diff)
-
main/java/medora/models/domain/Admin.java (modified) (2 diffs)
-
main/java/medora/models/domain/Billing.java (modified) (2 diffs)
-
main/java/medora/models/domain/Departments.java (modified) (1 diff)
-
main/java/medora/models/domain/DoctorLevel.java (modified) (1 diff)
-
main/java/medora/models/domain/DoctorSpecialization.java (modified) (1 diff)
-
main/java/medora/models/domain/LabTechnician.java (modified) (2 diffs)
-
main/java/medora/models/domain/MedicalRecordSymptoms.java (modified) (1 diff)
-
main/java/medora/models/domain/MedicalReport.java (modified) (1 diff)
-
main/java/medora/models/domain/Patient.java (modified) (2 diffs)
-
main/java/medora/models/domain/PerformedLabTests.java (modified) (1 diff)
-
main/java/medora/models/domain/ProcedureResults.java (modified) (1 diff)
-
main/java/medora/models/domain/Referrals.java (modified) (1 diff)
-
main/java/medora/models/domain/Symptoms.java (modified) (1 diff)
-
main/java/medora/models/domain/User.java (modified) (1 diff)
-
main/java/medora/repository/BillingRepository.java (modified) (2 diffs)
-
main/java/medora/repository/ProcedureResultRepository.java (modified) (1 diff)
-
main/java/medora/service/AppointmentService.java (modified) (7 diffs)
-
main/java/medora/service/AuthService.java (modified) (5 diffs)
-
main/java/medora/service/BillingService.java (modified) (3 diffs)
-
main/java/medora/service/DepartmentService.java (modified) (6 diffs)
-
main/java/medora/service/DiagnosisService.java (modified) (5 diffs)
-
main/java/medora/service/DoctorService.java (modified) (8 diffs)
-
main/java/medora/service/LabService.java (modified) (1 diff)
-
main/java/medora/service/MedicalObservationsService.java (modified) (6 diffs)
-
main/java/medora/service/MedicalRecordService.java (modified) (12 diffs)
-
main/java/medora/service/MedicalReportService.java (modified) (2 diffs)
-
main/java/medora/service/PatientService.java (modified) (1 diff)
-
main/java/medora/service/PrescriptionService.java (modified) (1 diff)
-
main/java/medora/service/ProcedureService.java (modified) (1 diff)
-
main/java/medora/service/ReferralService.java (modified) (5 diffs)
-
main/java/medora/util/JwtUtil.java (modified) (2 diffs)
-
main/resources/application.properties (modified) (1 diff)
-
main/resources/db.migration/V3__Insert_Doctor_Users.sql (deleted)
-
main/resources/db.migration/V4__Insert_Lab_Technician_Users.sql (deleted)
-
main/resources/db.migration/V5__Insert_Billing_Admin_Users.sql (deleted)
-
main/resources/db/migration/R__allergy_prescription_safety_enforcement.sql (moved) (moved from backend/src/main/resources/db.migration/R__allergy_prescription_safety_enforcement.sql )
-
main/resources/db/migration/R__billing_integrity.sql (moved) (moved from backend/src/main/resources/db.migration/R__billing_integrity.sql )
-
main/resources/db/migration/R__create_scoped_app_role.sql (added)
-
main/resources/db/migration/R__custom_domains.sql (moved) (moved from backend/src/main/resources/db.migration/R__custom_domains.sql )
-
main/resources/db/migration/R__medical_record_integrity.sql (moved) (moved from backend/src/main/resources/db.migration/R__medical_record_integrity.sql )
-
main/resources/db/migration/V1.1__Create_Daily_Billing_View.sql (moved) (moved from backend/src/main/resources/db.migration/V1.1__Create_Daily_Billing_View.sql ) (1 diff)
-
main/resources/db/migration/V1.2__Create_Users_Table.sql (moved) (moved from backend/src/main/resources/db.migration/V1.2__Create_Users_Table.sql ) (2 diffs)
-
main/resources/db/migration/V2__Add_appointment_fields_to_referrals.sql (moved) (moved from backend/src/main/resources/db.migration/V2__Add_appointment_fields_to_referrals.sql )
-
main/resources/db/migration/V3__Fix_LabTechnician_Admin_Structure.sql (added)
-
main/resources/db/migration/V6__Insert_Billing_Admin_Users.sql (moved) (moved from backend/src/main/resources/db.migration/V6__Insert_Billing_Admin_Users.sql )
-
main/resources/db/migration/V7__Update_Billing_Admin_Names.sql (moved) (moved from backend/src/main/resources/db.migration/V7__Update_Billing_Admin_Names.sql )
-
main/resources/db/migration/V8__appointment_scheduling_integrity.sql (moved) (moved from backend/src/main/resources/db.migration/V8__appointment_scheduling_integrity.sql )
-
main/resources/db/migration/V9__mv_revenue_reporting.sql (moved) (moved from backend/src/main/resources/db.migration/V9__mv_revenue_reporting.sql )
-
main/resources/db/phase7/verify_section2_deployment.sql (added)
-
main/resources/import.sql (added)
-
test/java/medora/Medora4ApplicationTests.java (moved) (moved from backend/src/test/java/medora/Medora5ApplicationTests.java ) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
backend/src/main/java/medora/config/AuthorizationInterceptor.java
r9af201e rcdcff72 1 1 package medora.config; 2 3 import medora.util.SecurityUtil; 4 import org.springframework.stereotype.Component; 5 import org.springframework.web.servlet.HandlerInterceptor; 2 6 3 7 import jakarta.servlet.http.HttpServletRequest; 4 8 import jakarta.servlet.http.HttpServletResponse; 5 import medora.util.SecurityUtil;6 import org.springframework.stereotype.Component;7 import org.springframework.web.servlet.HandlerInterceptor;8 9 9 10 /** … … 18 19 */ 19 20 @Component 20 21 22 23 24 21 public class AuthorizationInterceptor implements HandlerInterceptor { 25 22 -
backend/src/main/java/medora/config/SecurityConfig.java
r9af201e rcdcff72 14 14 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { 15 15 http 16 .csrf(csrf -> csrf.disable())17 .authorizeHttpRequests(auth -> auth18 .anyRequest().permitAll()19 );16 .csrf(csrf -> csrf.disable()) 17 .authorizeHttpRequests(auth -> auth 18 .anyRequest().permitAll() 19 ); 20 20 21 21 return http.build(); -
backend/src/main/java/medora/config/WebConfig.java
r9af201e rcdcff72 32 32 Path uploadPath = Path.of("uploads").toAbsolutePath().normalize(); 33 33 registry 34 .addResourceHandler("/uploads/**")35 .addResourceLocations(uploadPath.toUri().toString() + "/");34 .addResourceHandler("/uploads/**") 35 .addResourceLocations(uploadPath.toUri().toString() + "/"); 36 36 } 37 37 -
backend/src/main/java/medora/controller/AuthController.java
r9af201e rcdcff72 3 3 import medora.dto.LoginRequest; 4 4 import medora.service.AuthService; 5 import medora.util.SecurityUtil; 5 6 import org.slf4j.Logger; 6 7 import org.slf4j.LoggerFactory; … … 8 9 import org.springframework.http.ResponseEntity; 9 10 import org.springframework.web.bind.annotation.*; 11 import jakarta.servlet.http.HttpServletRequest; 10 12 11 13 import java.util.Map; 14 import java.util.HashMap; 12 15 13 16 @RestController … … 19 22 20 23 private final AuthService authService; 24 private final SecurityUtil securityUtil; 21 25 22 public AuthController(AuthService authService ) {26 public AuthController(AuthService authService, SecurityUtil securityUtil) { 23 27 this.authService = authService; 28 this.securityUtil = securityUtil; 24 29 } 25 30 … … 69 74 return ResponseEntity.ok(Map.of("status", "healthy")); 70 75 } 76 77 /** 78 * Debug endpoint to test token validation 79 */ 80 @GetMapping("/debug/token") 81 public ResponseEntity<?> debugToken(HttpServletRequest httpRequest) { 82 String role = securityUtil.getRoleFromRequest(httpRequest); 83 String username = securityUtil.getUsernameFromRequest(httpRequest); 84 Long userId = securityUtil.getUserIdFromRequest(httpRequest); 85 86 Map<String, Object> debug = new HashMap<>(); 87 debug.put("role", role); 88 debug.put("username", username); 89 debug.put("userId", userId); 90 debug.put("isValid", role != null); 91 92 if (role == null) { 93 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(debug); 94 } 95 return ResponseEntity.ok(debug); 96 } 97 98 /** 99 * Test endpoint - no auth required, returns test token 100 */ 101 @GetMapping("/test/generate-token") 102 public ResponseEntity<?> generateTestToken() { 103 String testToken = authService.generateTestToken(); 104 Map<String, Object> response = new HashMap<>(); 105 response.put("token", testToken); 106 response.put("message", "Copy this token and try it"); 107 return ResponseEntity.ok(response); 108 } 71 109 } -
backend/src/main/java/medora/controller/BillingController.java
r9af201e rcdcff72 244 244 @PatchMapping("/{billId}/payment-status") 245 245 public ResponseEntity<?> updatePaymentStatus(@PathVariable Long billId, 246 @RequestBody UpdateBillingRequest request,247 HttpServletRequest httpRequest) {246 @RequestBody UpdateBillingRequest request, 247 HttpServletRequest httpRequest) { 248 248 try { 249 249 String role = securityUtil.getRoleFromRequest(httpRequest); … … 344 344 if (billing.getMedicalRecord() != null && billing.getMedicalRecord().getPatient() != null) { 345 345 patientName = billing.getMedicalRecord().getPatient().getFirstName() + " " + 346 billing.getMedicalRecord().getPatient().getLastName();346 billing.getMedicalRecord().getPatient().getLastName(); 347 347 } 348 348 return new BillingDTO( -
backend/src/main/java/medora/controller/DepartmentController.java
r9af201e rcdcff72 162 162 @PutMapping("/{departmentId}") 163 163 public ResponseEntity<?> updateDepartment(@PathVariable Long departmentId, 164 @RequestBody Map<String, String> request,165 HttpServletRequest httpRequest) {164 @RequestBody Map<String, String> request, 165 HttpServletRequest httpRequest) { 166 166 try { 167 167 String role = securityUtil.getRoleFromRequest(httpRequest); -
backend/src/main/java/medora/controller/DiagnosisController.java
r9af201e rcdcff72 1 1 package medora.controller; 2 2 3 import medora.dto.DiagnosisDTO; 3 4 import medora.dto.CreateDiagnosisRequest; 4 import medora.dto.DiagnosisDTO;5 5 import medora.models.domain.Diagnosis; 6 6 import medora.service.DiagnosisService; -
backend/src/main/java/medora/controller/DoctorController.java
r9af201e rcdcff72 212 212 @PutMapping("/{doctorId}") 213 213 public ResponseEntity<?> updateDoctor(@PathVariable Long doctorId, 214 @RequestBody CreateDoctorRequest request,215 HttpServletRequest httpRequest) {214 @RequestBody CreateDoctorRequest request, 215 HttpServletRequest httpRequest) { 216 216 try { 217 217 String role = securityUtil.getRoleFromRequest(httpRequest); -
backend/src/main/java/medora/controller/LabController.java
r9af201e rcdcff72 125 125 @PutMapping("/{testId}") 126 126 public ResponseEntity<?> updateLabTest(@PathVariable Long testId, 127 @RequestBody CreateLabTestRequest request) {127 @RequestBody CreateLabTestRequest request) { 128 128 try { 129 129 logger.info("Updating lab test with ID: {}", testId); -
backend/src/main/java/medora/controller/MedicalRecordController.java
r9af201e rcdcff72 1 1 package medora.controller; 2 2 3 import medora.dto.AllergyDTO;4 3 import medora.dto.ComprehensiveMedicalRecordDTO; 5 4 import medora.dto.MedicalRecordDTO; 5 import medora.dto.AllergyDTO; 6 6 import medora.dto.SymptomDTO; 7 7 import medora.models.domain.*; -
backend/src/main/java/medora/controller/MedicalReportController.java
r9af201e rcdcff72 13 13 import java.util.List; 14 14 import java.util.Map; 15 import java.util.stream.Collectors; 15 16 16 17 @RestController -
backend/src/main/java/medora/controller/PatientController.java
r9af201e rcdcff72 207 207 @PutMapping("/{patientId}") 208 208 public ResponseEntity<?> updatePatient(@PathVariable Long patientId, 209 @RequestBody CreatePatientRequest request,210 HttpServletRequest httpRequest) {209 @RequestBody CreatePatientRequest request, 210 HttpServletRequest httpRequest) { 211 211 try { 212 212 String role = securityUtil.getRoleFromRequest(httpRequest); -
backend/src/main/java/medora/controller/PrescriptionController.java
r9af201e rcdcff72 1 1 package medora.controller; 2 2 3 import medora.dto.PrescriptionDTO; 3 4 import medora.dto.CreatePrescriptionRequest; 4 import medora.dto.PrescriptionDTO;5 5 import medora.models.domain.PrescriptionMedicalRecord; 6 6 import medora.service.PrescriptionService; -
backend/src/main/java/medora/controller/ProcedureController.java
r9af201e rcdcff72 334 334 private Map<String, Object> convertResultToDTO(ProcedureResults result) { 335 335 return Map.of( 336 "resultId", result.getResultId(),337 "procedureId", result.getProcedure().getProcedureId(),338 "procedureType", result.getProcedure().getProcedureType(),339 "resultDescription", result.getResultDescription() != null ? result.getResultDescription() : "",340 "resultDate", result.getResultDate()336 "resultId", result.getResultId(), 337 "procedureId", result.getProcedure().getProcedureId(), 338 "procedureType", result.getProcedure().getProcedureType(), 339 "resultDescription", result.getResultDescription() != null ? result.getResultDescription() : "", 340 "resultDate", result.getResultDate() 341 341 ); 342 342 } 343 343 } 344 -
backend/src/main/java/medora/dto/BillingDetailDTO.java
r9af201e rcdcff72 21 21 22 22 public BillingDetailDTO(Long billId, Long patientId, String patientName, String patientEmbg, String patientPhone, 23 BigDecimal totalCost, String paymentStatus, LocalDate paymentDate,24 LocalDate billDate, List<BillingItemDTO> procedures, List<BillingItemDTO> labTests) {23 BigDecimal totalCost, String paymentStatus, LocalDate paymentDate, 24 LocalDate billDate, List<BillingItemDTO> procedures, List<BillingItemDTO> labTests) { 25 25 this.billId = billId; 26 26 this.patientId = patientId; -
backend/src/main/java/medora/dto/CreateDoctorRequest.java
r9af201e rcdcff72 10 10 @NoArgsConstructor 11 11 @AllArgsConstructor 12 public class CreateDoctorRequest { 12 public class 13 CreateDoctorRequest { 13 14 private String firstName; 14 15 private String lastName; -
backend/src/main/java/medora/dto/LabResultDTO.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 7 import java.time.LocalDate; 9 8 -
backend/src/main/java/medora/dto/MedicalRecordDTO.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 import java.time.LocalDate; 7 9 8 10 @Getter -
backend/src/main/java/medora/dto/PrescriptionDTO.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 import java.time.LocalDate; 7 9 8 10 @Getter -
backend/src/main/java/medora/dto/ProcedureRequestDTO.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 7 import java.time.LocalDate; 9 8 -
backend/src/main/java/medora/dto/ProcedureResultDTO.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 7 import java.time.LocalDate; 9 8 -
backend/src/main/java/medora/dto/RequestLabTestRequest.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 7 import java.time.LocalDate; 9 8 -
backend/src/main/java/medora/dto/SubmitLabResultRequest.java
r9af201e rcdcff72 5 5 import lombok.NoArgsConstructor; 6 6 import lombok.Setter; 7 8 7 import java.time.LocalDate; 9 8 -
backend/src/main/java/medora/models/domain/Admin.java
r9af201e rcdcff72 1 1 package medora.models.domain; 2 2 3 4 import jakarta.persistence.Column; 5 import jakarta.persistence.Entity; 6 import jakarta.persistence.Id; 7 import jakarta.persistence.Table; 8 import jakarta.validation.constraints.Pattern; 3 import jakarta.persistence.*; 9 4 import lombok.Getter; 10 5 import lombok.Setter; … … 20 15 private Long adminId; 21 16 22 @Column(name = "username", nullable = false, unique = true) 23 private String username; 17 @OneToOne(optional = false) 18 @JoinColumn(name = "user_id", nullable = false, unique = true) 19 private User user; 24 20 25 @Column(name = "name", nullable = false) 26 private String name; 27 28 @Column(name = "lastname", nullable = false) 29 private String lastname; 30 31 @Pattern(regexp = ".*@adminmedora.*") 32 @Column(name = "email", nullable = false, unique = true) 33 private String email; 21 @Column(name = "permissions") 22 private String permissions; 34 23 35 24 public Admin() {} 36 25 37 public Admin(Long adminId, String username, String name, String lastname, String email) {26 public Admin(Long adminId, User user, String permissions) { 38 27 this.adminId = adminId; 39 this.username = username; 40 this.name = name; 41 this.lastname = lastname; 42 this.email = email; 28 this.user = user; 29 this.permissions = permissions; 30 } 31 32 public Admin(Long adminId, User user) { 33 this.adminId = adminId; 34 this.user = user; 43 35 } 44 36 } -
backend/src/main/java/medora/models/domain/Billing.java
r9af201e rcdcff72 4 4 import jakarta.persistence.*; 5 5 import jakarta.validation.constraints.DecimalMin; 6 import jakarta.validation.constraints.NotBlank; 6 7 import lombok.Getter; 7 8 import lombok.Setter; … … 38 39 private MedicalRecord medicalRecord; 39 40 40 @ManyToOne(optional = false)41 @JoinColumn(name = "admin_id", nullable = false)41 @ManyToOne(optional = true) 42 @JoinColumn(name = "admin_id", nullable = true) 42 43 private Admin admin; 43 44 -
backend/src/main/java/medora/models/domain/Departments.java
r9af201e rcdcff72 1 1 package medora.models.domain; 2 3 import jakarta.persistence.Column; 4 import jakarta.persistence.Entity; 5 import jakarta.persistence.Id; 6 import jakarta.persistence.Table; 2 import jakarta.persistence.*; 7 3 import lombok.Getter; 8 4 import lombok.Setter; -
backend/src/main/java/medora/models/domain/DoctorLevel.java
r9af201e rcdcff72 1 1 package medora.models.domain; 2 3 import jakarta.persistence.Column; 4 import jakarta.persistence.Entity; 5 import jakarta.persistence.Id; 6 import jakarta.persistence.Table; 2 import jakarta.persistence.*; 7 3 import lombok.Getter; 8 4 import lombok.Setter; -
backend/src/main/java/medora/models/domain/DoctorSpecialization.java
r9af201e rcdcff72 1 1 package medora.models.domain; 2 3 import jakarta.persistence.Column; 4 import jakarta.persistence.Entity; 5 import jakarta.persistence.Id; 6 import jakarta.persistence.Table; 2 import jakarta.persistence.*; 7 3 import lombok.Getter; 8 4 import lombok.Setter; -
backend/src/main/java/medora/models/domain/LabTechnician.java
r9af201e rcdcff72 1 1 package medora.models.domain; 2 2 3 4 import jakarta.persistence.Column; 5 import jakarta.persistence.Entity; 6 import jakarta.persistence.Id; 7 import jakarta.persistence.Table; 8 import jakarta.validation.constraints.Pattern; 3 import jakarta.persistence.*; 9 4 import lombok.Getter; 10 5 import lombok.Setter; … … 20 15 private Long technicianId; 21 16 22 @Column(name = "username", nullable = false, unique = true) 23 private String username; 17 @OneToOne(optional = false) 18 @JoinColumn(name = "user_id", nullable = false, unique = true) 19 private User user; 24 20 25 @Column(name = "name", nullable = false) 26 private String name; 27 28 @Column(name = "lastname", nullable = false) 29 private String lastname; 30 31 @Pattern(regexp = ".*@labmedora.*") 32 @Column(name = "email", nullable = false, unique = true) 33 private String email; 21 @Column(name = "certification") 22 private String certification; 34 23 35 24 public LabTechnician() {} 36 25 37 public LabTechnician(Long technicianId, String username, String name, String lastname, String email) {26 public LabTechnician(Long technicianId, User user, String certification) { 38 27 this.technicianId = technicianId; 39 this.username = username; 40 this.name = name; 41 this.lastname = lastname; 42 this.email = email; 28 this.user = user; 29 this.certification = certification; 30 } 31 32 public LabTechnician(Long technicianId, User user) { 33 this.technicianId = technicianId; 34 this.user = user; 43 35 } 44 36 } -
backend/src/main/java/medora/models/domain/MedicalRecordSymptoms.java
r9af201e rcdcff72 20 20 @Id 21 21 @ManyToOne(optional = false, fetch = FetchType.LAZY) 22 @JoinColumn(name = "symptom_id") 22 23 private Symptoms symptom; 23 24 -
backend/src/main/java/medora/models/domain/MedicalReport.java
r9af201e rcdcff72 7 7 8 8 import java.time.LocalDate; 9 import java.util.List; 10 import java.util.ArrayList; 9 11 10 12 @Getter -
backend/src/main/java/medora/models/domain/Patient.java
r9af201e rcdcff72 2 2 3 3 4 import com.fasterxml.jackson.annotation.JsonIgnore;5 4 import jakarta.persistence.*; 6 5 import lombok.Getter; … … 8 7 import medora.models.enums.BloodType; 9 8 import medora.models.enums.Gender; 9 import com.fasterxml.jackson.annotation.JsonIgnore; 10 10 11 11 import java.time.LocalDate; -
backend/src/main/java/medora/models/domain/PerformedLabTests.java
r9af201e rcdcff72 48 48 49 49 public PerformedLabTests(Long performedTestId, 50 LabTests labTest,51 Patient patient,52 Doctors doctor,53 LabTechnician technician,54 LocalDate testDate,55 String notes) {50 LabTests labTest, 51 Patient patient, 52 Doctors doctor, 53 LabTechnician technician, 54 LocalDate testDate, 55 String notes) { 56 56 this.performedTestId = performedTestId; 57 57 this.labTest = labTest; -
backend/src/main/java/medora/models/domain/ProcedureResults.java
r9af201e rcdcff72 3 3 4 4 import jakarta.persistence.*; 5 import jakarta.validation.constraints.NotBlank; 5 6 import lombok.Getter; 6 7 import lombok.Setter; -
backend/src/main/java/medora/models/domain/Referrals.java
r9af201e rcdcff72 50 50 51 51 public Referrals(Long referralId, 52 String reason,53 LocalDate referralDate,54 LocalDate appointmentDate,55 LocalTime appointmentTime,56 MedicalRecord medicalRecord,57 Doctors fromDoctor,58 Doctors toDoctor) {52 String reason, 53 LocalDate referralDate, 54 LocalDate appointmentDate, 55 LocalTime appointmentTime, 56 MedicalRecord medicalRecord, 57 Doctors fromDoctor, 58 Doctors toDoctor) { 59 59 60 60 this.referralId = referralId; -
backend/src/main/java/medora/models/domain/Symptoms.java
r9af201e rcdcff72 2 2 3 3 4 import jakarta.persistence.Column; 5 import jakarta.persistence.Entity; 6 import jakarta.persistence.Id; 7 import jakarta.persistence.Table; 4 import jakarta.persistence.*; 8 5 import jakarta.validation.constraints.NotBlank; 9 6 import lombok.Getter; -
backend/src/main/java/medora/models/domain/User.java
r9af201e rcdcff72 34 34 private Boolean isActive = true; 35 35 36 // Foreign key to patient for PATIENT role37 @OneToOne(fetch = jakarta.persistence.FetchType.LAZY)36 // Foreign key to patient (only for PATIENT role) 37 @OneToOne(fetch = FetchType.LAZY) 38 38 @JoinColumn(name = "patient_id") 39 39 private Patient patient; 40 40 41 // Foreign key to doctor for DOCTOR role42 @OneToOne(fetch = jakarta.persistence.FetchType.LAZY)41 // Foreign key to doctor (only for DOCTOR role) 42 @OneToOne(fetch = FetchType.LAZY) 43 43 @JoinColumn(name = "doctor_id") 44 44 private Doctors doctor; -
backend/src/main/java/medora/repository/BillingRepository.java
r9af201e rcdcff72 116 116 WHERE bp.bill_id = :billId 117 117 """, nativeQuery = true) 118 java.util.List<Object[]> findProceduresForBilling(@Param("billId") Long billId);118 List<Object[]> findProceduresForBilling(@Param("billId") Long billId); 119 119 120 120 // UC020 – Get lab tests for a billing record … … 125 125 WHERE blt.bill_id = :billId 126 126 """, nativeQuery = true) 127 java.util.List<Object[]> findLabTestsForBilling(@Param("billId") Long billId);127 List<Object[]> findLabTestsForBilling(@Param("billId") Long billId); 128 128 129 129 // Cleanup: Delete test records -
backend/src/main/java/medora/repository/ProcedureResultRepository.java
r9af201e rcdcff72 30 30 """) 31 31 List<ProcedureResults> findLatestResultsByProcedure(@Param("procedureId") Long procedureId); 32 33 @Query(""" 34 SELECT pr FROM ProcedureResults pr 35 WHERE pr IN ( 36 SELECT mrpr.procedureResult FROM MedicalRecordProcedureResults mrpr 37 WHERE mrpr.medicalRecord.recordId = :recordId 38 ) 39 AND pr.procedure.procedureId = :procedureId 40 """) 41 List<ProcedureResults> findByMedicalRecordAndProcedure(@Param("recordId") Long recordId, @Param("procedureId") Long procedureId); 32 42 } -
backend/src/main/java/medora/service/AppointmentService.java
r9af201e rcdcff72 181 181 } 182 182 183 183 /** 184 * Mark appointment as completed 185 */ 184 186 @Transactional 185 187 public Appointment completeAppointment(Long appointmentId) { … … 208 210 } 209 211 212 /** 213 * Get appointment by ID 214 */ 210 215 @Transactional(readOnly = true) 211 216 public Optional<Appointment> getAppointmentById(Long appointmentId) { … … 220 225 } 221 226 222 227 /** 228 * Get appointments for patient 229 */ 223 230 @Transactional(readOnly = true) 224 231 public List<Appointment> getAppointmentsForPatient(Long patientId) { … … 242 249 } 243 250 244 251 /** 252 * Get appointments for doctor 253 */ 245 254 @Transactional(readOnly = true) 246 255 public List<Appointment> getAppointmentsForDoctor(Long doctorId) { … … 264 273 } 265 274 266 275 /** 276 * Get doctor's schedule for a specific date 277 */ 267 278 @Transactional(readOnly = true) 268 279 public List<Appointment> getDoctorSchedule(Long doctorId, … … 290 301 } 291 302 292 303 /** 304 * Get all appointments 305 */ 293 306 @Transactional(readOnly = true) 294 307 public List<Appointment> getAllAppointments() { … … 299 312 } 300 313 301 314 /** 315 * Find next available appointment slot for a doctor on a given date 316 * Returns a LocalTime for the next available slot, or null if no slots available 317 */ 302 318 public LocalTime findNextAvailableSlot(Long doctorId, LocalDate appointmentDate) { 303 319 LocalTime[] timeSlots = { -
backend/src/main/java/medora/service/AuthService.java
r9af201e rcdcff72 6 6 import org.slf4j.Logger; 7 7 import org.slf4j.LoggerFactory; 8 import org.springframework.security.crypto.password.PasswordEncoder; 8 9 import org.springframework.stereotype.Service; 9 10 import org.springframework.transaction.annotation.Transactional; 10 11 11 12 import java.util.HashMap; 13 import java.util.List; 12 14 import java.util.Map; 13 15 import java.util.Optional; … … 20 22 private final UserRepository userRepository; 21 23 private final JwtUtil jwtUtil; 24 private final PasswordEncoder passwordEncoder; 22 25 23 public AuthService(UserRepository userRepository, JwtUtil jwtUtil ) {26 public AuthService(UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder) { 24 27 this.userRepository = userRepository; 25 28 this.jwtUtil = jwtUtil; 29 this.passwordEncoder = passwordEncoder; 26 30 } 27 31 … … 48 52 } 49 53 50 // Simple password check (in production, use BCrypt)51 if (! user.getPassword().equals(password)) {54 // Verify password using BCrypt 55 if (!passwordEncoder.matches(password, user.getPassword())) { 52 56 logger.warn("Failed login attempt for user: {}", username); 53 57 throw new RuntimeException("Invalid username or password"); … … 72 76 } 73 77 78 public String generateTestToken() { 79 return jwtUtil.generateTokenWithDoctorId("admin", "ADMIN", 1L, null, null); 80 } 81 74 82 @Transactional 75 83 public void createUser(String username, String password, String role, String firstName, String lastName) { … … 78 86 } 79 87 80 User user = new User(username, password, role, firstName, lastName); 88 // Hash password before storing 89 String hashedPassword = passwordEncoder.encode(password); 90 User user = new User(username, hashedPassword, role, firstName, lastName); 81 91 userRepository.save(user); 82 92 logger.info("User created: {} with role: {}", username, role); 83 93 } 94 95 /** 96 * One-time migration: re-hashes any user whose stored password is still 97 * plaintext (i.e. not already a BCrypt hash) into a proper BCrypt hash. 98 * Safe to call more than once — already-hashed users are skipped. 99 * 100 * Intended to be run once via a temporary CommandLineRunner bean, then 101 * the bean should be removed so this doesn't run on every startup. 102 */ 103 @Transactional 104 public int migratePlaintextPasswords() { 105 List<User> allUsers = userRepository.findAll(); 106 int migratedCount = 0; 107 108 for (User user : allUsers) { 109 String currentPassword = user.getPassword(); 110 111 // BCrypt hashes always start with $2a$, $2b$, or $2y$ — anything 112 // else is assumed to still be plaintext and needs migrating 113 if (currentPassword != null && !currentPassword.startsWith("$2")) { 114 user.setPassword(passwordEncoder.encode(currentPassword)); 115 userRepository.save(user); 116 migratedCount++; 117 logger.info("Migrated password for user: {}", user.getUsername()); 118 } 119 } 120 121 logger.info("Password migration complete: {} of {} users migrated", migratedCount, allUsers.size()); 122 return migratedCount; 123 } 84 124 } -
backend/src/main/java/medora/service/BillingService.java
r9af201e rcdcff72 221 221 } 222 222 223 logger.info("Total billing cost for bill ID {}: procedures={}, lab tests={}", 223 logger.info("Total billing cost for bill ID {}: procedures={}, lab tests={}", 224 224 billId, procedureCost, labTestCost); 225 225 return procedureCost.add(labTestCost); … … 244 244 // This is a placeholder - adjust based on your actual Procedure entity 245 245 logger.info("Adding procedure {} to billing record {}", procedureId, billId); 246 246 247 247 return null; // Will be implemented with ProcedureRepository injection 248 248 } … … 464 464 billingRepository.deleteAll(); 465 465 466 logger.info(" Deleted {} billing records successfully", billingCount);466 logger.info("✅ Deleted {} billing records successfully", billingCount); 467 467 return billingCount; 468 468 } catch (Exception e) { 469 logger.error(" Error deleting billing records: {}", e.getMessage());469 logger.error("❌ Error deleting billing records: {}", e.getMessage()); 470 470 e.printStackTrace(); 471 471 throw e; -
backend/src/main/java/medora/service/DepartmentService.java
r9af201e rcdcff72 32 32 } 33 33 34 34 /** 35 * UC023 – View Departments 36 * Get all departments 37 */ 35 38 @Transactional(readOnly = true) 36 39 public List<Departments> getAllDepartments() { … … 39 42 } 40 43 41 44 /** 45 * Get department by ID 46 */ 42 47 @Transactional(readOnly = true) 43 48 public Optional<Departments> getDepartmentById(Long departmentId) { … … 49 54 } 50 55 51 56 /** 57 * Get department by name 58 */ 52 59 @Transactional(readOnly = true) 53 60 public Optional<Departments> getDepartmentByName(String departmentName) { … … 59 66 } 60 67 61 68 /** 69 * UC024 – View Doctors by Department 70 * Get all doctors in a specific department 71 */ 62 72 @Transactional(readOnly = true) 63 73 public List<Doctors> getDoctorsByDepartment(Long departmentId) { … … 75 85 } 76 86 77 87 /** 88 * Create a new department 89 */ 78 90 @Transactional 79 91 public Departments createDepartment(Departments department) { … … 87 99 } 88 100 89 101 /** 102 * Update department 103 */ 90 104 @Transactional 91 105 public Departments updateDepartment(Long departmentId, Departments departmentDetails) { -
backend/src/main/java/medora/service/DiagnosisService.java
r9af201e rcdcff72 2 2 3 3 import medora.models.domain.Diagnosis; 4 import medora.models.domain.Patient; 4 5 import medora.models.domain.Doctors; 5 import medora.models.domain.Patient;6 6 import medora.repository.DiagnosisRepository; 7 import medora.repository.PatientRepository; 7 8 import medora.repository.DoctorRepository; 8 import medora.repository.PatientRepository;9 9 import org.slf4j.Logger; 10 10 import org.slf4j.LoggerFactory; … … 69 69 } 70 70 71 /** 72 * Get diagnosis by ID 73 */ 71 74 @Transactional(readOnly = true) 72 75 public Optional<Diagnosis> getDiagnosisById(Long diagnosisId) { … … 78 81 } 79 82 80 83 /** 84 * Get diagnoses for patient 85 */ 81 86 @Transactional(readOnly = true) 82 87 public List<Diagnosis> getDiagnosesForPatient(Long patientId) { … … 91 96 } 92 97 93 98 /** 99 * Get diagnoses by doctor 100 */ 94 101 @Transactional(readOnly = true) 95 102 public List<Diagnosis> getDiagnosesByDoctor(Long doctorId) { … … 105 112 106 113 107 @Transactional108 public Diagnosis updateDiagnosis(Long diagnosisId,109 String diagnosisName,110 String description) {111 112 if (diagnosisId == null || diagnosisId <= 0)113 throw new IllegalArgumentException("Diagnosis ID must be valid");114 115 Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)116 .orElseThrow(() -> new RuntimeException("Diagnosis not found"));117 118 if (diagnosisName != null && !diagnosisName.isBlank())119 diagnosis.setName(diagnosisName);120 121 if (description != null)122 diagnosis.setDescription(description);123 124 return diagnosisRepository.save(diagnosis);125 }126 114 } -
backend/src/main/java/medora/service/DoctorService.java
r9af201e rcdcff72 1 1 package medora.service; 2 2 3 import medora.models.domain.Doctors; 3 4 import medora.models.domain.Departments; 4 import medora. models.domain.Doctors;5 import medora.repository.DoctorRepository; 5 6 import medora.repository.DepartmentRepository; 6 import medora.repository.DoctorRepository;7 7 import org.slf4j.Logger; 8 8 import org.slf4j.LoggerFactory; … … 46 46 } 47 47 48 48 /** 49 * Get doctor by email 50 */ 49 51 @Transactional(readOnly = true) 50 52 public Doctors getDoctorByEmail(String emailAddress) { … … 59 61 } 60 62 61 63 /** 64 * UC024 – View Doctors by Department 65 */ 62 66 @Transactional(readOnly = true) 63 67 public List<Doctors> getDoctorsByDepartment(Long departmentId) { … … 74 78 } 75 79 76 80 /** 81 * Get doctors by specialization 82 */ 77 83 @Transactional(readOnly = true) 78 84 public List<Doctors> getDoctorsBySpecialization(Long specializationId) { … … 86 92 } 87 93 88 94 /** 95 * Get doctors by level 96 */ 89 97 @Transactional(readOnly = true) 90 98 public List<Doctors> getDoctorsByLevel(Long levelId) { … … 98 106 } 99 107 100 108 /** 109 * Get all doctors 110 */ 101 111 @Transactional(readOnly = true) 102 112 public List<Doctors> getAllDoctors() { … … 105 115 } 106 116 107 117 /** 118 * Create doctor 119 */ 108 120 @Transactional 109 121 public Doctors createDoctor(Doctors doctor) { … … 146 158 } 147 159 148 160 /** 161 * Update doctor 162 */ 149 163 @Transactional 150 164 public Doctors updateDoctor(Long doctorId, Doctors doctorDetails) { -
backend/src/main/java/medora/service/LabService.java
r9af201e rcdcff72 223 223 @Transactional(readOnly = true) 224 224 public List<PerformedLabTests> getPendingLabTests() { 225 // Get all performed tests and filter to only those without results 226 List<PerformedLabTests> allTests = performedLabTestRepository.findAll(); 227 228 return allTests.stream() 229 .filter(test -> { 230 // Get the patient's medical record 231 Optional<MedicalRecord> recordOpt = medicalRecordRepository.findByPatientPatientId(test.getPatient().getPatientId()); 232 if (recordOpt.isEmpty()) { 233 return true; // No medical record, so no results possible 234 } 235 236 MedicalRecord record = recordOpt.get(); 237 // Check if this test has results in this medical record 238 List<MedicalRecordLabResults> results = medicalRecordLabResultRepository 239 .findByMedicalRecordRecordId(record.getRecordId()); 240 241 // Filter to only results for this specific test 242 return results.stream() 243 .noneMatch(r -> r.getLabResult().getLabTest().getTestId().equals(test.getLabTest().getTestId())); 244 }) 245 .toList(); 225 logger.info("Fetching all pending lab test requests"); 226 return performedLabTestRepository.findAll(); 246 227 } 247 228 -
backend/src/main/java/medora/service/MedicalObservationsService.java
r9af201e rcdcff72 2 2 3 3 4 import medora.models.domain.*; 5 import medora.repository.*; 4 import medora.models.domain.MedicalRecordSymptoms; 5 import medora.models.domain.MedicalRecordAllergies; 6 import medora.models.domain.Symptoms; 7 import medora.models.domain.Allergies; 8 import medora.models.domain.MedicalRecord; 9 import medora.repository.SymptomRepository; 10 import medora.repository.AllergyRepository; 11 import medora.repository.MedicalRecordSymptomRepository; 12 import medora.repository.MedicalRecordAllergyRepository; 13 import medora.repository.MedicalRecordRepository; 6 14 import org.slf4j.Logger; 7 15 import org.slf4j.LoggerFactory; … … 61 69 .orElseThrow(() -> new RuntimeException("Symptom not found with ID: " + symptomId)); 62 70 63 71 // Check if symptom is already recorded 64 72 if (medicalRecordSymptomRepository.existsByMedicalRecordRecordIdAndSymptomSymptomId( 65 73 medicalRecordId, symptomId)) { … … 93 101 94 102 95 // For ALLERGIES103 // ================= ALLERGIES OPERATIONS ================= 96 104 97 105 /** … … 128 136 } 129 137 130 138 /** 139 * Get all allergies for a patient's medical record 140 */ 131 141 @Transactional(readOnly = true) 132 142 public List<MedicalRecordAllergies> getAllergiesForMedicalRecord(Long medicalRecordId) { … … 143 153 } 144 154 155 145 156 157 /** 158 * Get all available symptoms 159 */ 146 160 @Transactional(readOnly = true) 147 161 public List<Symptoms> getAllSymptoms() { … … 150 164 } 151 165 152 166 /** 167 * Get all available allergies 168 */ 153 169 @Transactional(readOnly = true) 154 170 public List<Allergies> getAllAllergies() { -
backend/src/main/java/medora/service/MedicalRecordService.java
r9af201e rcdcff72 1 1 package medora.service; 2 2 3 import medora.models.domain.*; 3 import medora.models.domain.Allergies; 4 import medora.models.domain.MedicalRecord; 5 import medora.models.domain.MedicalRecordAllergies; 6 import medora.models.domain.MedicalRecordSymptoms; 7 import medora.models.domain.Symptoms; 4 8 import medora.models.domain.id.MedicalRecordAllergyId; 5 9 import medora.models.domain.id.MedicalRecordLabResultId; 6 10 import medora.models.domain.id.MedicalRecordProcedureId; 7 11 import medora.models.domain.id.MedicalRecordSymptomId; 8 import medora.repository.*; 12 import medora.repository.AllergyRepository; 13 import medora.repository.MedicalRecordAllergyRepository; 14 import medora.repository.MedicalRecordLabResultRepository; 15 import medora.repository.MedicalRecordProcedureRepository; 16 import medora.repository.MedicalRecordRepository; 17 import medora.repository.MedicalRecordSymptomRepository; 18 import medora.repository.PatientRepository; 19 import medora.repository.SymptomRepository; 9 20 import org.slf4j.Logger; 10 21 import org.slf4j.LoggerFactory; … … 94 105 } 95 106 96 // UC015 – Link Medical Data to Medical Record 107 // UC015 – Link Medical Data to Medical Record ⭐ (IMPORTANT FIX) 97 108 @Transactional 98 109 public MedicalRecord linkMedicalData(Long recordId, MedicalRecord updatedData) { … … 109 120 .orElseThrow(() -> new RuntimeException("Medical record not found")); 110 121 122 // Safely link many-to-many/join-table rows. 123 // The project currently models join-tables as explicit entities (e.g. MedicalRecordProcedures), 124 // but `MedicalRecord` entity in this codebase doesn't expose collection getters yet. 125 // To avoid compile problems and still support DTOs that may contain collections, use reflection: 111 126 112 127 try { … … 126 141 } 127 142 } catch (NoSuchMethodException ignored) { 128 143 // updatedData has no getProcedures() — nothing to do 129 144 } 130 145 … … 144 159 } 145 160 } catch (NoSuchMethodException ignored) { 146 161 // updatedData has no getLabResults() — nothing to do 147 162 } 148 163 … … 157 172 MedicalRecordAllergyId mraId = new MedicalRecordAllergyId(recordId, allergyId); 158 173 if (medicalRecordAllergyRepository.findById(mraId).isEmpty()) { 159 174 // Create allergy join entity manually and save 160 175 MedicalRecordAllergies allergyJoin = 161 176 new MedicalRecordAllergies(); 162 177 allergyJoin.setMedicalRecord(record); 163 178 // Load allergy entity would require allergyRepo, which we don't have injected yet 179 // For now, just save the join if it doesn't exist (via repository direct save) 164 180 logger.debug("Allergy {} linking deferred (missing allergyRepo)", allergyId); 165 181 } … … 167 183 } 168 184 } catch (NoSuchMethodException ignored) { 169 185 // updatedData has no getAllergies() — nothing to do 170 186 } 171 187 … … 185 201 } 186 202 } catch (NoSuchMethodException ignored) { 187 203 // updatedData has no getSymptoms() — nothing to do 188 204 } 189 205 } catch (ReflectiveOperationException e) { 190 206 // If reflection fails for unexpected reasons, log and rethrow as runtime to avoid silent data loss. 191 207 throw new RuntimeException("Failed to link medical data via reflection", e); 192 208 } … … 196 212 } 197 213 214 // UPDATE medical record 198 215 @Transactional 199 216 public MedicalRecord updateMedicalRecord(Long recordId, MedicalRecord recordDetails) { … … 214 231 } 215 232 233 // helper 216 234 @Transactional(readOnly = true) 217 235 public List<MedicalRecord> getAllMedicalRecords() { … … 273 291 } 274 292 275 293 // Reflection helper: try to extract an id from an object using common getter names 276 294 private Long extractId(Object obj, String... candidateGetters) { 277 295 if (obj == null) return null; … … 282 300 if (val instanceof Number) return ((Number) val).longValue(); 283 301 } catch (ReflectiveOperationException ignored) { 284 302 // try next 285 303 } 286 304 } -
backend/src/main/java/medora/service/MedicalReportService.java
r9af201e rcdcff72 1 1 package medora.service; 2 2 3 import medora.models.domain.*; 3 4 import medora.dto.*; 4 import medora.models.domain.*;5 5 import medora.repository.*; 6 6 import org.slf4j.Logger; … … 10 10 11 11 import java.time.LocalDate; 12 import java.util.HashSet; 12 13 import java.util.List; 13 14 import java.util.Optional; 15 import java.util.Set; 14 16 import java.util.stream.Collectors; 15 17 -
backend/src/main/java/medora/service/PatientService.java
r9af201e rcdcff72 2 2 3 3 4 import medora.models.domain.Patient; 4 5 import medora.models.domain.MedicalRecord; 5 import medora. models.domain.Patient;6 import medora.repository.PatientRepository; 6 7 import medora.repository.MedicalRecordRepository; 7 import medora.repository.PatientRepository;8 8 import org.slf4j.Logger; 9 9 import org.slf4j.LoggerFactory; -
backend/src/main/java/medora/service/PrescriptionService.java
r9af201e rcdcff72 1 1 package medora.service; 2 2 3 import medora.models.domain.Prescriptions; 4 import medora.models.domain.PrescriptionMedicalRecord; 3 5 import medora.models.domain.MedicalRecord; 4 import medora. models.domain.PrescriptionMedicalRecord;5 import medora. models.domain.Prescriptions;6 import medora.repository.PrescriptionRepository; 7 import medora.repository.PrescriptionMedicalRecordRepository; 6 8 import medora.repository.MedicalRecordRepository; 7 import medora.repository.PrescriptionMedicalRecordRepository;8 import medora.repository.PrescriptionRepository;9 9 import org.slf4j.Logger; 10 10 import org.slf4j.LoggerFactory; -
backend/src/main/java/medora/service/ProcedureService.java
r9af201e rcdcff72 297 297 .orElseThrow(() -> new RuntimeException("Procedure not found")); 298 298 299 ProcedureResults result = new ProcedureResults(); 300 result.setProcedure(procedure); 301 result.setResultDescription(resultDescription); 302 result.setResultDate(resultDate); 303 304 ProcedureResults savedResult = procedureResultRepository.save(result); 305 306 // Link to medical record 307 MedicalRecordProcedureResults link = new MedicalRecordProcedureResults(record, savedResult); 308 medicalRecordProcedureResultRepository.save(link); 309 310 logger.info("Stored procedure result {} for medical record {}", savedResult.getResultId(), medicalRecordId); 311 return savedResult; 299 // Check if result already exists for this medical record and procedure 300 List<ProcedureResults> existingResults = procedureResultRepository.findByMedicalRecordAndProcedure(medicalRecordId, procedureId); 301 302 ProcedureResults result; 303 if (!existingResults.isEmpty()) { 304 // Update existing result 305 result = existingResults.get(0); 306 result.setResultDescription(resultDescription); 307 result.setResultDate(resultDate); 308 ProcedureResults savedResult = procedureResultRepository.save(result); 309 logger.info("Updated procedure result {} for medical record {}", savedResult.getResultId(), medicalRecordId); 310 return savedResult; 311 } else { 312 // Create new result 313 result = new ProcedureResults(); 314 result.setProcedure(procedure); 315 result.setResultDescription(resultDescription); 316 result.setResultDate(resultDate); 317 318 // Save result first to generate ID 319 ProcedureResults savedResult = procedureResultRepository.save(result); 320 321 // Then link to medical record 322 MedicalRecordProcedureResults link = new MedicalRecordProcedureResults(record, savedResult); 323 medicalRecordProcedureResultRepository.save(link); 324 logger.info("Created new procedure result {} for medical record {}", savedResult.getResultId(), medicalRecordId); 325 return savedResult; 326 } 312 327 } 313 328 -
backend/src/main/java/medora/service/ReferralService.java
r9af201e rcdcff72 106 106 } 107 107 108 108 /** 109 * Get referral by ID 110 */ 109 111 @Transactional(readOnly = true) 110 112 public Optional<Referrals> getReferralById(Long referralId) { … … 116 118 } 117 119 118 120 /** 121 * Get referrals for a patient 122 */ 119 123 @Transactional(readOnly = true) 120 124 public List<Referrals> getReferralsForPatient(Long patientId) { … … 131 135 } 132 136 133 137 /** 138 * Get referrals made by a doctor 139 */ 134 140 @Transactional(readOnly = true) 135 141 public List<Referrals> getReferralsByFromDoctor(Long doctorId) { … … 146 152 } 147 153 154 /** 155 * Get referrals received by a doctor 156 */ 148 157 @Transactional(readOnly = true) 149 158 public List<Referrals> getReferralsToDoctor(Long doctorId) { … … 160 169 } 161 170 162 171 /** 172 * Create appointment for referral in a separate transaction 173 * Using REQUIRES_NEW ensures appointment creation failures don't rollback the referral 174 */ 163 175 @Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW) 164 176 private void createAppointmentForReferral(Long patientId, Long doctorId, LocalDate appointmentDate, LocalTime appointmentTime) { -
backend/src/main/java/medora/util/JwtUtil.java
r9af201e rcdcff72 30 30 public void init() { 31 31 logger.info("JwtUtil initialized - JWT Secret length: {}, Expiration: {}ms", 32 jwtSecret != null ? jwtSecret.length() : 0, jwtExpirationMs);32 jwtSecret != null ? jwtSecret.length() : 0, jwtExpirationMs); 33 33 if (jwtSecret == null || jwtSecret.isEmpty()) { 34 34 logger.error("⚠️ JWT_SECRET is not set or empty!"); … … 123 123 124 124 logger.info("🔐 Validating token - secret hash: {}, secret length: {}, token length: {}", 125 jwtSecret.hashCode(), jwtSecret.length(), token.length());125 jwtSecret.hashCode(), jwtSecret.length(), token.length()); 126 126 127 127 Jwts.parser() -
backend/src/main/resources/application.properties
r9af201e rcdcff72 23 23 spring.jackson.serialization.fail-on-empty-beans=false 24 24 spring.jackson.default-property-inclusion=non_null 25 -
backend/src/main/resources/db/migration/V1.1__Create_Daily_Billing_View.sql
r9af201e rcdcff72 1 -- Create materialized view for daily patient billing totals1 -- Create materialized view for daily patient billing totals 2 2 CREATE MATERIALIZED VIEW IF NOT EXISTS daily_patient_billing_totals AS 3 3 SELECT -
backend/src/main/resources/db/migration/V1.2__Create_Users_Table.sql
r9af201e rcdcff72 1 user2 1 -- Create users table 3 2 CREATE TABLE IF NOT EXISTS users ( … … 32 31 ) 33 32 LIMIT 39; 33 34 -- Insert doctor users (password: doctor123 for all) 35 -- These will be linked to existing doctors by email 36 INSERT INTO users (username, password, role, first_name, last_name, doctor_id, is_active) 37 SELECT d.email_address, 'doctor123', 'DOCTOR', d.first_name, d.last_name, d.doctor_id, true 38 FROM doctors d 39 WHERE NOT EXISTS ( 40 SELECT 1 FROM users u WHERE u.username = d.email_address 41 ); -
backend/src/test/java/medora/Medora4ApplicationTests.java
r9af201e rcdcff72 5 5 6 6 @SpringBootTest 7 class Medora 5ApplicationTests {7 class Medora4ApplicationTests { 8 8 9 9 @Test
Note:
See TracChangeset
for help on using the changeset viewer.
