Index: backend/src/main/java/medora/controller/BillingController.java
===================================================================
--- backend/src/main/java/medora/controller/BillingController.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/controller/BillingController.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -2,11 +2,16 @@
 
 import medora.dto.BillingDTO;
+import medora.dto.BillingDetailDTO;
 import medora.dto.CreateBillingRequest;
 import medora.dto.UpdateBillingRequest;
 import medora.models.domain.Billing;
+import medora.models.enums.PaymentStatus;
 import medora.service.BillingService;
+import medora.util.BillingPDFGenerator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
@@ -82,4 +87,21 @@
     }
 
+    @GetMapping("/{billId}/detail")
+    public ResponseEntity<?> getBillingDetail(@PathVariable Long billId) {
+        try {
+            logger.info("Fetching detailed billing information for bill ID: {}", billId);
+            BillingDetailDTO detail = billingService.getBillingDetail(billId);
+            return ResponseEntity.ok(detail);
+        } catch (RuntimeException e) {
+            logger.error("Error fetching billing detail: {}", e.getMessage());
+            return ResponseEntity.badRequest()
+                    .body(Map.of("error", e.getMessage()));
+        } catch (Exception e) {
+            logger.error("Unexpected error fetching billing detail: {}", e.getMessage());
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+                    .body(Map.of("error", "Failed to fetch billing detail: " + e.getMessage()));
+        }
+    }
+
     @GetMapping
     public ResponseEntity<?> getAllBillings() {
@@ -124,5 +146,5 @@
     @PatchMapping("/{billId}/payment-status")
     public ResponseEntity<?> updatePaymentStatus(@PathVariable Long billId,
-                                                @RequestBody UpdateBillingRequest request) {
+                                                 @RequestBody UpdateBillingRequest request) {
         try {
             if (request.getPaymentStatus() == null) {
@@ -144,4 +166,28 @@
             return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                     .body(Map.of("error", "Failed to update payment status: " + e.getMessage()));
+        }
+    }
+
+    @GetMapping("/{billId}/invoice-pdf")
+    public ResponseEntity<?> downloadInvoicePDF(@PathVariable Long billId) {
+        try {
+            logger.info("Generating PDF invoice for bill ID: {}", billId);
+            BillingDetailDTO billingDetail = billingService.getBillingDetail(billId);
+            byte[] pdfContent = BillingPDFGenerator.generateInvoicePDF(billingDetail);
+
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_PDF);
+            headers.setContentDispositionFormData("attachment", "invoice-" + billId + ".pdf");
+            headers.setContentLength(pdfContent.length);
+
+            return new ResponseEntity<>(pdfContent, headers, HttpStatus.OK);
+        } catch (RuntimeException e) {
+            logger.error("Error generating PDF invoice: {}", e.getMessage());
+            return ResponseEntity.badRequest()
+                    .body(Map.of("error", e.getMessage()));
+        } catch (Exception e) {
+            logger.error("Unexpected error generating PDF invoice: {}", e.getMessage());
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
+                    .body(Map.of("error", "Failed to generate invoice: " + e.getMessage()));
         }
     }
@@ -151,5 +197,5 @@
         if (billing.getMedicalRecord() != null && billing.getMedicalRecord().getPatient() != null) {
             patientName = billing.getMedicalRecord().getPatient().getFirstName() + " " +
-                         billing.getMedicalRecord().getPatient().getLastName();
+                    billing.getMedicalRecord().getPatient().getLastName();
         }
         return new BillingDTO(
Index: backend/src/main/java/medora/dto/BillingDetailDTO.java
===================================================================
--- backend/src/main/java/medora/dto/BillingDetailDTO.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
+++ backend/src/main/java/medora/dto/BillingDetailDTO.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -0,0 +1,66 @@
+package medora.dto;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+
+public class BillingDetailDTO {
+    private Long billId;
+    private String patientName;
+    private String patientEmbg;
+    private String patientPhone;
+    private BigDecimal totalCost;
+    private String paymentStatus;
+    private LocalDate paymentDate;
+    private LocalDate billDate;
+    private List<BillingItemDTO> procedures;
+    private List<BillingItemDTO> labTests;
+
+    public BillingDetailDTO() {}
+
+    public BillingDetailDTO(Long billId, String patientName, String patientEmbg, String patientPhone,
+                            BigDecimal totalCost, String paymentStatus, LocalDate paymentDate,
+                            LocalDate billDate, List<BillingItemDTO> procedures, List<BillingItemDTO> labTests) {
+        this.billId = billId;
+        this.patientName = patientName;
+        this.patientEmbg = patientEmbg;
+        this.patientPhone = patientPhone;
+        this.totalCost = totalCost;
+        this.paymentStatus = paymentStatus;
+        this.paymentDate = paymentDate;
+        this.billDate = billDate;
+        this.procedures = procedures;
+        this.labTests = labTests;
+    }
+
+    // Getters and Setters
+    public Long getBillId() { return billId; }
+    public void setBillId(Long billId) { this.billId = billId; }
+
+    public String getPatientName() { return patientName; }
+    public void setPatientName(String patientName) { this.patientName = patientName; }
+
+    public String getPatientEmbg() { return patientEmbg; }
+    public void setPatientEmbg(String patientEmbg) { this.patientEmbg = patientEmbg; }
+
+    public String getPatientPhone() { return patientPhone; }
+    public void setPatientPhone(String patientPhone) { this.patientPhone = patientPhone; }
+
+    public BigDecimal getTotalCost() { return totalCost; }
+    public void setTotalCost(BigDecimal totalCost) { this.totalCost = totalCost; }
+
+    public String getPaymentStatus() { return paymentStatus; }
+    public void setPaymentStatus(String paymentStatus) { this.paymentStatus = paymentStatus; }
+
+    public LocalDate getPaymentDate() { return paymentDate; }
+    public void setPaymentDate(LocalDate paymentDate) { this.paymentDate = paymentDate; }
+
+    public LocalDate getBillDate() { return billDate; }
+    public void setBillDate(LocalDate billDate) { this.billDate = billDate; }
+
+    public List<BillingItemDTO> getProcedures() { return procedures; }
+    public void setProcedures(List<BillingItemDTO> procedures) { this.procedures = procedures; }
+
+    public List<BillingItemDTO> getLabTests() { return labTests; }
+    public void setLabTests(List<BillingItemDTO> labTests) { this.labTests = labTests; }
+}
Index: backend/src/main/java/medora/dto/BillingItemDTO.java
===================================================================
--- backend/src/main/java/medora/dto/BillingItemDTO.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
+++ backend/src/main/java/medora/dto/BillingItemDTO.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -0,0 +1,26 @@
+package medora.dto;
+
+import java.math.BigDecimal;
+
+public class BillingItemDTO {
+    private Long itemId;
+    private String description;
+    private BigDecimal cost;
+
+    public BillingItemDTO() {}
+
+    public BillingItemDTO(Long itemId, String description, BigDecimal cost) {
+        this.itemId = itemId;
+        this.description = description;
+        this.cost = cost;
+    }
+
+    public Long getItemId() { return itemId; }
+    public void setItemId(Long itemId) { this.itemId = itemId; }
+
+    public String getDescription() { return description; }
+    public void setDescription(String description) { this.description = description; }
+
+    public BigDecimal getCost() { return cost; }
+    public void setCost(BigDecimal cost) { this.cost = cost; }
+}
Index: backend/src/main/java/medora/repository/BillingRepository.java
===================================================================
--- backend/src/main/java/medora/repository/BillingRepository.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/repository/BillingRepository.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -79,3 +79,50 @@
     """)
     List<Billing> findBillingHistoryForPatient(@Param("patientId") Long patientId);
+
+    // UC020 – Auto billing: Check if billing exists for patient on a specific date
+    @Query(value = """
+        SELECT COUNT(b.bill_id) > 0
+        FROM billing b
+        JOIN medical_records mr ON b.record_id = mr.record_id
+        WHERE mr.patient_id = :patientId
+        AND CAST(b.payment_date AS DATE) = :billDate
+    """, nativeQuery = true)
+    boolean existsBillingForPatientOnDate(@Param("patientId") Long patientId, @Param("billDate") java.time.LocalDate billDate);
+
+    // UC020 – Auto billing: Get billing for patient on a specific date
+    @Query(value = """
+        SELECT b.* FROM billing b
+        JOIN medical_records mr ON b.record_id = mr.record_id
+        WHERE mr.patient_id = :patientId
+        AND CAST(b.payment_date AS DATE) = :billDate
+        LIMIT 1
+    """, nativeQuery = true)
+    Billing findBillingForPatientOnDate(@Param("patientId") Long patientId, @Param("billDate") java.time.LocalDate billDate);
+
+    // UC020 – Auto billing: Calculate total cost for patient on a specific date (using view)
+    @Query(value = """
+        SELECT COALESCE(total_cost, 0::decimal)
+        FROM daily_patient_billing_totals
+        WHERE patient_id = :patientId
+        AND service_date = :serviceDate
+    """, nativeQuery = true)
+    BigDecimal calculateDailyTotalCostForPatient(@Param("patientId") Long patientId, @Param("serviceDate") java.time.LocalDate serviceDate);
+
+    // UC020 – Get procedures for a billing record
+    @Query(value = """
+        SELECT p.procedure_id, p.procedure_type, p.cost
+        FROM billing_procedures bp
+        JOIN procedures p ON bp.procedure_id = p.procedure_id
+        WHERE bp.bill_id = :billId
+    """, nativeQuery = true)
+    java.util.List<Object[]> findProceduresForBilling(@Param("billId") Long billId);
+
+    // UC020 – Get lab tests for a billing record
+    @Query(value = """
+        SELECT l.test_id, l.test_name, l.cost
+        FROM billing_lab_tests blt
+        JOIN lab_tests l ON blt.test_id = l.test_id
+        WHERE blt.bill_id = :billId
+    """, nativeQuery = true)
+    java.util.List<Object[]> findLabTestsForBilling(@Param("billId") Long billId);
 }
Index: backend/src/main/java/medora/repository/PerformedLabTestRepository.java
===================================================================
--- backend/src/main/java/medora/repository/PerformedLabTestRepository.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/repository/PerformedLabTestRepository.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -4,4 +4,6 @@
 import medora.models.domain.PerformedLabTests;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 
 import java.util.List;
@@ -12,3 +14,11 @@
 
     List<PerformedLabTests> findByDoctorDoctorId(Long doctorId);
+
+    // UC020 – Auto billing: Get lab tests for a patient on a specific date
+    @Query("""
+        SELECT plt FROM PerformedLabTests plt
+        WHERE plt.patient.patientId = :patientId
+        AND plt.testDate = :testDate
+    """)
+    List<PerformedLabTests> findByPatientAndDate(@Param("patientId") Long patientId, @Param("testDate") java.time.LocalDate testDate);
 }
Index: backend/src/main/java/medora/repository/PerformedProcedureRepository.java
===================================================================
--- backend/src/main/java/medora/repository/PerformedProcedureRepository.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/repository/PerformedProcedureRepository.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -45,3 +45,11 @@
     """)
     List<PerformedProcedures> findByMedicalRecordId(@Param("recordId") Long recordId);
+
+    // UC020 – Auto billing: Get procedures for a patient on a specific date
+    @Query("""
+        SELECT pp FROM PerformedProcedures pp
+        WHERE pp.patient.patientId = :patientId
+        AND pp.procedureDate = :procedureDate
+    """)
+    List<PerformedProcedures> findByPatientAndDate(@Param("patientId") Long patientId, @Param("procedureDate") java.time.LocalDate procedureDate);
 }
