Index: backend/src/main/java/medora/dto/SimpleProcedureDTO.java
===================================================================
--- backend/src/main/java/medora/dto/SimpleProcedureDTO.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/dto/SimpleProcedureDTO.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,18 @@
+package medora.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class SimpleProcedureDTO {
+    private Long procedureId;
+    private String procedureType;
+    private String description;
+    private BigDecimal cost;
+}
Index: backend/src/main/java/medora/service/AppointmentService.java
===================================================================
--- backend/src/main/java/medora/service/AppointmentService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/AppointmentService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,299 @@
+package medora.service;
+
+import medora.models.domain.Appointment;
+import medora.models.domain.Doctors;
+import medora.models.domain.Patient;
+import medora.models.enums.AppointmentStatus;
+import medora.repository.AppointmentRepository;
+import medora.repository.DoctorRepository;
+import medora.repository.PatientRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * AppointmentService handles appointment operations.
+ * UC006 – Create Appointment Record
+ * UC007 – Cancel Appointment Record
+ */
+@Service
+public class AppointmentService {
+
+    private static final Logger logger =
+            LoggerFactory.getLogger(AppointmentService.class);
+
+    private final AppointmentRepository appointmentRepository;
+    private final PatientRepository patientRepository;
+    private final DoctorRepository doctorRepository;
+
+    public AppointmentService(AppointmentRepository appointmentRepository,
+                              PatientRepository patientRepository,
+                              DoctorRepository doctorRepository) {
+
+        this.appointmentRepository = appointmentRepository;
+        this.patientRepository = patientRepository;
+        this.doctorRepository = doctorRepository;
+    }
+
+    /**
+     * UC006 – Create Appointment Record
+     */
+    @Transactional
+    public Appointment createAppointment(Long patientId,
+                                         Long doctorId,
+                                         LocalDate appointmentDate,
+                                         LocalTime appointmentTime) {
+
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        if (appointmentDate == null) {
+            throw new IllegalArgumentException("Appointment date is required");
+        }
+
+        if (appointmentTime == null) {
+            throw new IllegalArgumentException("Appointment time is required");
+        }
+
+        Patient patient = patientRepository.findById(patientId)
+                .orElseThrow(() ->
+                        new RuntimeException("Patient not found with ID: " + patientId));
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() ->
+                        new RuntimeException("Doctor not found with ID: " + doctorId));
+
+        LocalDateTime appointmentDateTime =
+                LocalDateTime.of(appointmentDate, appointmentTime);
+
+
+        if (!appointmentDateTime.isAfter(LocalDateTime.now())) {
+            throw new RuntimeException(
+                    "Appointment must be scheduled for a future date and time"
+            );
+        }
+
+        boolean doctorBusy =
+                appointmentRepository
+                        .existsByDoctorDoctorIdAndAppointmentDateAndAppointmentTimeAndStatusNot(
+                                doctorId,
+                                appointmentDate,
+                                appointmentTime,
+                                AppointmentStatus.CANCELLED
+                        );
+
+        if (doctorBusy) {
+            throw new RuntimeException("This appointment slot is already booked");
+        }
+
+        boolean duplicateAppointment =
+                appointmentRepository
+                        .existsByPatientPatientIdAndDoctorDoctorIdAndAppointmentDateAndAppointmentTimeAndStatusNot(
+                                patientId,
+                                doctorId,
+                                appointmentDate,
+                                appointmentTime,
+                                AppointmentStatus.CANCELLED
+                        );
+
+        if (duplicateAppointment) {
+            throw new RuntimeException(
+                    "Patient already has this appointment scheduled"
+            );
+        }
+
+        Appointment appointment = new Appointment();
+
+        appointment.setPatient(patient);
+        appointment.setDoctor(doctor);
+        appointment.setAppointmentDate(appointmentDate);
+        appointment.setAppointmentTime(appointmentTime);
+        appointment.setStatus(AppointmentStatus.SCHEDULED);
+
+        logger.info(
+                "Creating appointment for patient ID: {} with doctor ID: {}",
+                patientId,
+                doctorId
+        );
+
+        return appointmentRepository.save(appointment);
+    }
+
+    /**
+     * UC007 – Cancel Appointment Record
+     */
+    @Transactional
+    public Appointment cancelAppointment(Long appointmentId) {
+
+        if (appointmentId == null || appointmentId <= 0) {
+            throw new IllegalArgumentException("Appointment ID must be valid");
+        }
+
+        Appointment appointment = appointmentRepository.findById(appointmentId)
+                .orElseThrow(() ->
+                        new RuntimeException(
+                                "Appointment not found with ID: " + appointmentId
+                        ));
+
+        LocalDateTime appointmentDateTime =
+                LocalDateTime.of(
+                        appointment.getAppointmentDate(),
+                        appointment.getAppointmentTime()
+                );
+
+        if (!appointmentDateTime.isAfter(LocalDateTime.now())) {
+            throw new RuntimeException(
+                    "Only future appointments can be cancelled"
+            );
+        }
+
+        if (appointment.getStatus() == AppointmentStatus.CANCELLED) {
+            throw new RuntimeException("Appointment is already cancelled");
+        }
+
+        if (appointment.getStatus() == AppointmentStatus.COMPLETED) {
+            throw new RuntimeException(
+                    "Completed appointments cannot be cancelled"
+            );
+        }
+
+        appointment.setStatus(AppointmentStatus.CANCELLED);
+
+        logger.info("Cancelling appointment with ID: {}", appointmentId);
+
+        return appointmentRepository.save(appointment);
+    }
+
+
+    @Transactional
+    public Appointment completeAppointment(Long appointmentId) {
+
+        if (appointmentId == null || appointmentId <= 0) {
+            throw new IllegalArgumentException("Appointment ID must be valid");
+        }
+
+        Appointment appointment = appointmentRepository.findById(appointmentId)
+                .orElseThrow(() ->
+                        new RuntimeException(
+                                "Appointment not found with ID: " + appointmentId
+                        ));
+
+        if (appointment.getStatus() == AppointmentStatus.CANCELLED) {
+            throw new RuntimeException(
+                    "Cancelled appointments cannot be completed"
+            );
+        }
+
+        appointment.setStatus(AppointmentStatus.COMPLETED);
+
+        logger.info("Completing appointment with ID: {}", appointmentId);
+
+        return appointmentRepository.save(appointment);
+    }
+
+
+    @Transactional(readOnly = true)
+    public Optional<Appointment> getAppointmentById(Long appointmentId) {
+
+        if (appointmentId == null || appointmentId <= 0) {
+            throw new IllegalArgumentException("Appointment ID must be valid");
+        }
+
+        logger.info("Fetching appointment with ID: {}", appointmentId);
+
+        return appointmentRepository.findById(appointmentId);
+    }
+
+    /**
+     * Get appointments for patient
+     */
+    @Transactional(readOnly = true)
+    public List<Appointment> getAppointmentsForPatient(Long patientId) {
+
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+
+        if (!patientRepository.existsById(patientId)) {
+            throw new RuntimeException(
+                    "Patient not found with ID: " + patientId
+            );
+        }
+
+        logger.info("Fetching appointments for patient ID: {}", patientId);
+
+        return appointmentRepository
+                .findByPatientPatientIdOrderByAppointmentDateAscAppointmentTimeAsc(
+                        patientId
+                );
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Appointment> getAppointmentsForDoctor(Long doctorId) {
+
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        if (!doctorRepository.existsById(doctorId)) {
+            throw new RuntimeException(
+                    "Doctor not found with ID: " + doctorId
+            );
+        }
+
+        logger.info("Fetching appointments for doctor ID: {}", doctorId);
+
+        return appointmentRepository
+                .findByDoctorDoctorIdOrderByAppointmentDateAscAppointmentTimeAsc(
+                        doctorId
+                );
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Appointment> getDoctorSchedule(Long doctorId,
+                                               LocalDate appointmentDate) {
+
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        if (appointmentDate == null) {
+            throw new IllegalArgumentException("Appointment date is required");
+        }
+
+        logger.info(
+                "Fetching doctor schedule for doctor ID: {} on {}",
+                doctorId,
+                appointmentDate
+        );
+
+        return appointmentRepository
+                .findByDoctorDoctorIdAndAppointmentDateOrderByAppointmentTimeAsc(
+                        doctorId,
+                        appointmentDate
+                );
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Appointment> getAllAppointments() {
+
+        logger.info("Fetching all appointments");
+
+        return appointmentRepository.findAll();
+    }
+}
Index: backend/src/main/java/medora/service/BillingService.java
===================================================================
--- backend/src/main/java/medora/service/BillingService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/BillingService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,246 @@
+package medora.service;
+
+import medora.models.domain.*;
+import medora.models.enums.PaymentStatus;
+import medora.repository.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * BillingService handles billing operations.
+ * UC020 – Generate Billing Record
+ * UC021 – Record Payment Status
+ * UC022 – View Billing History
+ */
+@Service
+public class BillingService {
+
+    private static final Logger logger = LoggerFactory.getLogger(BillingService.class);
+
+    private final BillingRepository billingRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+    private final AdminRepository adminRepository;
+    private final BillingLabTestsRepository billingLabTestsRepository;
+    private final BillingProceduresRepository billingProceduresRepository;
+
+    public BillingService(BillingRepository billingRepository,
+                          MedicalRecordRepository medicalRecordRepository,
+                          AdminRepository adminRepository,
+                          BillingLabTestsRepository billingLabTestsRepository,
+                          BillingProceduresRepository billingProceduresRepository) {
+        this.billingRepository = billingRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+        this.adminRepository = adminRepository;
+        this.billingLabTestsRepository = billingLabTestsRepository;
+        this.billingProceduresRepository = billingProceduresRepository;
+    }
+
+    /**
+     * UC020 – Generate Billing Record
+     * Create a billing record based on procedures and lab tests
+     */
+    @Transactional
+    public Billing generateBillingRecord(Long medicalRecordId, Long adminId, BigDecimal totalCost) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (adminId == null || adminId <= 0) {
+            throw new IllegalArgumentException("Admin ID must be valid");
+        }
+        if (totalCost == null || totalCost.compareTo(BigDecimal.ZERO) < 0) {
+            throw new IllegalArgumentException("Total cost must be valid");
+        }
+
+        MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found with ID: " + medicalRecordId));
+
+        Admin admin = adminRepository.findById(adminId)
+                .orElseThrow(() -> new RuntimeException("Admin not found with ID: " + adminId));
+
+        Billing billing = new Billing();
+        billing.setMedicalRecord(medicalRecord);
+        billing.setAdmin(admin);
+        billing.setTotalCost(totalCost);
+        billing.setPaymentStatus(PaymentStatus.PENDING);
+
+        logger.info("Generating billing record for medical record ID: {} with total cost: {}",
+                medicalRecordId, totalCost);
+        return billingRepository.save(billing);
+    }
+
+    /**
+     * UC021 – Record Payment Status
+     * Update billing payment status
+     */
+    @Transactional
+    public Billing updatePaymentStatus(Long billId, PaymentStatus paymentStatus, LocalDate paymentDate) {
+        if (billId == null || billId <= 0) {
+            throw new IllegalArgumentException("Bill ID must be valid");
+        }
+        if (paymentStatus == null) {
+            throw new IllegalArgumentException("Payment status is required");
+        }
+
+        Billing billing = billingRepository.findById(billId)
+                .orElseThrow(() -> new RuntimeException("Billing record not found with ID: " + billId));
+
+        billing.setPaymentStatus(paymentStatus);
+        if (paymentDate != null && paymentStatus == PaymentStatus.PAID) {
+            billing.setPaymentDate(paymentDate);
+        }
+
+        logger.info("Updating payment status for bill ID: {} to {}", billId, paymentStatus);
+        return billingRepository.save(billing);
+    }
+
+    /**
+     * UC022 – View Billing History
+     * Get all billing records for a patient (via medical record)
+     */
+    @Transactional(readOnly = true)
+    public List<Billing> getBillingHistoryForPatient(Long patientId) {
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+
+        logger.info("Fetching billing history for patient ID: {}", patientId);
+        return billingRepository.findBillingHistoryForPatient(patientId);
+    }
+
+    /**
+     * UC022 – View Billing History
+     * Get billing record by ID
+     */
+    @Transactional(readOnly = true)
+    public Optional<Billing> getBillingById(Long billId) {
+        if (billId == null || billId <= 0) {
+            throw new IllegalArgumentException("Bill ID must be valid");
+        }
+        logger.info("Fetching billing record with ID: {}", billId);
+        return billingRepository.findById(billId);
+    }
+
+    /**
+     * Get all billing records
+     */
+    @Transactional(readOnly = true)
+    public List<Billing> getAllBillingRecords() {
+        logger.info("Fetching all billing records");
+        return billingRepository.findAll();
+    }
+
+    /**
+     * Get billing records by payment status
+     */
+    @Transactional(readOnly = true)
+    public List<Billing> getBillingByPaymentStatus(PaymentStatus paymentStatus) {
+        if (paymentStatus == null) {
+            throw new IllegalArgumentException("Payment status is required");
+        }
+
+        logger.info("Fetching billing records with payment status: {}", paymentStatus);
+        return billingRepository.findByPaymentStatus(paymentStatus.toString());
+    }
+
+    /**
+     * Get billing record for a medical record
+     */
+    @Transactional(readOnly = true)
+    public Optional<Billing> getBillingForMedicalRecord(Long medicalRecordId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+
+        if (!medicalRecordRepository.existsById(medicalRecordId)) {
+            throw new RuntimeException("Medical record not found with ID: " + medicalRecordId);
+        }
+
+        logger.info("Fetching billing record for medical record ID: {}", medicalRecordId);
+        // Get all bills and filter by medical record
+        return billingRepository.findAll()
+                .stream()
+                .filter(b -> b.getMedicalRecord().getRecordId().equals(medicalRecordId))
+                .findFirst();
+    }
+
+    /**
+     * Calculate total cost from procedures and lab tests for a medical record
+     */
+    @Transactional(readOnly = true)
+    public BigDecimal calculateTotalCostForBilling(Long billId) {
+        if (billId == null || billId <= 0) {
+            throw new IllegalArgumentException("Bill ID must be valid");
+        }
+
+        if (!billingRepository.existsById(billId)) {
+            throw new RuntimeException("Billing record not found with ID: " + billId);
+        }
+
+        // Calculate cost from procedures
+        BigDecimal procedureCost = billingProceduresRepository.calculateTotalCostForBilling(billId);
+        if (procedureCost == null) {
+            procedureCost = BigDecimal.ZERO;
+        }
+
+        // Calculate cost from lab tests
+        BigDecimal labTestCost = billingLabTestsRepository.calculateTotalCostForBilling(billId);
+        if (labTestCost == null) {
+            labTestCost = BigDecimal.ZERO;
+        }
+
+        logger.info("Total billing cost for bill ID {}: procedures={}, lab tests={}", 
+                billId, procedureCost, labTestCost);
+        return procedureCost.add(labTestCost);
+    }
+
+    /**
+     * Add a procedure to a billing record
+     */
+    @Transactional
+    public BillingProcedures addProcedureToBilling(Long billId, Long procedureId) {
+        if (billId == null || billId <= 0) {
+            throw new IllegalArgumentException("Bill ID must be valid");
+        }
+        if (procedureId == null || procedureId <= 0) {
+            throw new IllegalArgumentException("Procedure ID must be valid");
+        }
+
+        Billing billing = billingRepository.findById(billId)
+                .orElseThrow(() -> new RuntimeException("Billing record not found with ID: " + billId));
+
+        // Note: You'll need to inject ProcedureRepository to get the procedure
+        // This is a placeholder - adjust based on your actual Procedure entity
+        logger.info("Adding procedure {} to billing record {}", procedureId, billId);
+        
+        return null; // Will be implemented with ProcedureRepository injection
+    }
+
+    /**
+     * Add a lab test to a billing record
+     */
+    @Transactional
+    public BillingLabTests addLabTestToBilling(Long billId, Long testId) {
+        if (billId == null || billId <= 0) {
+            throw new IllegalArgumentException("Bill ID must be valid");
+        }
+        if (testId == null || testId <= 0) {
+            throw new IllegalArgumentException("Test ID must be valid");
+        }
+
+        Billing billing = billingRepository.findById(billId)
+                .orElseThrow(() -> new RuntimeException("Billing record not found with ID: " + billId));
+
+        // Note: You'll need to inject LabTestRepository to get the test
+        // This is a placeholder - adjust based on your actual LabTests entity
+        logger.info("Adding lab test {} to billing record {}", testId, billId);
+        
+        return null; // Will be implemented with LabTestRepository injection
+    }
+}
Index: backend/src/main/java/medora/service/DepartmentService.java
===================================================================
--- backend/src/main/java/medora/service/DepartmentService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/DepartmentService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,106 @@
+package medora.service;
+
+import medora.models.domain.Departments;
+import medora.models.domain.Doctors;
+import medora.repository.DepartmentRepository;
+import medora.repository.DoctorRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * DepartmentService handles department operations.
+ * UC023 – View Departments
+ * UC024 – View Doctors by Department
+ */
+@Service
+public class DepartmentService {
+
+    private static final Logger logger = LoggerFactory.getLogger(DepartmentService.class);
+
+    private final DepartmentRepository departmentRepository;
+    private final DoctorRepository doctorRepository;
+
+    public DepartmentService(DepartmentRepository departmentRepository,
+                             DoctorRepository doctorRepository) {
+        this.departmentRepository = departmentRepository;
+        this.doctorRepository = doctorRepository;
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Departments> getAllDepartments() {
+        logger.info("Fetching all departments");
+        return departmentRepository.findAll();
+    }
+
+
+    @Transactional(readOnly = true)
+    public Optional<Departments> getDepartmentById(Long departmentId) {
+        if (departmentId == null || departmentId <= 0) {
+            throw new IllegalArgumentException("Department ID must be valid");
+        }
+        logger.info("Fetching department with ID: {}", departmentId);
+        return departmentRepository.findById(departmentId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public Optional<Departments> getDepartmentByName(String departmentName) {
+        if (departmentName == null || departmentName.isBlank()) {
+            throw new IllegalArgumentException("Department name cannot be null or empty");
+        }
+        logger.info("Fetching department with name: {}", departmentName);
+        return departmentRepository.findByDepartmentName(departmentName);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Doctors> getDoctorsByDepartment(Long departmentId) {
+        if (departmentId == null || departmentId <= 0) {
+            throw new IllegalArgumentException("Department ID must be valid");
+        }
+
+        // Verify department exists
+        if (!departmentRepository.existsById(departmentId)) {
+            throw new RuntimeException("Department not found with ID: " + departmentId);
+        }
+
+        logger.info("Fetching doctors for department ID: {}", departmentId);
+        return doctorRepository.findByDepartmentDepartmentId(departmentId);
+    }
+
+
+    @Transactional
+    public Departments createDepartment(Departments department) {
+        if (department == null || department.getDepartmentName() == null ||
+                department.getDepartmentName().isBlank()) {
+            throw new IllegalArgumentException("Department name is required");
+        }
+
+        logger.info("Creating new department: {}", department.getDepartmentName());
+        return departmentRepository.save(department);
+    }
+
+
+    @Transactional
+    public Departments updateDepartment(Long departmentId, Departments departmentDetails) {
+        if (departmentId == null || departmentId <= 0) {
+            throw new IllegalArgumentException("Department ID must be valid");
+        }
+
+        Departments department = departmentRepository.findById(departmentId)
+                .orElseThrow(() -> new RuntimeException("Department not found with ID: " + departmentId));
+
+        if (departmentDetails.getDepartmentName() != null && !departmentDetails.getDepartmentName().isBlank()) {
+            department.setDepartmentName(departmentDetails.getDepartmentName());
+        }
+
+        logger.info("Updating department with ID: {}", departmentId);
+        return departmentRepository.save(department);
+    }
+}
Index: backend/src/main/java/medora/service/DiagnosisService.java
===================================================================
--- backend/src/main/java/medora/service/DiagnosisService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/DiagnosisService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,126 @@
+package medora.service;
+
+import medora.models.domain.Diagnosis;
+import medora.models.domain.Doctors;
+import medora.models.domain.Patient;
+import medora.repository.DiagnosisRepository;
+import medora.repository.DoctorRepository;
+import medora.repository.PatientRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * DiagnosisService handles diagnosis operations.
+ * UC009 – Record Diagnosis
+ * UC015 – Link Medical Data to Medical Record
+ */
+@Service
+public class DiagnosisService {
+
+    private static final Logger logger = LoggerFactory.getLogger(DiagnosisService.class);
+
+    private final DiagnosisRepository diagnosisRepository;
+    private final PatientRepository patientRepository;
+    private final DoctorRepository doctorRepository;
+
+    public DiagnosisService(DiagnosisRepository diagnosisRepository,
+                            PatientRepository patientRepository,
+                            DoctorRepository doctorRepository) {
+        this.diagnosisRepository = diagnosisRepository;
+        this.patientRepository = patientRepository;
+        this.doctorRepository = doctorRepository;
+    }
+
+    /**
+     * UC009 – Record Diagnosis
+     */
+    @Transactional
+    public Diagnosis recordDiagnosis(Long patientId, Long doctorId,
+                                     String diagnosisName, String description) {
+
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Patient ID must be valid");
+
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Doctor ID must be valid");
+
+        if (diagnosisName == null || diagnosisName.isBlank())
+            throw new IllegalArgumentException("Diagnosis name is required");
+
+        Patient patient = patientRepository.findById(patientId)
+                .orElseThrow(() -> new RuntimeException("Patient not found"));
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found"));
+
+        Diagnosis diagnosis = new Diagnosis();
+        diagnosis.setName(diagnosisName);
+        diagnosis.setDescription(description);
+        diagnosis.setPatient(patient);
+        diagnosis.setDoctor(doctor);
+
+        logger.info("Recording diagnosis '{}' for patient {}", diagnosisName, patientId);
+        return diagnosisRepository.save(diagnosis);
+    }
+
+    @Transactional(readOnly = true)
+    public Optional<Diagnosis> getDiagnosisById(Long diagnosisId) {
+
+        if (diagnosisId == null || diagnosisId <= 0)
+            throw new IllegalArgumentException("Diagnosis ID must be valid");
+
+        return diagnosisRepository.findById(diagnosisId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Diagnosis> getDiagnosesForPatient(Long patientId) {
+
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Patient ID must be valid");
+
+        if (!patientRepository.existsById(patientId))
+            throw new RuntimeException("Patient not found");
+
+        return diagnosisRepository.findByPatientPatientId(patientId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Diagnosis> getDiagnosesByDoctor(Long doctorId) {
+
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Doctor ID must be valid");
+
+        if (!doctorRepository.existsById(doctorId))
+            throw new RuntimeException("Doctor not found");
+
+        return diagnosisRepository.findByDoctorDoctorId(doctorId);
+    }
+
+
+    @Transactional
+    public Diagnosis updateDiagnosis(Long diagnosisId,
+                                     String diagnosisName,
+                                     String description) {
+
+        if (diagnosisId == null || diagnosisId <= 0)
+            throw new IllegalArgumentException("Diagnosis ID must be valid");
+
+        Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)
+                .orElseThrow(() -> new RuntimeException("Diagnosis not found"));
+
+        if (diagnosisName != null && !diagnosisName.isBlank())
+            diagnosis.setName(diagnosisName);
+
+        if (description != null)
+            diagnosis.setDescription(description);
+
+        return diagnosisRepository.save(diagnosis);
+    }
+}
Index: backend/src/main/java/medora/service/DoctorService.java
===================================================================
--- backend/src/main/java/medora/service/DoctorService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/DoctorService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,189 @@
+package medora.service;
+
+import medora.models.domain.Departments;
+import medora.models.domain.Doctors;
+import medora.repository.DepartmentRepository;
+import medora.repository.DoctorRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * DoctorService handles doctor profile and specialization operations.
+ * UC024 – View Doctors by Department
+ * UC025 – View Doctor Profile
+ */
+@Service
+public class DoctorService {
+
+    private static final Logger logger = LoggerFactory.getLogger(DoctorService.class);
+
+    private final DoctorRepository doctorRepository;
+    private final DepartmentRepository departmentRepository;
+
+    public DoctorService(DoctorRepository doctorRepository,
+                         DepartmentRepository departmentRepository) {
+        this.doctorRepository = doctorRepository;
+        this.departmentRepository = departmentRepository;
+    }
+
+    /**
+     * UC025 – View Doctor Profile
+     */
+    @Transactional(readOnly = true)
+    public Doctors getDoctorById(Long doctorId) {
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        logger.info("Fetching doctor with ID: {}", doctorId);
+
+        return doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found with ID: " + doctorId));
+    }
+
+
+    @Transactional(readOnly = true)
+    public Doctors getDoctorByEmail(String emailAddress) {
+        if (emailAddress == null || emailAddress.isBlank()) {
+            throw new IllegalArgumentException("Email cannot be null or empty");
+        }
+
+        logger.info("Fetching doctor with email: {}", emailAddress);
+
+        return doctorRepository.findByEmailAddress(emailAddress)
+                .orElseThrow(() -> new RuntimeException("Doctor not found with email: " + emailAddress));
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Doctors> getDoctorsByDepartment(Long departmentId) {
+        if (departmentId == null || departmentId <= 0) {
+            throw new IllegalArgumentException("Department ID must be valid");
+        }
+
+        departmentRepository.findById(departmentId)
+                .orElseThrow(() -> new RuntimeException("Department not found with ID: " + departmentId));
+
+        logger.info("Fetching doctors for department ID: {}", departmentId);
+
+        return doctorRepository.findByDepartmentDepartmentId(departmentId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Doctors> getDoctorsBySpecialization(Long specializationId) {
+        if (specializationId == null || specializationId <= 0) {
+            throw new IllegalArgumentException("Specialization ID must be valid");
+        }
+
+        logger.info("Fetching doctors with specialization ID: {}", specializationId);
+
+        return doctorRepository.findBySpecializationSpecializationId(specializationId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Doctors> getDoctorsByLevel(Long levelId) {
+        if (levelId == null || levelId <= 0) {
+            throw new IllegalArgumentException("Doctor level ID must be valid");
+        }
+
+        logger.info("Fetching doctors with level ID: {}", levelId);
+
+        return doctorRepository.findByLevelLevelId(levelId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Doctors> getAllDoctors() {
+        logger.info("Fetching all doctors");
+        return doctorRepository.findAll();
+    }
+
+
+    @Transactional
+    public Doctors createDoctor(Doctors doctor) {
+
+        if (doctor == null) {
+            throw new IllegalArgumentException("Doctor cannot be null");
+        }
+
+        if (doctor.getFirstName() == null || doctor.getFirstName().isBlank()) {
+            throw new IllegalArgumentException("Doctor first name is required");
+        }
+
+        if (doctor.getLastName() == null || doctor.getLastName().isBlank()) {
+            throw new IllegalArgumentException("Doctor last name is required");
+        }
+
+        if (doctor.getEmailAddress() == null || doctor.getEmailAddress().isBlank()) {
+            throw new IllegalArgumentException("Doctor email is required");
+        }
+
+        if (doctor.getDepartment() == null || doctor.getDepartment().getDepartmentId() == null) {
+            throw new IllegalArgumentException("Doctor department is required");
+        }
+
+        // uniqueness check
+        if (doctorRepository.findByEmailAddress(doctor.getEmailAddress()).isPresent()) {
+            throw new RuntimeException("Doctor with this email already exists");
+        }
+
+        // validate department exists
+        Departments department = departmentRepository.findById(
+                doctor.getDepartment().getDepartmentId()
+        ).orElseThrow(() -> new RuntimeException("Department not found"));
+
+        doctor.setDepartment(department);
+
+        logger.info("Creating new doctor: {} {}", doctor.getFirstName(), doctor.getLastName());
+
+        return doctorRepository.save(doctor);
+    }
+
+
+    @Transactional
+    public Doctors updateDoctor(Long doctorId, Doctors doctorDetails) {
+
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found with ID: " + doctorId));
+
+        if (doctorDetails.getFirstName() != null && !doctorDetails.getFirstName().isBlank()) {
+            doctor.setFirstName(doctorDetails.getFirstName());
+        }
+
+        if (doctorDetails.getLastName() != null && !doctorDetails.getLastName().isBlank()) {
+            doctor.setLastName(doctorDetails.getLastName());
+        }
+
+        if (doctorDetails.getDepartment() != null &&
+                doctorDetails.getDepartment().getDepartmentId() != null) {
+
+            Departments dept = departmentRepository.findById(
+                    doctorDetails.getDepartment().getDepartmentId()
+            ).orElseThrow(() -> new RuntimeException("Department not found"));
+
+            doctor.setDepartment(dept);
+        }
+
+        if (doctorDetails.getSpecialization() != null) {
+            doctor.setSpecialization(doctorDetails.getSpecialization());
+        }
+
+        if (doctorDetails.getLevel() != null) {
+            doctor.setLevel(doctorDetails.getLevel());
+        }
+
+        logger.info("Updating doctor with ID: {}", doctorId);
+
+        return doctorRepository.save(doctor);
+    }
+}
Index: backend/src/main/java/medora/service/LabService.java
===================================================================
--- backend/src/main/java/medora/service/LabService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/LabService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,212 @@
+package medora.service;
+
+import medora.models.domain.*;
+import medora.repository.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * LabService handles lab test and lab result operations.
+ * UC013 – Record Lab Test Request
+ * UC014 – Store Lab Results
+ * UC015 – Link Medical Data to Medical Record
+ */
+@Service
+public class LabService {
+
+    private static final Logger logger = LoggerFactory.getLogger(LabService.class);
+
+    private final LabTestRepository labTestRepository;
+    private final LabResultsRepository labResultsRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+    private final MedicalRecordLabResultRepository medicalRecordLabResultRepository;
+    private final PerformedLabTestRepository performedLabTestRepository;
+    private final PatientRepository patientRepository;
+    private final DoctorRepository doctorRepository;
+    private final LabTechnicianRepository labTechnicianRepository;
+
+    public LabService(LabTestRepository labTestRepository,
+                      LabResultsRepository labResultsRepository,
+                      MedicalRecordRepository medicalRecordRepository,
+                      MedicalRecordLabResultRepository medicalRecordLabResultRepository,
+                      PerformedLabTestRepository performedLabTestRepository,
+                      PatientRepository patientRepository,
+                      DoctorRepository doctorRepository,
+                      LabTechnicianRepository labTechnicianRepository) {
+        this.labTestRepository = labTestRepository;
+        this.labResultsRepository = labResultsRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+        this.medicalRecordLabResultRepository = medicalRecordLabResultRepository;
+        this.performedLabTestRepository = performedLabTestRepository;
+        this.patientRepository = patientRepository;
+        this.doctorRepository = doctorRepository;
+        this.labTechnicianRepository = labTechnicianRepository;
+    }
+
+    // LAB TEST
+
+    @Transactional
+    public LabTests requestLabTest(String testName, String description,
+                                   java.math.BigDecimal cost) {
+
+        if (testName == null || testName.isBlank())
+            throw new IllegalArgumentException("Lab test name is required");
+
+        if (cost == null || cost.compareTo(java.math.BigDecimal.ZERO) < 0)
+            throw new IllegalArgumentException("Invalid cost");
+
+        LabTests labTest = new LabTests();
+        labTest.setTestName(testName);
+        labTest.setDescription(description);
+        labTest.setCost(cost);
+
+        return labTestRepository.save(labTest);
+    }
+
+    @Transactional(readOnly = true)
+    public Optional<LabTests> getLabTestById(Long id) {
+
+        if (id == null || id <= 0)
+            throw new IllegalArgumentException("Invalid lab test ID");
+
+        return labTestRepository.findById(id);
+    }
+
+    @Transactional(readOnly = true)
+    public List<LabTests> getAllLabTests() {
+        return labTestRepository.findAll();
+    }
+
+    @Transactional
+    public LabTests updateLabTest(Long id, String name,
+                                  String description,
+                                  java.math.BigDecimal cost) {
+
+        LabTests test = labTestRepository.findById(id)
+                .orElseThrow(() -> new RuntimeException("Lab test not found"));
+
+        if (name != null && !name.isBlank())
+            test.setTestName(name);
+
+        if (description != null)
+            test.setDescription(description);
+
+        if (cost != null && cost.compareTo(java.math.BigDecimal.ZERO) >= 0)
+            test.setCost(cost);
+
+        return labTestRepository.save(test);
+    }
+
+    //  LAB TEST REQUESTS (UC013)
+
+    @Transactional
+    public PerformedLabTests requestLabTestForPatient(Long patientId,
+                                                      Long doctorId,
+                                                      Long testId,
+                                                      LocalDate testDate,
+                                                      String notes) {
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Invalid patient ID");
+
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Invalid doctor ID");
+
+        if (testId == null || testId <= 0)
+            throw new IllegalArgumentException("Invalid test ID");
+
+        Patient patient = patientRepository.findById(patientId)
+                .orElseThrow(() -> new RuntimeException("Patient not found"));
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found"));
+
+        LabTests test = labTestRepository.findById(testId)
+                .orElseThrow(() -> new RuntimeException("Lab test not found"));
+
+        PerformedLabTests performedTest = new PerformedLabTests();
+        performedTest.setPatient(patient);
+        performedTest.setDoctor(doctor);
+        performedTest.setLabTest(test);
+        performedTest.setTestDate(testDate != null ? testDate : LocalDate.now());
+        performedTest.setNotes(notes);
+
+        logger.info("Lab test {} requested for patient {} by doctor {}", testId, patientId, doctorId);
+        return performedLabTestRepository.save(performedTest);
+    }
+
+    @Transactional(readOnly = true)
+    public List<PerformedLabTests> getLabTestRequestsForPatient(Long patientId) {
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Invalid patient ID");
+
+        if (!patientRepository.existsById(patientId))
+            throw new RuntimeException("Patient not found");
+
+        return performedLabTestRepository.findByPatientPatientId(patientId);
+    }
+
+    @Transactional(readOnly = true)
+    public List<PerformedLabTests> getLabTestRequestsByDoctor(Long doctorId) {
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Invalid doctor ID");
+
+        if (!doctorRepository.existsById(doctorId))
+            throw new RuntimeException("Doctor not found");
+
+        return performedLabTestRepository.findByDoctorDoctorId(doctorId);
+    }
+
+    //  LAB RESULTS (UC014, UC015)
+
+    @Transactional
+    public MedicalRecordLabResults storeLabResult(Long medicalRecordId,
+                                                  Long testId,
+                                                  String results,
+                                                  LocalDate resultDate) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Invalid medical record ID");
+
+        if (testId == null || testId <= 0)
+            throw new IllegalArgumentException("Invalid test ID");
+
+        if (results == null || results.isBlank())
+            throw new IllegalArgumentException("Results required");
+
+        MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+        LabTests labTest = labTestRepository.findById(testId)
+                .orElseThrow(() -> new RuntimeException("Lab test not found"));
+
+        LabResults labResult = new LabResults();
+        labResult.setResults(results);
+        labResult.setResultDate(resultDate);
+        labResult.setLabTest(labTest);
+
+        LabResults saved = labResultsRepository.save(labResult);
+
+
+        MedicalRecordLabResults link = new MedicalRecordLabResults();
+        link.setMedicalRecord(medicalRecord);
+        link.setLabResult(saved);
+
+        logger.info("Stored lab result {} for medical record {}", saved.getResultId(), medicalRecordId);
+        return medicalRecordLabResultRepository.save(link);
+    }
+
+    @Transactional(readOnly = true)
+    public List<MedicalRecordLabResults> getLabResultsForMedicalRecord(Long medicalRecordId) {
+
+        if (!medicalRecordRepository.existsById(medicalRecordId))
+            throw new RuntimeException("Medical record not found");
+
+        return medicalRecordLabResultRepository.findByMedicalRecordRecordId(medicalRecordId);
+    }
+}
Index: backend/src/main/java/medora/service/MedicalObservationsService.java
===================================================================
--- backend/src/main/java/medora/service/MedicalObservationsService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/MedicalObservationsService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,158 @@
+package medora.service;
+
+
+import medora.models.domain.*;
+import medora.repository.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * MedicalObservationService handles medical observations (symptoms and allergies).
+ * UC010 – Record Symptoms
+ * UC011 – Record Allergies
+ * UC015 – Link Medical Data to Medical Record
+ */
+@Service
+public class MedicalObservationsService {
+
+    private static final Logger logger = LoggerFactory.getLogger(MedicalObservationsService.class);
+
+    private final SymptomRepository symptomRepository;
+    private final AllergyRepository allergyRepository;
+    private final MedicalRecordSymptomRepository medicalRecordSymptomRepository;
+    private final MedicalRecordAllergyRepository medicalRecordAllergyRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+
+    public MedicalObservationsService(SymptomRepository symptomRepository,
+                                     AllergyRepository allergyRepository,
+                                     MedicalRecordSymptomRepository medicalRecordSymptomRepository,
+                                     MedicalRecordAllergyRepository medicalRecordAllergyRepository,
+                                     MedicalRecordRepository medicalRecordRepository) {
+        this.symptomRepository = symptomRepository;
+        this.allergyRepository = allergyRepository;
+        this.medicalRecordSymptomRepository = medicalRecordSymptomRepository;
+        this.medicalRecordAllergyRepository = medicalRecordAllergyRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+    }
+
+    // ================= SYMPTOMS OPERATIONS =================
+
+    /**
+     * UC010 – Record Symptoms
+     * Record a symptom for a patient's medical record
+     */
+    @Transactional
+    public MedicalRecordSymptoms recordSymptom(Long medicalRecordId, Long symptomId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (symptomId == null || symptomId <= 0) {
+            throw new IllegalArgumentException("Symptom ID must be valid");
+        }
+
+        MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found with ID: " + medicalRecordId));
+
+        Symptoms symptom = symptomRepository.findById(symptomId)
+                .orElseThrow(() -> new RuntimeException("Symptom not found with ID: " + symptomId));
+
+
+        if (medicalRecordSymptomRepository.existsByMedicalRecordRecordIdAndSymptomSymptomId(
+                medicalRecordId, symptomId)) {
+            throw new RuntimeException("Symptom already recorded for this medical record");
+        }
+
+        MedicalRecordSymptoms recordSymptom = new MedicalRecordSymptoms();
+        recordSymptom.setMedicalRecord(medicalRecord);
+        recordSymptom.setSymptom(symptom);
+
+        logger.info("Recording symptom ID: {} for medical record ID: {}", symptomId, medicalRecordId);
+        return medicalRecordSymptomRepository.save(recordSymptom);
+    }
+
+    /**
+     * Get all symptoms for a patient's medical record
+     */
+    @Transactional(readOnly = true)
+    public List<MedicalRecordSymptoms> getSymptomsForMedicalRecord(Long medicalRecordId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+
+        if (!medicalRecordRepository.existsById(medicalRecordId)) {
+            throw new RuntimeException("Medical record not found with ID: " + medicalRecordId);
+        }
+
+        logger.info("Fetching symptoms for medical record ID: {}", medicalRecordId);
+        return medicalRecordSymptomRepository.findByMedicalRecordRecordId(medicalRecordId);
+    }
+
+   
+    // For ALLERGIES
+
+    /**
+     * UC011 – Record Allergies
+     * Record an allergy for a patient's medical record
+     */
+    @Transactional
+    public MedicalRecordAllergies recordAllergy(Long medicalRecordId, Long allergyId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (allergyId == null || allergyId <= 0) {
+            throw new IllegalArgumentException("Allergy ID must be valid");
+        }
+
+        MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found with ID: " + medicalRecordId));
+
+        Allergies allergy = allergyRepository.findById(allergyId)
+                .orElseThrow(() -> new RuntimeException("Allergy not found with ID: " + allergyId));
+
+        // Check if allergy is already recorded
+        if (medicalRecordAllergyRepository.existsByMedicalRecordRecordIdAndAllergyAllergyId(
+                medicalRecordId, allergyId)) {
+            throw new RuntimeException("Allergy already recorded for this medical record");
+        }
+
+        MedicalRecordAllergies recordAllergy = new MedicalRecordAllergies();
+        recordAllergy.setMedicalRecord(medicalRecord);
+        recordAllergy.setAllergy(allergy);
+
+        logger.info("Recording allergy ID: {} for medical record ID: {}", allergyId, medicalRecordId);
+        return medicalRecordAllergyRepository.save(recordAllergy);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<MedicalRecordAllergies> getAllergiesForMedicalRecord(Long medicalRecordId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+
+        if (!medicalRecordRepository.existsById(medicalRecordId)) {
+            throw new RuntimeException("Medical record not found with ID: " + medicalRecordId);
+        }
+
+        logger.info("Fetching allergies for medical record ID: {}", medicalRecordId);
+        return medicalRecordAllergyRepository.findByMedicalRecordRecordId(medicalRecordId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Symptoms> getAllSymptoms() {
+        logger.info("Fetching all symptoms");
+        return symptomRepository.findAll();
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Allergies> getAllAllergies() {
+        logger.info("Fetching all allergies");
+        return allergyRepository.findAll();
+    }
+}
Index: backend/src/main/java/medora/service/MedicalRecordService.java
===================================================================
--- backend/src/main/java/medora/service/MedicalRecordService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/MedicalRecordService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,289 @@
+package medora.service;
+
+import medora.models.domain.*;
+import medora.models.domain.id.MedicalRecordAllergyId;
+import medora.models.domain.id.MedicalRecordLabResultId;
+import medora.models.domain.id.MedicalRecordProcedureId;
+import medora.models.domain.id.MedicalRecordSymptomId;
+import medora.repository.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class MedicalRecordService {
+
+    private static final Logger logger = LoggerFactory.getLogger(MedicalRecordService.class);
+
+    private final MedicalRecordRepository medicalRecordRepository;
+    private final PatientRepository patientRepository;
+    private final MedicalRecordProcedureRepository medicalRecordProcedureRepository;
+    private final MedicalRecordLabResultRepository medicalRecordLabResultRepository;
+    private final MedicalRecordAllergyRepository medicalRecordAllergyRepository;
+    private final MedicalRecordSymptomRepository medicalRecordSymptomRepository;
+    private final SymptomRepository symptomRepository;
+    private final AllergyRepository allergyRepository;
+
+    public MedicalRecordService(MedicalRecordRepository medicalRecordRepository,
+                                PatientRepository patientRepository,
+                                MedicalRecordProcedureRepository medicalRecordProcedureRepository,
+                                MedicalRecordLabResultRepository medicalRecordLabResultRepository,
+                                MedicalRecordAllergyRepository medicalRecordAllergyRepository,
+                                MedicalRecordSymptomRepository medicalRecordSymptomRepository,
+                                SymptomRepository symptomRepository,
+                                AllergyRepository allergyRepository) {
+        this.medicalRecordRepository = medicalRecordRepository;
+        this.patientRepository = patientRepository;
+        this.medicalRecordProcedureRepository = medicalRecordProcedureRepository;
+        this.medicalRecordLabResultRepository = medicalRecordLabResultRepository;
+        this.medicalRecordAllergyRepository = medicalRecordAllergyRepository;
+        this.medicalRecordSymptomRepository = medicalRecordSymptomRepository;
+        this.symptomRepository = symptomRepository;
+        this.allergyRepository = allergyRepository;
+    }
+
+    // UC008 – Access Medical Record
+    @Transactional(readOnly = true)
+    public Optional<MedicalRecord> getMedicalRecordById(Long recordId) {
+        if (recordId == null || recordId <= 0) {
+            throw new IllegalArgumentException("Record ID must be valid");
+        }
+
+        logger.info("Fetching medical record ID: {}", recordId);
+        return medicalRecordRepository.findById(recordId);
+    }
+
+    // UC005 – View Medical Record
+    @Transactional(readOnly = true)
+    public Optional<MedicalRecord> getMedicalRecordByPatientId(Long patientId) {
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+
+        if (!patientRepository.existsById(patientId)) {
+            throw new RuntimeException("Patient not found");
+        }
+
+        logger.info("Fetching medical record for patient ID: {}", patientId);
+        return medicalRecordRepository.findByPatientPatientId(patientId);
+    }
+
+    // UC026 – Search Medical Records
+    @Transactional(readOnly = true)
+    public List<MedicalRecord> searchMedicalRecords(
+            String patientName,
+            String embg,
+            String diagnosisName,
+            LocalDate startDate,
+            LocalDate endDate
+    ) {
+        logger.info("Searching medical records with filters");
+
+        return medicalRecordRepository.searchMedicalRecords(
+                patientName,
+                embg,
+                diagnosisName,
+                startDate,
+                endDate
+        );
+    }
+
+    // UC015 – Link Medical Data to Medical Record
+    @Transactional
+    public MedicalRecord linkMedicalData(Long recordId, MedicalRecord updatedData) {
+
+        if (recordId == null || recordId <= 0) {
+            throw new IllegalArgumentException("Record ID must be valid");
+        }
+
+        if (updatedData == null) {
+            throw new IllegalArgumentException("Updated data cannot be null");
+        }
+
+        MedicalRecord record = medicalRecordRepository.findById(recordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+
+        try {
+            // Procedures
+            try {
+                java.lang.reflect.Method getProcs = updatedData.getClass().getMethod("getProcedures");
+                Object procsObj = getProcs.invoke(updatedData);
+                if (procsObj instanceof Iterable<?> procs) {
+                    for (Object p : procs) {
+                        Long procId = extractId(p, "getProcedureId", "getId");
+                        if (procId == null) continue;
+                        MedicalRecordProcedureId mrpId = new MedicalRecordProcedureId(recordId, procId);
+                        if (medicalRecordProcedureRepository.findById(mrpId).isEmpty()) {
+                            medicalRecordProcedureRepository.linkProcedure(recordId, procId);
+                        }
+                    }
+                }
+            } catch (NoSuchMethodException ignored) {
+
+            }
+
+            // LabResults
+            try {
+                java.lang.reflect.Method getLabs = updatedData.getClass().getMethod("getLabResults");
+                Object labsObj = getLabs.invoke(updatedData);
+                if (labsObj instanceof Iterable<?> labs) {
+                    for (Object lr : labs) {
+                        Long lrId = extractId(lr, "getResultId", "getId");
+                        if (lrId == null) continue;
+                        MedicalRecordLabResultId mrlId = new MedicalRecordLabResultId(recordId, lrId);
+                        if (medicalRecordLabResultRepository.findById(mrlId).isEmpty()) {
+                            medicalRecordLabResultRepository.linkLabResult(recordId, lrId);
+                        }
+                    }
+                }
+            } catch (NoSuchMethodException ignored) {
+
+            }
+
+            // Allergies
+            try {
+                java.lang.reflect.Method getAllergies = updatedData.getClass().getMethod("getAllergies");
+                Object allergiesObj = getAllergies.invoke(updatedData);
+                if (allergiesObj instanceof Iterable<?> allergies) {
+                    for (Object allergy : allergies) {
+                        Long allergyId = extractId(allergy, "getAllergyId", "getId");
+                        if (allergyId == null) continue;
+                        MedicalRecordAllergyId mraId = new MedicalRecordAllergyId(recordId, allergyId);
+                        if (medicalRecordAllergyRepository.findById(mraId).isEmpty()) {
+
+                            MedicalRecordAllergies allergyJoin =
+                                new MedicalRecordAllergies();
+                            allergyJoin.setMedicalRecord(record);
+
+                            logger.debug("Allergy {} linking deferred (missing allergyRepo)", allergyId);
+                        }
+                    }
+                }
+            } catch (NoSuchMethodException ignored) {
+
+            }
+
+            // Symptoms
+            try {
+                java.lang.reflect.Method getSymptoms = updatedData.getClass().getMethod("getSymptoms");
+                Object symptomsObj = getSymptoms.invoke(updatedData);
+                if (symptomsObj instanceof Iterable<?> symptoms) {
+                    for (Object symptom : symptoms) {
+                        Long symptomId = extractId(symptom, "getSymptomId", "getId");
+                        if (symptomId == null) continue;
+                        MedicalRecordSymptomId mrsId = new MedicalRecordSymptomId(recordId, symptomId);
+                        if (medicalRecordSymptomRepository.findById(mrsId).isEmpty()) {
+                            logger.debug("Symptom {} linking deferred (missing symptomRepo)", symptomId);
+                        }
+                    }
+                }
+            } catch (NoSuchMethodException ignored) {
+
+            }
+        } catch (ReflectiveOperationException e) {
+
+            throw new RuntimeException("Failed to link medical data via reflection", e);
+        }
+
+        logger.info("Linked medical data to record ID: {}", recordId);
+        return medicalRecordRepository.save(record);
+    }
+
+    @Transactional
+    public MedicalRecord updateMedicalRecord(Long recordId, MedicalRecord recordDetails) {
+
+        if (recordId == null || recordId <= 0) {
+            throw new IllegalArgumentException("Record ID must be valid");
+        }
+
+        MedicalRecord record = medicalRecordRepository.findById(recordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+        if (recordDetails != null && recordDetails.getPatient() != null) {
+            record.setPatient(recordDetails.getPatient());
+        }
+
+        logger.info("Updating medical record ID: {}", recordId);
+        return medicalRecordRepository.save(record);
+    }
+
+    @Transactional(readOnly = true)
+    public List<MedicalRecord> getAllMedicalRecords() {
+        return medicalRecordRepository.findAll();
+    }
+
+    @Transactional
+    public MedicalRecord recordSymptom(Long medicalRecordId, Long symptomId, String severity) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (symptomId == null || symptomId <= 0) {
+            throw new IllegalArgumentException("Symptom ID must be valid");
+        }
+
+        MedicalRecord record = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+        Symptoms symptom = symptomRepository.findById(symptomId)
+                .orElseThrow(() -> new RuntimeException("Symptom not found"));
+
+        if (medicalRecordSymptomRepository.existsByMedicalRecordRecordIdAndSymptomSymptomId(medicalRecordId, symptomId)) {
+            throw new RuntimeException("Symptom already recorded for this medical record");
+        }
+
+        logger.info("Recording symptom {} for medical record {}", symptomId, medicalRecordId);
+
+        MedicalRecordSymptoms mrs = new MedicalRecordSymptoms(record, symptom, severity);
+        medicalRecordSymptomRepository.save(mrs);
+
+        return record;
+    }
+
+    @Transactional
+    public MedicalRecord recordAllergy(Long medicalRecordId, Long allergyId, String reaction, String severity) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (allergyId == null || allergyId <= 0) {
+            throw new IllegalArgumentException("Allergy ID must be valid");
+        }
+
+        MedicalRecord record = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+        Allergies allergy = allergyRepository.findById(allergyId)
+                .orElseThrow(() -> new RuntimeException("Allergy not found"));
+
+        if (medicalRecordAllergyRepository.existsByMedicalRecordRecordIdAndAllergyAllergyId(medicalRecordId, allergyId)) {
+            throw new RuntimeException("Allergy already recorded for this medical record");
+        }
+
+        logger.info("Recording allergy {} for medical record {}", allergyId, medicalRecordId);
+
+        MedicalRecordAllergies mra = new MedicalRecordAllergies(record, allergy, reaction, severity);
+        medicalRecordAllergyRepository.save(mra);
+
+        return record;
+    }
+
+
+    private Long extractId(Object obj, String... candidateGetters) {
+        if (obj == null) return null;
+        for (String getter : candidateGetters) {
+            try {
+                java.lang.reflect.Method m = obj.getClass().getMethod(getter);
+                Object val = m.invoke(obj);
+                if (val instanceof Number) return ((Number) val).longValue();
+            } catch (ReflectiveOperationException ignored) {
+
+            }
+        }
+        return null;
+    }
+}
Index: backend/src/main/java/medora/service/MedicalReportService.java
===================================================================
--- backend/src/main/java/medora/service/MedicalReportService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/MedicalReportService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,378 @@
+package medora.service;
+
+import medora.dto.*;
+import medora.models.domain.*;
+import medora.repository.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * MedicalReportService handles medical report operations.
+ * UC018 – Create Medical Report
+ * OPTIONAL - Use only if needed
+ */
+@Service
+public class MedicalReportService {
+
+    private static final Logger logger = LoggerFactory.getLogger(MedicalReportService.class);
+
+    private final MedicalReportRepository medicalReportRepository;
+    private final DoctorRepository doctorRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+    private final DiagnosisRepository diagnosisRepository;
+    private final PrescriptionMedicalRecordRepository prescriptionMedicalRecordRepository;
+    private final MedicalRecordAllergyRepository medicalRecordAllergyRepository;
+    private final MedicalRecordSymptomRepository symptomRepository;
+    private final ReportDiagnosisRepository reportDiagnosisRepository;
+    private final ReportPrescriptionRepository reportPrescriptionRepository;
+    private final ReportAllergyRepository reportAllergyRepository;
+    private final ReportSymptomRepository reportSymptomRepository;
+    private final PrescriptionRepository prescriptionRepository;
+    private final AllergyRepository allergyRepository;
+    private final SymptomRepository symptomDbRepository;
+
+    public MedicalReportService(MedicalReportRepository medicalReportRepository,
+                                DoctorRepository doctorRepository,
+                                MedicalRecordRepository medicalRecordRepository,
+                                DiagnosisRepository diagnosisRepository,
+                                PrescriptionMedicalRecordRepository prescriptionMedicalRecordRepository,
+                                MedicalRecordAllergyRepository medicalRecordAllergyRepository,
+                                MedicalRecordSymptomRepository symptomRepository,
+                                ReportDiagnosisRepository reportDiagnosisRepository,
+                                ReportPrescriptionRepository reportPrescriptionRepository,
+                                ReportAllergyRepository reportAllergyRepository,
+                                ReportSymptomRepository reportSymptomRepository,
+                                PrescriptionRepository prescriptionRepository,
+                                AllergyRepository allergyRepository,
+                                SymptomRepository symptomDbRepository) {
+        this.medicalReportRepository = medicalReportRepository;
+        this.doctorRepository = doctorRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+        this.diagnosisRepository = diagnosisRepository;
+        this.prescriptionMedicalRecordRepository = prescriptionMedicalRecordRepository;
+        this.medicalRecordAllergyRepository = medicalRecordAllergyRepository;
+        this.symptomRepository = symptomRepository;
+        this.reportDiagnosisRepository = reportDiagnosisRepository;
+        this.reportPrescriptionRepository = reportPrescriptionRepository;
+        this.reportAllergyRepository = reportAllergyRepository;
+        this.reportSymptomRepository = reportSymptomRepository;
+        this.prescriptionRepository = prescriptionRepository;
+        this.allergyRepository = allergyRepository;
+        this.symptomDbRepository = symptomDbRepository;
+    }
+
+    /**
+     * UC018 – Create Medical Report
+     * Create a medical report describing a patient's visit and condition
+     */
+    @Transactional
+    public MedicalReport createMedicalReport(Long doctorId, Long medicalRecordId, String description,
+                                             LocalDate reportDate) {
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (description == null || description.isBlank()) {
+            throw new IllegalArgumentException("Report description is required");
+        }
+        if (reportDate == null) {
+            throw new IllegalArgumentException("Report date is required");
+        }
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found with ID: " + doctorId));
+
+        MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found with ID: " + medicalRecordId));
+
+        MedicalReport report = new MedicalReport();
+        // Let JPA auto-generate the ID using the sequence
+        report.setReportId(null);
+        report.setDoctor(doctor);
+        report.setMedicalRecord(medicalRecord);
+        report.setDescription(description);
+        report.setReportDate(reportDate);
+
+        logger.info("Creating medical report for medical record ID: {} by doctor ID: {}",
+                medicalRecordId, doctorId);
+        return medicalReportRepository.save(report);
+    }
+
+    /**
+     * Create a medical report with selected diagnoses, prescriptions, allergies, and symptoms
+     */
+    @Transactional
+    public MedicalReport createMedicalReportWithSelectedItems(Long doctorId, Long medicalRecordId,
+            String description, LocalDate reportDate,
+            List<Long> selectedDiagnosisIds, List<Long> selectedPrescriptionIds,
+            List<Long> selectedAllergyIds, List<Long> selectedSymptomIds) {
+
+        // Create the base report
+        MedicalReport report = createMedicalReport(doctorId, medicalRecordId, description, reportDate);
+
+        // Store selected diagnoses
+        if (selectedDiagnosisIds != null) {
+            for (Long diagnosisId : selectedDiagnosisIds) {
+                Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)
+                        .orElseThrow(() -> new RuntimeException("Diagnosis not found with ID: " + diagnosisId));
+                ReportDiagnosis reportDiagnosis = new ReportDiagnosis(report, diagnosis);
+                reportDiagnosisRepository.save(reportDiagnosis);
+            }
+        }
+
+        // Store selected prescriptions
+        if (selectedPrescriptionIds != null) {
+            for (Long prescriptionId : selectedPrescriptionIds) {
+                Prescriptions prescription = prescriptionRepository.findById(prescriptionId)
+                        .orElseThrow(() -> new RuntimeException("Prescription not found with ID: " + prescriptionId));
+                ReportPrescription reportPrescription = new ReportPrescription(report, prescription);
+                reportPrescriptionRepository.save(reportPrescription);
+            }
+        }
+
+        // Store selected allergies
+        if (selectedAllergyIds != null) {
+            for (Long allergyId : selectedAllergyIds) {
+                Allergies allergy = allergyRepository.findById(allergyId)
+                        .orElseThrow(() -> new RuntimeException("Allergy not found with ID: " + allergyId));
+                ReportAllergy reportAllergy = new ReportAllergy(report, allergy);
+                reportAllergyRepository.save(reportAllergy);
+            }
+        }
+
+        // Store selected symptoms
+        if (selectedSymptomIds != null) {
+            for (Long symptomId : selectedSymptomIds) {
+                Symptoms symptom = symptomDbRepository.findById(symptomId)
+                        .orElseThrow(() -> new RuntimeException("Symptom not found with ID: " + symptomId));
+                ReportSymptom reportSymptom = new ReportSymptom(report, symptom);
+                reportSymptomRepository.save(reportSymptom);
+            }
+        }
+
+        logger.info("Created medical report with selected items for record ID: {}", medicalRecordId);
+        return report;
+    }
+
+    /**
+     * Get medical report by ID
+     */
+    @Transactional(readOnly = true)
+    public Optional<MedicalReport> getMedicalReportById(Long reportId) {
+        if (reportId == null || reportId <= 0) {
+            throw new IllegalArgumentException("Report ID must be valid");
+        }
+        logger.info("Fetching medical report with ID: {}", reportId);
+        return medicalReportRepository.findById(reportId);
+    }
+
+    /**
+     * Get all reports for a medical record
+     */
+    @Transactional(readOnly = true)
+    public List<MedicalReport> getReportsForMedicalRecord(Long medicalRecordId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+
+        if (!medicalRecordRepository.existsById(medicalRecordId)) {
+            throw new RuntimeException("Medical record not found with ID: " + medicalRecordId);
+        }
+
+        logger.info("Fetching reports for medical record ID: {}", medicalRecordId);
+        return medicalReportRepository.findByMedicalRecordRecordId(medicalRecordId);
+    }
+
+    /**
+     * Get all reports created by a doctor
+     */
+    @Transactional(readOnly = true)
+    public List<MedicalReport> getReportsByDoctor(Long doctorId) {
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        if (!doctorRepository.existsById(doctorId)) {
+            throw new RuntimeException("Doctor not found with ID: " + doctorId);
+        }
+
+        logger.info("Fetching reports created by doctor ID: {}", doctorId);
+        return medicalReportRepository.findByDoctorDoctorId(doctorId);
+    }
+
+    /**
+     * Update medical report
+     */
+    @Transactional
+    public MedicalReport updateMedicalReport(Long reportId, String description) {
+        if (reportId == null || reportId <= 0) {
+            throw new IllegalArgumentException("Report ID must be valid");
+        }
+
+        MedicalReport report = medicalReportRepository.findById(reportId)
+                .orElseThrow(() -> new RuntimeException("Medical report not found with ID: " + reportId));
+
+        if (description != null && !description.isBlank()) {
+            report.setDescription(description);
+        }
+
+        logger.info("Updating medical report with ID: {}", reportId);
+        return medicalReportRepository.save(report);
+    }
+
+    /**
+     * Delete medical report
+     */
+    @Transactional
+    public void deleteMedicalReport(Long reportId) {
+        if (reportId == null || reportId <= 0) {
+            throw new IllegalArgumentException("Report ID must be valid");
+        }
+
+        MedicalReport report = medicalReportRepository.findById(reportId)
+                .orElseThrow(() -> new RuntimeException("Medical report not found with ID: " + reportId));
+
+        logger.info("Deleting medical report with ID: {}", reportId);
+        medicalReportRepository.delete(report);
+    }
+
+    /**
+     * Get comprehensive medical report with all patient medical data
+     */
+    @Transactional(readOnly = true)
+    public ComprehensiveMedicalReportDTO getComprehensiveReport(Long reportId) {
+        if (reportId == null || reportId <= 0) {
+            throw new IllegalArgumentException("Report ID must be valid");
+        }
+
+        MedicalReport report = medicalReportRepository.findById(reportId)
+                .orElseThrow(() -> new RuntimeException("Medical report not found with ID: " + reportId));
+
+        return buildComprehensiveReport(report);
+    }
+
+    /**
+     * Get all comprehensive reports for a medical record
+     */
+    @Transactional(readOnly = true)
+    public List<ComprehensiveMedicalReportDTO> getComprehensiveReportsForMedicalRecord(Long medicalRecordId) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+
+        List<MedicalReport> reports = medicalReportRepository.findByMedicalRecordRecordId(medicalRecordId);
+        return reports.stream()
+                .map(this::buildComprehensiveReport)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Build a comprehensive report DTO with all medical data
+     */
+    private ComprehensiveMedicalReportDTO buildComprehensiveReport(MedicalReport report) {
+        Long medicalRecordId = report.getMedicalRecord().getRecordId();
+        Patient patient = report.getMedicalRecord().getPatient();
+
+        // Get selected diagnoses from linking table
+        List<ReportDiagnosis> reportDiagnoses = reportDiagnosisRepository.findByReportReportId(report.getReportId());
+        List<Diagnosis> diagnoses = reportDiagnoses.stream()
+                .map(ReportDiagnosis::getDiagnosis)
+                .collect(Collectors.toList());
+
+        List<DiagnosisDTO> diagnosisDTOs = diagnoses.stream()
+                .map(d -> new DiagnosisDTO(
+                        d.getDiagnosisId(),
+                        patient.getPatientId(),
+                        patient.getFirstName() + " " + patient.getLastName(),
+                        d.getDoctor().getDoctorId(),
+                        d.getDoctor().getFirstName() + " " + d.getDoctor().getLastName(),
+                        d.getName(),
+                        d.getDescription()
+                ))
+                .collect(Collectors.toList());
+
+        // Get selected prescriptions from linking table
+        List<ReportPrescription> reportPrescriptions = reportPrescriptionRepository.findByReportReportId(report.getReportId());
+        List<PrescriptionMedicalRecord> prescriptions = new java.util.ArrayList<>();
+        for (ReportPrescription rp : reportPrescriptions) {
+            // Find the corresponding PrescriptionMedicalRecord entry
+            List<PrescriptionMedicalRecord> pmr = prescriptionMedicalRecordRepository.findByMedicalRecordRecordIdAndPrescriptionPrescriptionId(
+                    medicalRecordId, rp.getPrescription().getPrescriptionId());
+            prescriptions.addAll(pmr);
+        }
+
+        List<PrescriptionDTO> prescriptionDTOs = prescriptions.stream()
+                .map(p -> new PrescriptionDTO(
+                        p.getPrescription().getPrescriptionId(),
+                        medicalRecordId,
+                        p.getPrescription().getMedicationName(),
+                        p.getDosage(),
+                        p.getFrequency(),
+                        p.getDuration(),
+                        p.getNotes()
+                ))
+                .collect(Collectors.toList());
+
+        // Get selected allergies from linking table
+        List<ReportAllergy> reportAllergies = reportAllergyRepository.findByReportReportId(report.getReportId());
+        List<MedicalRecordAllergies> allergies = new java.util.ArrayList<>();
+        for (ReportAllergy ra : reportAllergies) {
+            // Find the corresponding MedicalRecordAllergies entry
+            List<MedicalRecordAllergies> mra = medicalRecordAllergyRepository.findByMedicalRecordRecordIdAndAllergyAllergyId(
+                    medicalRecordId, ra.getAllergy().getAllergyId());
+            allergies.addAll(mra);
+        }
+
+        List<AllergyDTO> allergyDTOs = allergies.stream()
+                .map(a -> new AllergyDTO(
+                        a.getAllergy().getAllergyId(),
+                        a.getAllergy().getName(),
+                        a.getReaction(),
+                        a.getSeverity()
+                ))
+                .collect(Collectors.toList());
+
+        // Get selected symptoms from linking table
+        List<ReportSymptom> reportSymptoms = reportSymptomRepository.findByReportReportId(report.getReportId());
+        List<MedicalRecordSymptoms> symptoms = new java.util.ArrayList<>();
+        for (ReportSymptom rs : reportSymptoms) {
+            // Find the corresponding MedicalRecordSymptoms entry
+            List<MedicalRecordSymptoms> mrs = symptomRepository.findByMedicalRecordRecordIdAndSymptomSymptomId(
+                    medicalRecordId, rs.getSymptom().getSymptomId());
+            symptoms.addAll(mrs);
+        }
+
+        List<SymptomDTO> symptomDTOs = symptoms.stream()
+                .map(s -> new SymptomDTO(
+                        s.getSymptom().getSymptomId(),
+                        s.getSymptom().getName(),
+                        s.getSymptom().getDescription()
+                ))
+                .collect(Collectors.toList());
+
+        return new ComprehensiveMedicalReportDTO(
+                report.getReportId(),
+                medicalRecordId,
+                patient.getPatientId(),
+                patient.getFirstName() + " " + patient.getLastName(),
+                patient.getEmbg(),
+                report.getReportDate(),
+                report.getDoctor().getDoctorId(),
+                report.getDoctor().getFirstName() + " " + report.getDoctor().getLastName(),
+                report.getDescription(),
+                diagnosisDTOs,
+                prescriptionDTOs,
+                allergyDTOs,
+                symptomDTOs
+        );
+    }
+}
Index: backend/src/main/java/medora/service/PatientService.java
===================================================================
--- backend/src/main/java/medora/service/PatientService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/PatientService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,171 @@
+package medora.service;
+
+
+import medora.models.domain.MedicalRecord;
+import medora.models.domain.Patient;
+import medora.repository.MedicalRecordRepository;
+import medora.repository.PatientRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * PatientService handles patient profile operations.
+ * UC004 – View Patient Profile
+ * UC026 – Search Medical Records (helper)
+ */
+@Service
+public class PatientService {
+
+    private static final Logger logger = LoggerFactory.getLogger(PatientService.class);
+
+    private final PatientRepository patientRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+
+    public PatientService(PatientRepository patientRepository,
+                         MedicalRecordRepository medicalRecordRepository) {
+        this.patientRepository = patientRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+    }
+
+    /**
+     * UC004 – View Patient Profile
+     * Get patient by ID
+     */
+    @Transactional(readOnly = true)
+    public Optional<Patient> getPatientById(Long patientId) {
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+        logger.info("Fetching patient with ID: {}", patientId);
+        return patientRepository.findById(patientId);
+    }
+
+    /**
+     * UC004 – View Patient Profile
+     * Get patient by EMBG (unique identifier)
+     */
+    @Transactional(readOnly = true)
+    public Optional<Patient> getPatientByEmbg(String embg) {
+        if (embg == null || embg.isBlank()) {
+            throw new IllegalArgumentException("EMBG cannot be null or empty");
+        }
+        logger.info("Fetching patient with EMBG: {}", embg);
+        return patientRepository.findByEmbg(embg);
+    }
+
+    /**
+     * UC004 – View Patient Profile
+     * Get patient by email
+     */
+    @Transactional(readOnly = true)
+    public Optional<Patient> getPatientByEmail(String emailAddress) {
+        if (emailAddress == null || emailAddress.isBlank()) {
+            throw new IllegalArgumentException("Email cannot be null or empty");
+        }
+        logger.info("Fetching patient with email: {}", emailAddress);
+        return patientRepository.findByEmailAddress(emailAddress);
+    }
+
+    /**
+     * Get all patients
+     */
+    @Transactional(readOnly = true)
+    public List<Patient> getAllPatients() {
+        logger.info("Fetching all patients");
+        return patientRepository.findAll();
+    }
+
+    /**
+     * Create a new patient and automatically create their medical record
+     */
+    @Transactional
+    public Patient createPatient(Patient patient) {
+        if (patient == null || patient.getEmbg() == null || patient.getEmbg().isBlank()) {
+            throw new IllegalArgumentException("Patient EMBG is required");
+        }
+        if (patient.getFirstName() == null || patient.getFirstName().isBlank()) {
+            throw new IllegalArgumentException("Patient first name is required");
+        }
+        if (patient.getLastName() == null || patient.getLastName().isBlank()) {
+            throw new IllegalArgumentException("Patient last name is required");
+        }
+
+        logger.info("Creating new patient with EMBG: {}", patient.getEmbg());
+        Patient savedPatient = patientRepository.save(patient);
+
+        // Automatically create a medical record for the patient
+        try {
+            MedicalRecord medicalRecord = new MedicalRecord();
+            medicalRecord.setPatient(savedPatient);
+            medicalRecordRepository.save(medicalRecord);
+            logger.info("Created medical record for patient ID: {}", savedPatient.getPatientId());
+        } catch (Exception e) {
+            logger.error("Failed to create medical record for patient: {}", e.getMessage());
+        }
+
+        return savedPatient;
+    }
+
+    /**
+     * Update patient information
+     */
+    @Transactional
+    public Patient updatePatient(Long patientId, Patient patientDetails) {
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+
+        Patient patient = patientRepository.findById(patientId)
+                .orElseThrow(() -> new RuntimeException("Patient not found with ID: " + patientId));
+
+        if (patientDetails.getFirstName() != null) {
+            patient.setFirstName(patientDetails.getFirstName());
+        }
+        if (patientDetails.getLastName() != null) {
+            patient.setLastName(patientDetails.getLastName());
+        }
+        if (patientDetails.getPhoneNumber() != null) {
+            patient.setPhoneNumber(patientDetails.getPhoneNumber());
+        }
+        if (patientDetails.getBloodType() != null) {
+            patient.setBloodType(patientDetails.getBloodType());
+        }
+
+        logger.info("Updating patient with ID: {}", patientId);
+        return patientRepository.save(patient);
+    }
+
+    /**
+     * Create medical records for all patients that don't have one
+     * This is a utility method for backfilling missing medical records
+     */
+    @Transactional
+    public int createMissingMedicalRecords() {
+        List<Patient> allPatients = patientRepository.findAll();
+        int createdCount = 0;
+
+        for (Patient patient : allPatients) {
+            try {
+                // Check if patient already has a medical record
+                boolean hasRecord = patient.getMedicalRecords() != null && !patient.getMedicalRecords().isEmpty();
+                if (!hasRecord) {
+                    MedicalRecord medicalRecord = new MedicalRecord();
+                    medicalRecord.setPatient(patient);
+                    medicalRecordRepository.save(medicalRecord);
+                    createdCount++;
+                    logger.info("Created medical record for patient ID: {}", patient.getPatientId());
+                }
+            } catch (Exception e) {
+                logger.warn("Failed to create medical record for patient ID {}: {}", patient.getPatientId(), e.getMessage());
+            }
+        }
+
+        logger.info("Backfill complete: created {} medical records", createdCount);
+        return createdCount;
+    }
+}
Index: backend/src/main/java/medora/service/PrescriptionService.java
===================================================================
--- backend/src/main/java/medora/service/PrescriptionService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/PrescriptionService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,146 @@
+package medora.service;
+
+import medora.models.domain.MedicalRecord;
+import medora.models.domain.PrescriptionMedicalRecord;
+import medora.models.domain.Prescriptions;
+import medora.repository.MedicalRecordRepository;
+import medora.repository.PrescriptionMedicalRecordRepository;
+import medora.repository.PrescriptionRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * PrescriptionService handles prescription operations.
+ * UC012 – Record Prescription
+ * UC015 – Link Medical Data to Medical Record
+ */
+@Service
+public class PrescriptionService {
+
+    private static final Logger logger = LoggerFactory.getLogger(PrescriptionService.class);
+
+    private final PrescriptionRepository prescriptionRepository;
+    private final PrescriptionMedicalRecordRepository prescriptionMedicalRecordRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+
+    public PrescriptionService(PrescriptionRepository prescriptionRepository,
+                               PrescriptionMedicalRecordRepository prescriptionMedicalRecordRepository,
+                               MedicalRecordRepository medicalRecordRepository) {
+        this.prescriptionRepository = prescriptionRepository;
+        this.prescriptionMedicalRecordRepository = prescriptionMedicalRecordRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+    }
+
+    /**
+     * UC012 – Record Prescription
+     */
+    @Transactional
+    public PrescriptionMedicalRecord prescribeMedication(Long medicalRecordId,
+                                                         String medicationName,
+                                                         String dosage,
+                                                         String frequency,
+                                                         String duration,
+                                                         String notes) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Medical record ID must be valid");
+
+        if (medicationName == null || medicationName.isBlank())
+            throw new IllegalArgumentException("Medication name is required");
+
+        MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+        Prescriptions prescription = new Prescriptions();
+        prescription.setMedicationName(medicationName);
+
+        Prescriptions savedPrescription = prescriptionRepository.save(prescription);
+
+        PrescriptionMedicalRecord record = new PrescriptionMedicalRecord();
+        record.setPrescription(savedPrescription);
+        record.setMedicalRecord(medicalRecord);
+        record.setDosage(dosage);
+        record.setFrequency(frequency);
+        record.setDuration(duration);
+        record.setNotes(notes);
+
+        logger.info("Prescription '{}' added to medical record {}", medicationName, medicalRecordId);
+        return prescriptionMedicalRecordRepository.save(record);
+    }
+
+    /**
+     * Get prescriptions for medical record
+     */
+    @Transactional(readOnly = true)
+    public List<PrescriptionMedicalRecord> getPrescriptionsForMedicalRecord(Long medicalRecordId) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Medical record ID must be valid");
+
+        if (!medicalRecordRepository.existsById(medicalRecordId))
+            throw new RuntimeException("Medical record not found");
+
+        return prescriptionMedicalRecordRepository.findByMedicalRecordRecordId(medicalRecordId);
+    }
+
+    /**
+     * Get prescription by medical record and prescription IDs
+     */
+    @Transactional(readOnly = true)
+    public Optional<PrescriptionMedicalRecord> getPrescriptionByRecordAndId(Long medicalRecordId, Long prescriptionId) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Medical record ID must be valid");
+
+        if (prescriptionId == null || prescriptionId <= 0)
+            throw new IllegalArgumentException("Prescription ID must be valid");
+
+        return Optional.ofNullable(
+                prescriptionMedicalRecordRepository.findByMedicalRecordAndPrescription(medicalRecordId, prescriptionId)
+        );
+    }
+
+    /**
+     * Update prescription details
+     */
+    @Transactional
+    public PrescriptionMedicalRecord updatePrescription(Long medicalRecordId,
+                                                        Long prescriptionId,
+                                                        String dosage,
+                                                        String frequency,
+                                                        String duration,
+                                                        String notes) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Medical record ID must be valid");
+
+        if (prescriptionId == null || prescriptionId <= 0)
+            throw new IllegalArgumentException("Prescription ID must be valid");
+
+        PrescriptionMedicalRecord record = prescriptionMedicalRecordRepository
+                .findByMedicalRecordAndPrescription(medicalRecordId, prescriptionId);
+
+        if (record == null)
+            throw new RuntimeException("Prescription not found for the given medical record");
+
+        if (dosage != null && !dosage.isBlank())
+            record.setDosage(dosage);
+
+        if (frequency != null && !frequency.isBlank())
+            record.setFrequency(frequency);
+
+        if (duration != null && !duration.isBlank())
+            record.setDuration(duration);
+
+        if (notes != null && !notes.isBlank())
+            record.setNotes(notes);
+
+        logger.info("Updated prescription {} for medical record {}", prescriptionId, medicalRecordId);
+        return prescriptionMedicalRecordRepository.save(record);
+    }
+}
Index: backend/src/main/java/medora/service/ProcedureService.java
===================================================================
--- backend/src/main/java/medora/service/ProcedureService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/ProcedureService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,261 @@
+package medora.service;
+
+import jakarta.persistence.EntityManager;
+import medora.dto.SimpleProcedureDTO;
+import medora.models.domain.*;
+import medora.repository.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class ProcedureService {
+
+    private static final Logger logger = LoggerFactory.getLogger(ProcedureService.class);
+
+    private final PerformedProcedureRepository performedProcedureRepository;
+    private final ProcedureRepository procedureRepository;
+    private final PatientRepository patientRepository;
+    private final DoctorRepository doctorRepository;
+    private final DiagnosisRepository diagnosisRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+    private final MedicalRecordProcedureRepository medicalRecordProcedureRepository;
+
+    private final EntityManager entityManager;
+
+    public ProcedureService(PerformedProcedureRepository performedProcedureRepository,
+                            ProcedureRepository procedureRepository,
+                            PatientRepository patientRepository,
+                            DoctorRepository doctorRepository,
+                            DiagnosisRepository diagnosisRepository,
+                            MedicalRecordRepository medicalRecordRepository,
+                            MedicalRecordProcedureRepository medicalRecordProcedureRepository,
+
+                            EntityManager entityManager) {
+
+        this.performedProcedureRepository = performedProcedureRepository;
+        this.procedureRepository = procedureRepository;
+        this.patientRepository = patientRepository;
+        this.doctorRepository = doctorRepository;
+        this.diagnosisRepository = diagnosisRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+        this.medicalRecordProcedureRepository = medicalRecordProcedureRepository;
+
+        this.entityManager = entityManager;
+    }
+
+    //REQUEST PROCEDURE
+    @Transactional
+    public PerformedProcedures requestProcedureForPatient(Long patientId,
+                                                          Long doctorId,
+                                                          Long procedureId,
+                                                          Long diagnosisId,
+                                                          LocalDate procedureDate,
+                                                          String notes) {
+
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Patient ID must be valid");
+
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Doctor ID must be valid");
+
+        if (procedureId == null || procedureId <= 0)
+            throw new IllegalArgumentException("Procedure ID must be valid");
+
+        if (procedureDate == null)
+            throw new IllegalArgumentException("Procedure date is required");
+
+        Patient patient = patientRepository.findById(patientId)
+                .orElseThrow(() -> new RuntimeException("Patient not found"));
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found"));
+
+        Procedure procedure = procedureRepository.findById(procedureId)
+                .orElseThrow(() -> new RuntimeException("Procedure not found"));
+
+        PerformedProcedures performed = new PerformedProcedures();
+        performed.setProcedure(procedure);
+        performed.setDoctor(doctor);
+        performed.setPatient(patient);
+        performed.setProcedureDate(procedureDate);
+        performed.setNotes(notes);
+
+        if (diagnosisId != null && diagnosisId > 0) {
+            Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)
+                    .orElseThrow(() -> new RuntimeException("Diagnosis not found"));
+            performed.setDiagnosis(diagnosis);
+        }
+
+        logger.info("Requested procedure {} for patient {} by doctor {}", procedureId, patientId, doctorId);
+        return performedProcedureRepository.saveAndFlush(performed);
+    }
+
+    // UC016
+    @Transactional
+    public PerformedProcedures recordProcedure(Long procedureId,
+                                               Long doctorId,
+                                               Long patientId,
+                                               Long diagnosisId,
+                                               LocalDate procedureDate) {
+
+        if (procedureId == null || procedureId <= 0)
+            throw new IllegalArgumentException("Procedure ID must be valid");
+
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Doctor ID must be valid");
+
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Patient ID must be valid");
+
+        if (procedureDate == null)
+            throw new IllegalArgumentException("Procedure date is required");
+
+        Procedure procedure = procedureRepository.findById(procedureId)
+                .orElseThrow(() -> new RuntimeException("Procedure not found"));
+
+        Doctors doctor = doctorRepository.findById(doctorId)
+                .orElseThrow(() -> new RuntimeException("Doctor not found"));
+
+        Patient patient = patientRepository.findById(patientId)
+                .orElseThrow(() -> new RuntimeException("Patient not found"));
+
+        PerformedProcedures performed = new PerformedProcedures();
+        performed.setProcedure(procedure);
+        performed.setDoctor(doctor);
+        performed.setPatient(patient);
+        performed.setProcedureDate(procedureDate);
+
+        if (diagnosisId != null && diagnosisId > 0) {
+            Diagnosis diagnosis = diagnosisRepository.findById(diagnosisId)
+                    .orElseThrow(() -> new RuntimeException("Diagnosis not found"));
+            performed.setDiagnosis(diagnosis);
+        }
+
+        logger.info("Recorded procedure {} for patient {}", procedureId, patientId);
+        return performedProcedureRepository.saveAndFlush(performed);
+    }
+
+    // UC017
+    @Transactional
+    public PerformedProcedures recordProcedureOutcome(Long performedProcedureId, String notes) {
+
+        if (performedProcedureId == null || performedProcedureId <= 0)
+            throw new IllegalArgumentException("Performed procedure ID must be valid");
+
+        PerformedProcedures performed = performedProcedureRepository.findById(performedProcedureId)
+                .orElseThrow(() -> new RuntimeException("Performed procedure not found"));
+
+        if (notes != null && !notes.isBlank()) {
+            performed.setNotes(notes);
+        }
+
+        logger.info("Updated procedure outcome {}", performedProcedureId);
+        return performedProcedureRepository.save(performed);
+    }
+
+    //  LINK TO MEDICAL RECORD
+    @Transactional
+    public MedicalRecordProcedures linkProcedureToMedicalRecord(Long medicalRecordId,
+                                                                Long procedureId) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Medical record ID must be valid");
+
+        if (procedureId == null || procedureId <= 0)
+            throw new IllegalArgumentException("Procedure ID must be valid");
+
+        MedicalRecord record = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found"));
+
+        Procedure procedure = procedureRepository.findById(procedureId)
+                .orElseThrow(() -> new RuntimeException("Procedure not found"));
+
+        // Prevent duplicates
+        if (medicalRecordProcedureRepository
+                .existsByMedicalRecordRecordIdAndProcedureProcedureId(medicalRecordId, procedureId)) {
+            throw new RuntimeException("Procedure already linked to this medical record");
+        }
+
+        MedicalRecordProcedures link = new MedicalRecordProcedures(record, procedure);
+
+        logger.info("Linked procedure {} to record {}", procedureId, medicalRecordId);
+        return medicalRecordProcedureRepository.save(link);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<PerformedProcedures> getProcedureRequestsForPatient(Long patientId) {
+
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Patient ID must be valid");
+
+        if (!patientRepository.existsById(patientId))
+            throw new RuntimeException("Patient not found");
+
+        return performedProcedureRepository.findByPatientPatientId(patientId);
+    }
+
+    @Transactional(readOnly = true)
+    public List<PerformedProcedures> getProcedureRequestsByDoctor(Long doctorId) {
+
+        if (doctorId == null || doctorId <= 0)
+            throw new IllegalArgumentException("Doctor ID must be valid");
+
+        if (!doctorRepository.existsById(doctorId))
+            throw new RuntimeException("Doctor not found");
+
+        return performedProcedureRepository.findByDoctorDoctorId(doctorId);
+    }
+
+    @Transactional(readOnly = true)
+    public List<PerformedProcedures> getProceduresForPatient(Long patientId) {
+
+        if (patientId == null || patientId <= 0)
+            throw new IllegalArgumentException("Patient ID must be valid");
+
+        if (!patientRepository.existsById(patientId))
+            throw new RuntimeException("Patient not found");
+
+        return performedProcedureRepository.findByPatientPatientId(patientId);
+    }
+
+    @Transactional(readOnly = true)
+    public List<MedicalRecordProcedures> getProceduresForMedicalRecord(Long medicalRecordId) {
+
+        if (medicalRecordId == null || medicalRecordId <= 0)
+            throw new IllegalArgumentException("Medical record ID must be valid");
+
+        if (!medicalRecordRepository.existsById(medicalRecordId))
+            throw new RuntimeException("Medical record not found");
+
+        return medicalRecordProcedureRepository.findByMedicalRecordRecordId(medicalRecordId);
+    }
+
+    @Transactional(readOnly = true)
+    public List<SimpleProcedureDTO> getAllProcedures() {
+        return procedureRepository.findAll().stream()
+                .map(proc -> new SimpleProcedureDTO(
+                        proc.getProcedureId(),
+                        proc.getProcedureType(),
+                        proc.getDescription(),
+                        proc.getCost()
+                ))
+                .toList();
+    }
+
+    @Transactional(readOnly = true)
+    public Optional<PerformedProcedures> getPerformedProcedureById(Long id) {
+
+        if (id == null || id <= 0)
+            throw new IllegalArgumentException("ID must be valid");
+
+        return performedProcedureRepository.findById(id);
+    }
+
+    }
Index: backend/src/main/java/medora/service/ReferralService.java
===================================================================
--- backend/src/main/java/medora/service/ReferralService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
+++ backend/src/main/java/medora/service/ReferralService.java	(revision bc882d26274cd2e0b878d7a95fd44f4a49e80a46)
@@ -0,0 +1,145 @@
+package medora.service;
+
+import medora.models.domain.Doctors;
+import medora.models.domain.Referrals;
+import medora.repository.DoctorRepository;
+import medora.repository.MedicalRecordRepository;
+import medora.repository.PatientRepository;
+import medora.repository.ReferralRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * RefferalService handles referral operations.
+ * UC019 – Create Referral Record
+ * OPTIONAL - Use only if needed
+ */
+@Service
+public class ReferralService {
+
+    private static final Logger logger = LoggerFactory.getLogger(ReferralService.class);
+
+    private final ReferralRepository referralRepository;
+    private final DoctorRepository doctorRepository;
+    private final PatientRepository patientRepository;
+    private final MedicalRecordRepository medicalRecordRepository;
+
+    public ReferralService(ReferralRepository referralRepository,
+                           DoctorRepository doctorRepository,
+                           PatientRepository patientRepository,
+                           MedicalRecordRepository medicalRecordRepository) {
+        this.referralRepository = referralRepository;
+        this.doctorRepository = doctorRepository;
+        this.patientRepository = patientRepository;
+        this.medicalRecordRepository = medicalRecordRepository;
+    }
+
+    /**
+     * UC019 – Create Referral Record
+     * Create a referral from one doctor to another
+     */
+    @Transactional
+    public Referrals createReferral(Long medicalRecordId, Long fromDoctorId, Long toDoctorId,
+                                    String reason, LocalDate referralDate) {
+        if (medicalRecordId == null || medicalRecordId <= 0) {
+            throw new IllegalArgumentException("Medical record ID must be valid");
+        }
+        if (fromDoctorId == null || fromDoctorId <= 0) {
+            throw new IllegalArgumentException("From doctor ID must be valid");
+        }
+        if (toDoctorId == null || toDoctorId <= 0) {
+            throw new IllegalArgumentException("To doctor ID must be valid");
+        }
+        if (reason == null || reason.isBlank()) {
+            throw new IllegalArgumentException("Referral reason is required");
+        }
+        if (referralDate == null) {
+            throw new IllegalArgumentException("Referral date is required");
+        }
+
+        var medicalRecord = medicalRecordRepository.findById(medicalRecordId)
+                .orElseThrow(() -> new RuntimeException("Medical record not found with ID: " + medicalRecordId));
+
+        Doctors fromDoctor = doctorRepository.findById(fromDoctorId)
+                .orElseThrow(() -> new RuntimeException("From doctor not found with ID: " + fromDoctorId));
+
+        Doctors toDoctor = doctorRepository.findById(toDoctorId)
+                .orElseThrow(() -> new RuntimeException("To doctor not found with ID: " + toDoctorId));
+
+        if (fromDoctorId.equals(toDoctorId)) {
+            throw new RuntimeException("A doctor cannot refer to themselves");
+        }
+
+        Referrals referral = new Referrals();
+        referral.setMedicalRecord(medicalRecord);
+        referral.setFromDoctor(fromDoctor);
+        referral.setToDoctor(toDoctor);
+        referral.setReason(reason);
+        referral.setReferralDate(referralDate);
+
+        logger.info("Creating referral for medical record ID: {} from doctor ID: {} to doctor ID: {}",
+                medicalRecordId, fromDoctorId, toDoctorId);
+        return referralRepository.save(referral);
+    }
+
+
+    @Transactional(readOnly = true)
+    public Optional<Referrals> getReferralById(Long referralId) {
+        if (referralId == null || referralId <= 0) {
+            throw new IllegalArgumentException("Referral ID must be valid");
+        }
+        logger.info("Fetching referral with ID: {}", referralId);
+        return referralRepository.findById(referralId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Referrals> getReferralsForPatient(Long patientId) {
+        if (patientId == null || patientId <= 0) {
+            throw new IllegalArgumentException("Patient ID must be valid");
+        }
+
+        if (!patientRepository.existsById(patientId)) {
+            throw new RuntimeException("Patient not found with ID: " + patientId);
+        }
+
+        logger.info("Fetching referrals for patient ID: {}", patientId);
+        return referralRepository.findReferralsForPatient(patientId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Referrals> getReferralsByFromDoctor(Long doctorId) {
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        if (!doctorRepository.existsById(doctorId)) {
+            throw new RuntimeException("Doctor not found with ID: " + doctorId);
+        }
+
+        logger.info("Fetching referrals made by doctor ID: {}", doctorId);
+        return referralRepository.findByFromDoctorDoctorId(doctorId);
+    }
+
+
+    @Transactional(readOnly = true)
+    public List<Referrals> getReferralsToDoctor(Long doctorId) {
+        if (doctorId == null || doctorId <= 0) {
+            throw new IllegalArgumentException("Doctor ID must be valid");
+        }
+
+        if (!doctorRepository.existsById(doctorId)) {
+            throw new RuntimeException("Doctor not found with ID: " + doctorId);
+        }
+
+        logger.info("Fetching referrals to doctor ID: {}", doctorId);
+        return referralRepository.findIncomingReferralsForDoctor(doctorId);
+    }
+}