Index: backend/src/main/java/medora/service/AppointmentService.java
===================================================================
--- backend/src/main/java/medora/service/AppointmentService.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/service/AppointmentService.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -2,12 +2,14 @@
 
 import medora.models.domain.Appointment;
+import medora.models.domain.Patient;
 import medora.models.domain.Doctors;
-import medora.models.domain.Patient;
 import medora.models.enums.AppointmentStatus;
 import medora.repository.AppointmentRepository;
+import medora.repository.PatientRepository;
 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;
@@ -79,5 +81,5 @@
                 LocalDateTime.of(appointmentDate, appointmentTime);
 
-
+        // Future validation
         if (!appointmentDateTime.isAfter(LocalDateTime.now())) {
             throw new RuntimeException(
@@ -86,4 +88,5 @@
         }
 
+        // Doctor slot validation
         boolean doctorBusy =
                 appointmentRepository
@@ -99,4 +102,5 @@
         }
 
+        // Duplicate patient validation
         boolean duplicateAppointment =
                 appointmentRepository
@@ -204,5 +208,4 @@
     }
 
-
     @Transactional(readOnly = true)
     public Optional<Appointment> getAppointmentById(Long appointmentId) {
@@ -217,7 +220,5 @@
     }
 
-    /**
-     * Get appointments for patient
-     */
+
     @Transactional(readOnly = true)
     public List<Appointment> getAppointmentsForPatient(Long patientId) {
@@ -297,3 +298,30 @@
         return appointmentRepository.findAll();
     }
+
+
+    public LocalTime findNextAvailableSlot(Long doctorId, LocalDate appointmentDate) {
+        LocalTime[] timeSlots = {
+                LocalTime.of(9, 0),
+                LocalTime.of(10, 0),
+                LocalTime.of(11, 0),
+                LocalTime.of(13, 0),
+                LocalTime.of(14, 0),
+                LocalTime.of(15, 0),
+                LocalTime.of(16, 0)
+        };
+
+        for (LocalTime timeSlot : timeSlots) {
+            boolean isBooked = appointmentRepository
+                    .existsByDoctorDoctorIdAndAppointmentDateAndAppointmentTimeAndStatusNot(
+                            doctorId,
+                            appointmentDate,
+                            timeSlot,
+                            AppointmentStatus.CANCELLED
+                    );
+            if (!isBooked) {
+                return timeSlot;
+            }
+        }
+        return null;
+    }
 }
Index: backend/src/main/java/medora/service/BillingService.java
===================================================================
--- backend/src/main/java/medora/service/BillingService.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/service/BillingService.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -1,7 +1,22 @@
 package medora.service;
 
-import medora.models.domain.*;
+import medora.models.domain.Billing;
+import medora.models.domain.MedicalRecord;
+import medora.models.domain.Admin;
+import medora.models.domain.BillingLabTests;
+import medora.models.domain.BillingProcedures;
+import medora.models.domain.PerformedProcedures;
+import medora.models.domain.PerformedLabTests;
 import medora.models.enums.PaymentStatus;
-import medora.repository.*;
+import medora.repository.BillingRepository;
+import medora.repository.MedicalRecordRepository;
+import medora.repository.AdminRepository;
+import medora.repository.BillingLabTestsRepository;
+import medora.repository.BillingProceduresRepository;
+import medora.repository.PerformedProcedureRepository;
+import medora.repository.PerformedLabTestRepository;
+import medora.repository.PatientRepository;
+import medora.dto.BillingDetailDTO;
+import medora.dto.BillingItemDTO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -13,4 +28,5 @@
 import java.util.List;
 import java.util.Optional;
+import java.util.ArrayList;
 
 /**
@@ -30,4 +46,7 @@
     private final BillingLabTestsRepository billingLabTestsRepository;
     private final BillingProceduresRepository billingProceduresRepository;
+    private final PerformedProcedureRepository performedProcedureRepository;
+    private final PerformedLabTestRepository performedLabTestRepository;
+    private final PatientRepository patientRepository;
 
     public BillingService(BillingRepository billingRepository,
@@ -35,5 +54,8 @@
                           AdminRepository adminRepository,
                           BillingLabTestsRepository billingLabTestsRepository,
-                          BillingProceduresRepository billingProceduresRepository) {
+                          BillingProceduresRepository billingProceduresRepository,
+                          PerformedProcedureRepository performedProcedureRepository,
+                          PerformedLabTestRepository performedLabTestRepository,
+                          PatientRepository patientRepository) {
         this.billingRepository = billingRepository;
         this.medicalRecordRepository = medicalRecordRepository;
@@ -41,4 +63,7 @@
         this.billingLabTestsRepository = billingLabTestsRepository;
         this.billingProceduresRepository = billingProceduresRepository;
+        this.performedProcedureRepository = performedProcedureRepository;
+        this.performedLabTestRepository = performedLabTestRepository;
+        this.patientRepository = patientRepository;
     }
 
@@ -196,5 +221,5 @@
         }
 
-        logger.info("Total billing cost for bill ID {}: procedures={}, lab tests={}", 
+        logger.info("Total billing cost for bill ID {}: procedures={}, lab tests={}",
                 billId, procedureCost, labTestCost);
         return procedureCost.add(labTestCost);
@@ -219,5 +244,5 @@
         // 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
     }
@@ -241,6 +266,180 @@
         // 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
     }
+
+    /**
+     * UC020 – Auto-generate billing when a procedure or lab test is performed
+     * Creates a billing record if one doesn't exist for the patient on that date
+     * Calculates total cost from all procedures and lab tests performed that day
+     */
+    @Transactional
+    public void autoGenerateBillingForPatientService(Long patientId, LocalDate serviceDate) {
+        try {
+            if (patientId == null || patientId <= 0) {
+                throw new IllegalArgumentException("Patient ID must be valid");
+            }
+            if (serviceDate == null) {
+                throw new IllegalArgumentException("Service date must be valid");
+            }
+
+            logger.info("Starting auto-billing for patient {} on date {}", patientId, serviceDate);
+
+            // Get patient's medical record (or create one if it doesn't exist)
+            MedicalRecord medicalRecord = medicalRecordRepository.findByPatientPatientId(patientId)
+                    .orElseGet(() -> {
+                        logger.info("Creating new medical record for patient {}", patientId);
+                        MedicalRecord newRecord = new MedicalRecord();
+                        newRecord.setPatient(patientRepository.findById(patientId)
+                                .orElseThrow(() -> new RuntimeException("Patient not found with ID: " + patientId)));
+                        return medicalRecordRepository.save(newRecord);
+                    });
+
+            logger.info("Using medical record {} for patient {}", medicalRecord.getRecordId(), patientId);
+
+            // Get all procedures and lab tests for the patient on that date
+            List<PerformedProcedures> procedures = performedProcedureRepository.findByPatientAndDate(patientId, serviceDate);
+            List<PerformedLabTests> labTests = performedLabTestRepository.findByPatientAndDate(patientId, serviceDate);
+
+            logger.info("Found {} procedures and {} lab tests for patient {} on {}",
+                    procedures.size(), labTests.size(), patientId, serviceDate);
+
+            // Only generate billing if there are procedures or lab tests on that date
+            if (procedures.isEmpty() && labTests.isEmpty()) {
+                logger.info("No procedures or lab tests found for patient {} on {}", patientId, serviceDate);
+                return;
+            }
+
+            // Calculate total cost
+            BigDecimal procedureCost = procedures.stream()
+                    .map(p -> {
+                        BigDecimal cost = p.getProcedure().getCost();
+                        logger.debug("Procedure {} cost: {}", p.getProcedure().getProcedureId(), cost);
+                        return cost;
+                    })
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            BigDecimal labTestCost = labTests.stream()
+                    .map(lt -> {
+                        BigDecimal cost = lt.getLabTest().getCost();
+                        logger.debug("Lab test {} cost: {}", lt.getLabTest().getTestId(), cost);
+                        return cost;
+                    })
+                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            BigDecimal totalCost = procedureCost.add(labTestCost);
+            logger.info("Total cost calculation: procedures={}, labTests={}, total={}", procedureCost, labTestCost, totalCost);
+
+            // Check if billing already exists for this patient on this date
+            Billing billing = billingRepository.findBillingForPatientOnDate(patientId, serviceDate);
+
+            if (billing != null) {
+                logger.info("Billing record {} already exists for patient {} on {}, updating with new total",
+                        billing.getBillId(), patientId, serviceDate);
+                billing.setTotalCost(totalCost);
+            } else {
+                // Get default admin (first admin in system)
+                Admin admin = adminRepository.findAll()
+                        .stream()
+                        .findFirst()
+                        .orElseThrow(() -> new RuntimeException("No admin found in system"));
+
+                // Create new billing record
+                billing = new Billing();
+                billing.setMedicalRecord(medicalRecord);
+                billing.setAdmin(admin);
+                billing.setTotalCost(totalCost);
+                billing.setPaymentStatus(PaymentStatus.PENDING);
+                billing.setPaymentDate(serviceDate);
+
+                logger.info("Creating new billing record for patient {} on {}", patientId, serviceDate);
+            }
+
+            Billing savedBilling = billingRepository.save(billing);
+            logger.info("Billing record {} for patient {} on {} with total cost: {}",
+                    savedBilling.getBillId(), patientId, serviceDate, totalCost);
+
+            // Link procedures to billing (only if not already linked)
+            for (PerformedProcedures procedure : procedures) {
+                try {
+                    BillingProcedures billingProcedure = new BillingProcedures(savedBilling, procedure.getProcedure());
+                    billingProceduresRepository.save(billingProcedure);
+                    logger.debug("Linked procedure {} to billing {}", procedure.getProcedure().getProcedureId(), savedBilling.getBillId());
+                } catch (Exception e) {
+                    logger.debug("Procedure {} already linked to billing {}", procedure.getProcedure().getProcedureId(), savedBilling.getBillId());
+                }
+            }
+
+            // Link lab tests to billing (only if not already linked)
+            for (PerformedLabTests labTest : labTests) {
+                try {
+                    BillingLabTests billingLabTest = new BillingLabTests(savedBilling, labTest.getLabTest());
+                    billingLabTestsRepository.save(billingLabTest);
+                    logger.debug("Linked lab test {} to billing {}", labTest.getLabTest().getTestId(), savedBilling.getBillId());
+                } catch (Exception e) {
+                    logger.debug("Lab test {} already linked to billing {}", labTest.getLabTest().getTestId(), savedBilling.getBillId());
+                }
+            }
+
+            logger.info("Successfully processed {} procedures and {} lab tests for billing record {}",
+                    procedures.size(), labTests.size(), savedBilling.getBillId());
+
+        } catch (Exception e) {
+            logger.error("Error in auto-billing for patient {} on date {}: {}", patientId, serviceDate, e.getMessage(), e);
+            throw e;
+        }
+    }
+
+    /**
+     * Get detailed billing information with itemized procedures and lab tests
+     */
+    @Transactional(readOnly = true)
+    public BillingDetailDTO getBillingDetail(Long billId) {
+        if (billId == null || billId <= 0) {
+            throw new IllegalArgumentException("Bill ID must be valid");
+        }
+
+        Billing billing = billingRepository.findById(billId)
+                .orElseThrow(() -> new RuntimeException("Billing record not found with ID: " + billId));
+
+        // Get procedures for this bill
+        List<Object[]> procedureResults = billingRepository.findProceduresForBilling(billId);
+        List<BillingItemDTO> procedures = new ArrayList<>();
+        for (Object[] row : procedureResults) {
+            procedures.add(new BillingItemDTO(
+                    ((Number) row[0]).longValue(),
+                    (String) row[1],
+                    (BigDecimal) row[2]
+            ));
+        }
+
+        // Get lab tests for this bill
+        List<Object[]> labTestResults = billingRepository.findLabTestsForBilling(billId);
+        List<BillingItemDTO> labTests = new ArrayList<>();
+        for (Object[] row : labTestResults) {
+            labTests.add(new BillingItemDTO(
+                    ((Number) row[0]).longValue(),
+                    (String) row[1],
+                    (BigDecimal) row[2]
+            ));
+        }
+
+        // Build the detail DTO
+        BillingDetailDTO detail = new BillingDetailDTO();
+        detail.setBillId(billing.getBillId());
+        detail.setPatientName(billing.getMedicalRecord().getPatient().getFirstName() + " " +
+                billing.getMedicalRecord().getPatient().getLastName());
+        detail.setPatientEmbg(billing.getMedicalRecord().getPatient().getEmbg());
+        detail.setPatientPhone(billing.getMedicalRecord().getPatient().getPhoneNumber());
+        detail.setTotalCost(billing.getTotalCost());
+        detail.setPaymentStatus(billing.getPaymentStatus().toString());
+        detail.setPaymentDate(billing.getPaymentDate());
+        detail.setBillDate(billing.getPaymentDate());
+        detail.setProcedures(procedures);
+        detail.setLabTests(labTests);
+
+        logger.info("Retrieved detailed billing information for bill {}", billId);
+        return detail;
+    }
 }
Index: backend/src/main/java/medora/service/LabService.java
===================================================================
--- backend/src/main/java/medora/service/LabService.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/service/LabService.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -31,4 +31,5 @@
     private final DoctorRepository doctorRepository;
     private final LabTechnicianRepository labTechnicianRepository;
+    private final BillingService billingService;
 
     public LabService(LabTestRepository labTestRepository,
@@ -39,5 +40,6 @@
                       PatientRepository patientRepository,
                       DoctorRepository doctorRepository,
-                      LabTechnicianRepository labTechnicianRepository) {
+                      LabTechnicianRepository labTechnicianRepository,
+                      BillingService billingService) {
         this.labTestRepository = labTestRepository;
         this.labResultsRepository = labResultsRepository;
@@ -48,7 +50,8 @@
         this.doctorRepository = doctorRepository;
         this.labTechnicianRepository = labTechnicianRepository;
-    }
-
-    // LAB TEST
+        this.billingService = billingService;
+    }
+
+    // ================= LAB TEST =================
 
     @Transactional
@@ -104,5 +107,5 @@
     }
 
-    //  LAB TEST REQUESTS (UC013)
+    // ================= LAB TEST REQUESTS (UC013) =================
 
     @Transactional
@@ -134,9 +137,15 @@
         performedTest.setDoctor(doctor);
         performedTest.setLabTest(test);
-        performedTest.setTestDate(testDate != null ? testDate : LocalDate.now());
+        LocalDate finalTestDate = testDate != null ? testDate : LocalDate.now();
+        performedTest.setTestDate(finalTestDate);
         performedTest.setNotes(notes);
 
         logger.info("Lab test {} requested for patient {} by doctor {}", testId, patientId, doctorId);
-        return performedLabTestRepository.save(performedTest);
+        PerformedLabTests saved = performedLabTestRepository.save(performedTest);
+
+        // Auto-generate billing for the patient on this date
+        billingService.autoGenerateBillingForPatientService(patientId, finalTestDate);
+
+        return saved;
     }
 
@@ -163,5 +172,5 @@
     }
 
-    //  LAB RESULTS (UC014, UC015)
+    // ================= LAB RESULTS (UC014, UC015) =================
 
     @Transactional
@@ -193,5 +202,6 @@
         LabResults saved = labResultsRepository.save(labResult);
 
-
+        // Use the join repository to safely link (avoid deleting existing links)
+        // Create and save the join entity explicitly
         MedicalRecordLabResults link = new MedicalRecordLabResults();
         link.setMedicalRecord(medicalRecord);
Index: backend/src/main/java/medora/service/ProcedureService.java
===================================================================
--- backend/src/main/java/medora/service/ProcedureService.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/service/ProcedureService.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -29,4 +29,5 @@
     private final MedicalRecordProcedureResultRepository medicalRecordProcedureResultRepository;
     private final EntityManager entityManager;
+    private final BillingService billingService;
 
     public ProcedureService(PerformedProcedureRepository performedProcedureRepository,
@@ -39,5 +40,6 @@
                             ProcedureResultRepository procedureResultRepository,
                             MedicalRecordProcedureResultRepository medicalRecordProcedureResultRepository,
-                            EntityManager entityManager) {
+                            EntityManager entityManager,
+                            BillingService billingService) {
 
         this.performedProcedureRepository = performedProcedureRepository;
@@ -51,4 +53,5 @@
         this.medicalRecordProcedureResultRepository = medicalRecordProcedureResultRepository;
         this.entityManager = entityManager;
+        this.billingService = billingService;
     }
 
@@ -97,5 +100,10 @@
 
         logger.info("Requested procedure {} for patient {} by doctor {}", procedureId, patientId, doctorId);
-        return performedProcedureRepository.saveAndFlush(performed);
+        PerformedProcedures saved = performedProcedureRepository.saveAndFlush(performed);
+
+        // Auto-generate billing for the patient on this date
+        billingService.autoGenerateBillingForPatientService(patientId, procedureDate);
+
+        return saved;
     }
 
@@ -142,5 +150,10 @@
 
         logger.info("Recorded procedure {} for patient {}", procedureId, patientId);
-        return performedProcedureRepository.saveAndFlush(performed);
+        PerformedProcedures saved = performedProcedureRepository.saveAndFlush(performed);
+
+        // Auto-generate billing for the patient on this date
+        billingService.autoGenerateBillingForPatientService(patientId, procedureDate);
+
+        return saved;
     }
 
Index: backend/src/main/java/medora/service/ReferralService.java
===================================================================
--- backend/src/main/java/medora/service/ReferralService.java	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ backend/src/main/java/medora/service/ReferralService.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -1,10 +1,10 @@
 package medora.service;
 
+import medora.models.domain.Referrals;
 import medora.models.domain.Doctors;
-import medora.models.domain.Referrals;
+import medora.repository.ReferralRepository;
 import medora.repository.DoctorRepository;
+import medora.repository.PatientRepository;
 import medora.repository.MedicalRecordRepository;
-import medora.repository.PatientRepository;
-import medora.repository.ReferralRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -13,4 +13,5 @@
 
 import java.time.LocalDate;
+import java.time.LocalTime;
 import java.util.List;
 import java.util.Optional;
@@ -19,5 +20,5 @@
  * RefferalService handles referral operations.
  * UC019 – Create Referral Record
- * OPTIONAL - Use only if needed
+
  */
 @Service
@@ -30,22 +31,25 @@
     private final PatientRepository patientRepository;
     private final MedicalRecordRepository medicalRecordRepository;
+    private final AppointmentService appointmentService;
 
     public ReferralService(ReferralRepository referralRepository,
                            DoctorRepository doctorRepository,
                            PatientRepository patientRepository,
-                           MedicalRecordRepository medicalRecordRepository) {
+                           MedicalRecordRepository medicalRecordRepository,
+                           AppointmentService appointmentService) {
         this.referralRepository = referralRepository;
         this.doctorRepository = doctorRepository;
         this.patientRepository = patientRepository;
         this.medicalRecordRepository = medicalRecordRepository;
+        this.appointmentService = appointmentService;
     }
 
     /**
      * UC019 – Create Referral Record
-     * Create a referral from one doctor to another
+     * Create a referral from one doctor to another and automatically create an appointment
      */
     @Transactional
     public Referrals createReferral(Long medicalRecordId, Long fromDoctorId, Long toDoctorId,
-                                    String reason, LocalDate referralDate) {
+                                    String reason, LocalDate referralDate, LocalDate appointmentDate, LocalTime appointmentTime) {
         if (medicalRecordId == null || medicalRecordId <= 0) {
             throw new IllegalArgumentException("Medical record ID must be valid");
@@ -62,4 +66,10 @@
         if (referralDate == null) {
             throw new IllegalArgumentException("Referral date is required");
+        }
+        if (appointmentDate == null) {
+            throw new IllegalArgumentException("Appointment date is required");
+        }
+        if (appointmentTime == null) {
+            throw new IllegalArgumentException("Appointment time is required");
         }
 
@@ -83,8 +93,12 @@
         referral.setReason(reason);
         referral.setReferralDate(referralDate);
+        referral.setAppointmentDate(appointmentDate);
+        referral.setAppointmentTime(appointmentTime);
 
         logger.info("Creating referral for medical record ID: {} from doctor ID: {} to doctor ID: {}",
                 medicalRecordId, fromDoctorId, toDoctorId);
-        return referralRepository.save(referral);
+        Referrals savedReferral = referralRepository.save(referral);
+
+        return savedReferral;
     }
 
@@ -143,3 +157,15 @@
         return referralRepository.findIncomingReferralsForDoctor(doctorId);
     }
+
+
+    @Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW)
+    private void createAppointmentForReferral(Long patientId, Long doctorId, LocalDate appointmentDate, LocalTime appointmentTime) {
+        try {
+            appointmentService.createAppointment(patientId, doctorId, appointmentDate, appointmentTime);
+            logger.info("Automatically created appointment for patient ID: {} with doctor ID: {} on {} at {}",
+                    patientId, doctorId, appointmentDate, appointmentTime);
+        } catch (RuntimeException e) {
+            logger.warn("Failed to create appointment for referral. Error: {}", e.getMessage());
+        }
+    }
 }
Index: backend/src/main/java/medora/util/BillingPDFGenerator.java
===================================================================
--- backend/src/main/java/medora/util/BillingPDFGenerator.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
+++ backend/src/main/java/medora/util/BillingPDFGenerator.java	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -0,0 +1,137 @@
+package medora.util;
+
+import com.itextpdf.kernel.pdf.PdfDocument;
+import com.itextpdf.kernel.pdf.PdfWriter;
+import com.itextpdf.layout.Document;
+import com.itextpdf.layout.element.Paragraph;
+import com.itextpdf.layout.element.Table;
+import com.itextpdf.layout.element.Cell;
+import medora.dto.BillingDetailDTO;
+import medora.dto.BillingItemDTO;
+
+import java.io.ByteArrayOutputStream;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+public class BillingPDFGenerator {
+
+    public static byte[] generateInvoicePDF(BillingDetailDTO billingDetail) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+        try {
+            PdfWriter writer = new PdfWriter(outputStream);
+            PdfDocument pdfDoc = new PdfDocument(writer);
+            Document document = new Document(pdfDoc);
+            document.setMargins(20, 20, 20, 20);
+
+            // Header
+            Paragraph title = new Paragraph("MEDICAL BILLING INVOICE")
+                    .setFontSize(24)
+                    .setBold();
+            document.add(title);
+
+            // Bill Information
+            Paragraph billInfo = new Paragraph()
+                    .add("Bill #: " + billingDetail.getBillId())
+                    .add("\nDate: " + formatDate(billingDetail.getBillDate()))
+                    .setFontSize(11);
+            document.add(billInfo);
+
+            document.add(new Paragraph("\n"));
+
+            // Patient Information Section
+            Paragraph patientHeader = new Paragraph("PATIENT INFORMATION")
+                    .setBold()
+                    .setFontSize(12);
+            document.add(patientHeader);
+
+            Paragraph patientInfo = new Paragraph()
+                    .add("Name: " + billingDetail.getPatientName())
+                    .add("\nEMBG: " + billingDetail.getPatientEmbg())
+                    .add("\nPhone: " + billingDetail.getPatientPhone())
+                    .setFontSize(10);
+            document.add(patientInfo);
+
+            document.add(new Paragraph("\n"));
+
+            // Services Table
+            Paragraph servicesHeader = new Paragraph("ITEMIZED SERVICES")
+                    .setBold()
+                    .setFontSize(12);
+            document.add(servicesHeader);
+
+            // Create table with 2 columns
+            Table table = new Table(new float[]{5, 2});
+
+            // Table header
+            Cell descriptionHeader = new Cell().add(new Paragraph("Description").setBold());
+            Cell costHeader = new Cell().add(new Paragraph("Cost").setBold());
+            table.addCell(descriptionHeader);
+            table.addCell(costHeader);
+
+            // Add procedures
+            if (billingDetail.getProcedures() != null && !billingDetail.getProcedures().isEmpty()) {
+                Cell procedureCategory = new Cell(1, 2).add(new Paragraph("PROCEDURES").setBold());
+                table.addCell(procedureCategory);
+
+                for (BillingItemDTO procedure : billingDetail.getProcedures()) {
+                    table.addCell(new Cell().add(new Paragraph(procedure.getDescription())));
+                    table.addCell(new Cell().add(new Paragraph("$" + procedure.getCost())));
+                }
+            }
+
+            // Add lab tests
+            if (billingDetail.getLabTests() != null && !billingDetail.getLabTests().isEmpty()) {
+                Cell labTestCategory = new Cell(1, 2).add(new Paragraph("LAB TESTS").setBold());
+                table.addCell(labTestCategory);
+
+                for (BillingItemDTO labTest : billingDetail.getLabTests()) {
+                    table.addCell(new Cell().add(new Paragraph(labTest.getDescription())));
+                    table.addCell(new Cell().add(new Paragraph("$" + labTest.getCost())));
+                }
+            }
+
+            // Total row
+            Cell totalLabel = new Cell().add(new Paragraph("TOTAL:").setBold());
+            Cell totalAmount = new Cell().add(new Paragraph("$" + billingDetail.getTotalCost())
+                    .setBold()
+                    .setFontSize(12));
+            table.addCell(totalLabel);
+            table.addCell(totalAmount);
+
+            document.add(table);
+
+            document.add(new Paragraph("\n"));
+
+            // Payment Status
+            Paragraph paymentStatus = new Paragraph()
+                    .add("Payment Status: " + billingDetail.getPaymentStatus())
+                    .setFontSize(11);
+            if ("PAID".equals(billingDetail.getPaymentStatus())) {
+                paymentStatus.add("\nPayment Date: " + formatDate(billingDetail.getPaymentDate()));
+            }
+            document.add(paymentStatus);
+
+            document.add(new Paragraph("\n\n"));
+
+            // Footer
+            Paragraph footer = new Paragraph("Thank you for your business.")
+                    .setFontSize(10);
+            document.add(footer);
+
+            document.close();
+            return outputStream.toByteArray();
+
+        } catch (Exception e) {
+            throw new RuntimeException("Error generating PDF: " + e.getMessage(), e);
+        }
+    }
+
+    private static String formatDate(LocalDate date) {
+        if (date == null) {
+            return "N/A";
+        }
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        return date.format(formatter);
+    }
+}
Index: pom.xml
===================================================================
--- pom.xml	(revision 0e894d2e555e067c016c7808133cdfce21ce9fbe)
+++ pom.xml	(revision a95bd1b9389a87171a521267d3f382aaedf66d7f)
@@ -10,8 +10,8 @@
     </parent>
     <groupId>medora</groupId>
-    <artifactId>medora5</artifactId>
+    <artifactId>medora4</artifactId>
     <version>0.0.1-SNAPSHOT</version>
-    <name>medora5</name>
-    <description>medora5</description>
+    <name>medora4</name>
+    <description>medora4</description>
     <url/>
     <licenses>
@@ -75,4 +75,21 @@
             <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
+
+        <!-- iText for PDF generation -->
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>kernel</artifactId>
+            <version>7.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>layout</artifactId>
+            <version>7.2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>io</artifactId>
+            <version>7.2.5</version>
+        </dependency>
     </dependencies>
 
