# """ # Viewflow workflows for radiology app. # Provides imaging order processing, study execution, and report generation workflows. # """ # # from viewflow import Flow, lock # from viewflow.base import this, flow_func # from viewflow.contrib import celery # from viewflow.decorators import flow_view # from viewflow.fields import CharField, ModelField # from viewflow.forms import ModelForm # from viewflow.views import CreateProcessView, UpdateProcessView # from viewflow.models import Process, Task # from django.contrib.auth.models import User # from django.urls import reverse_lazy # from django.utils import timezone # from django.db import transaction # from django.core.mail import send_mail # # from .models import ImagingOrder, ImagingStudy, RadiologyReport, ReportTemplate # from .views import ( # ImagingOrderView, OrderVerificationView, StudySchedulingView, # PatientPreparationView, StudyExecutionView, ImageQualityCheckView, # ReportDictationView, ReportTranscriptionView, ReportVerificationView, # CriticalFindingNotificationView # ) # # # class ImagingOrderProcess(Process): # """ # Viewflow process model for imaging orders # """ # imaging_order = ModelField(ImagingOrder, help_text='Associated imaging order') # # # Process status tracking # order_received = models.BooleanField(default=False) # order_verified = models.BooleanField(default=False) # study_scheduled = models.BooleanField(default=False) # patient_prepared = models.BooleanField(default=False) # study_completed = models.BooleanField(default=False) # images_reviewed = models.BooleanField(default=False) # report_dictated = models.BooleanField(default=False) # report_finalized = models.BooleanField(default=False) # results_communicated = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Imaging Order Process' # verbose_name_plural = 'Imaging Order Processes' # # # class ImagingOrderFlow(Flow): # """ # Imaging Order Workflow # # This flow manages the complete imaging process from order receipt # through study execution and report delivery. # """ # # process_class = ImagingOrderProcess # # # Flow definition # start = ( # flow_func(this.start_imaging_order) # .Next(this.receive_order) # ) # # receive_order = ( # flow_view(ImagingOrderView) # .Permission('radiology.can_receive_orders') # .Next(this.verify_order) # ) # # verify_order = ( # flow_view(OrderVerificationView) # .Permission('radiology.can_verify_orders') # .Next(this.schedule_study) # ) # # schedule_study = ( # flow_view(StudySchedulingView) # .Permission('radiology.can_schedule_studies') # .Next(this.prepare_patient) # ) # # prepare_patient = ( # flow_view(PatientPreparationView) # .Permission('radiology.can_prepare_patients') # .Next(this.execute_study) # ) # # execute_study = ( # flow_view(StudyExecutionView) # .Permission('radiology.can_execute_studies') # .Next(this.review_images) # ) # # review_images = ( # flow_view(ImageQualityCheckView) # .Permission('radiology.can_review_images') # .Next(this.dictate_report) # ) # # dictate_report = ( # flow_view(ReportDictationView) # .Permission('radiology.can_dictate_reports') # .Next(this.transcribe_report) # ) # # transcribe_report = ( # flow_view(ReportTranscriptionView) # .Permission('radiology.can_transcribe_reports') # .Next(this.verify_report) # ) # # verify_report = ( # flow_view(ReportVerificationView) # .Permission('radiology.can_verify_reports') # .Next(this.check_critical_findings) # ) # # check_critical_findings = ( # flow_func(this.assess_critical_findings) # .Next(this.finalize_report) # ) # # finalize_report = ( # flow_func(this.complete_imaging_order) # .Next(this.end) # ) # # end = flow_func(this.end_imaging_order) # # # Flow functions # def start_imaging_order(self, activation): # """Initialize the imaging order process""" # process = activation.process # order = process.imaging_order # # # Update order status # order.status = 'RECEIVED' # order.save() # # # Send notification to radiology staff # self.notify_radiology_staff(order) # # # Check for STAT orders # if order.priority in ['STAT', 'EMERGENCY']: # self.notify_stat_order(order) # # def assess_critical_findings(self, activation): # """Check for critical findings and handle notifications""" # process = activation.process # order = process.imaging_order # # # Get the associated report # try: # report = RadiologyReport.objects.get(study__imaging_order=order) # # if report.critical_finding: # # Handle critical finding notification # self.handle_critical_finding(report) # # # Mark as critical communicated # report.critical_communicated = True # report.critical_communicated_datetime = timezone.now() # report.save() # except RadiologyReport.DoesNotExist: # pass # # def complete_imaging_order(self, activation): # """Finalize the imaging order process""" # process = activation.process # order = process.imaging_order # # # Update order status # order.status = 'COMPLETED' # order.completion_datetime = timezone.now() # order.save() # # # Mark process as completed # process.results_communicated = True # process.save() # # # Send completion notifications # self.notify_order_completion(order) # # # Update quality metrics # self.update_quality_metrics(order) # # def end_imaging_order(self, activation): # """End the imaging order workflow""" # process = activation.process # # # Generate order summary report # self.generate_order_summary(process.imaging_order) # # # Helper methods # def notify_radiology_staff(self, order): # """Notify radiology staff of new order""" # from django.contrib.auth.models import Group # # radiology_staff = User.objects.filter( # groups__name='Radiology Staff' # ) # # for staff in radiology_staff: # send_mail( # subject=f'New Imaging Order: {order.order_number}', # message=f'New {order.get_priority_display()} imaging order for {order.patient.get_full_name()}.', # from_email='radiology@hospital.com', # recipient_list=[staff.email], # fail_silently=True # ) # # def notify_stat_order(self, order): # """Notify of STAT imaging order""" # radiologists = User.objects.filter( # groups__name='Radiologists' # ) # # for radiologist in radiologists: # send_mail( # subject=f'STAT Imaging Order: {order.order_number}', # message=f'{order.get_priority_display()} imaging order requires immediate attention.', # from_email='radiology@hospital.com', # recipient_list=[radiologist.email], # fail_silently=True # ) # # def handle_critical_finding(self, report): # """Handle critical finding notification""" # # Notify ordering physician immediately # if report.study.referring_physician and report.study.referring_physician.email: # send_mail( # subject=f'CRITICAL FINDING: {report.study.accession_number}', # message=f'Critical finding identified in imaging study. Please review immediately.', # from_email='radiology@hospital.com', # recipient_list=[report.study.referring_physician.email], # fail_silently=True # ) # # # Notify radiology supervisor # supervisors = User.objects.filter( # groups__name='Radiology Supervisors' # ) # # for supervisor in supervisors: # send_mail( # subject=f'Critical Finding Communicated: {report.study.accession_number}', # message=f'Critical finding has been communicated for study {report.study.accession_number}.', # from_email='radiology@hospital.com', # recipient_list=[supervisor.email], # fail_silently=True # ) # # def notify_order_completion(self, order): # """Notify ordering physician of completed study""" # if order.ordering_provider and order.ordering_provider.email: # send_mail( # subject=f'Imaging Results Available: {order.order_number}', # message=f'Imaging results are now available for {order.patient.get_full_name()}.', # from_email='radiology@hospital.com', # recipient_list=[order.ordering_provider.email], # fail_silently=True # ) # # def update_quality_metrics(self, order): # """Update radiology quality metrics""" # # This would update quality and performance metrics # pass # # def generate_order_summary(self, order): # """Generate imaging order summary report""" # # This would generate a comprehensive order report # pass # # # class RadiologyReportProcess(Process): # """ # Viewflow process model for radiology reports # """ # radiology_report = ModelField(RadiologyReport, help_text='Associated radiology report') # # # Process status tracking # report_initiated = models.BooleanField(default=False) # preliminary_read = models.BooleanField(default=False) # report_dictated = models.BooleanField(default=False) # report_transcribed = models.BooleanField(default=False) # report_reviewed = models.BooleanField(default=False) # report_signed = models.BooleanField(default=False) # report_distributed = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Radiology Report Process' # verbose_name_plural = 'Radiology Report Processes' # # # class RadiologyReportFlow(Flow): # """ # Radiology Report Workflow # # This flow manages the radiology reporting process from initial # interpretation through final report distribution. # """ # # process_class = RadiologyReportProcess # # # Flow definition # start = ( # flow_func(this.start_report) # .Next(this.preliminary_interpretation) # ) # # preliminary_interpretation = ( # flow_view(PreliminaryInterpretationView) # .Permission('radiology.can_preliminary_interpret') # .Next(this.dictate_report) # ) # # dictate_report = ( # flow_view(ReportDictationView) # .Permission('radiology.can_dictate_reports') # .Next(this.transcribe_report) # ) # # transcribe_report = ( # flow_view(ReportTranscriptionView) # .Permission('radiology.can_transcribe_reports') # .Next(this.review_report) # ) # # review_report = ( # flow_view(ReportReviewView) # .Permission('radiology.can_review_reports') # .Next(this.sign_report) # ) # # sign_report = ( # flow_view(ReportSigningView) # .Permission('radiology.can_sign_reports') # .Next(this.distribute_report) # ) # # distribute_report = ( # flow_func(this.complete_report) # .Next(this.end) # ) # # end = flow_func(this.end_report) # # # Flow functions # def start_report(self, activation): # """Initialize the report process""" # process = activation.process # report = process.radiology_report # # # Update report status # report.status = 'DRAFT' # report.save() # # # Assign to radiologist # self.assign_radiologist(report) # # def complete_report(self, activation): # """Finalize the report process""" # process = activation.process # report = process.radiology_report # # # Update report status # report.status = 'FINAL' # report.finalized_datetime = timezone.now() # report.save() # # # Mark process as completed # process.report_distributed = True # process.save() # # # Send distribution notifications # self.distribute_final_report(report) # # def end_report(self, activation): # """End the report workflow""" # process = activation.process # # # Generate report metrics # self.generate_report_metrics(process.radiology_report) # # # Helper methods # def assign_radiologist(self, report): # """Assign radiologist to report""" # # This would implement radiologist assignment logic # pass # # def distribute_final_report(self, report): # """Distribute final report""" # # Notify referring physician # if report.study.referring_physician and report.study.referring_physician.email: # send_mail( # subject=f'Final Report Available: {report.study.accession_number}', # message=f'Final radiology report is available for {report.study.patient.get_full_name()}.', # from_email='radiology@hospital.com', # recipient_list=[report.study.referring_physician.email], # fail_silently=True # ) # # def generate_report_metrics(self, report): # """Generate report performance metrics""" # # This would generate reporting metrics # pass # # # class QualityAssuranceProcess(Process): # """ # Viewflow process model for radiology quality assurance # """ # study_id = CharField(max_length=50, help_text='Study identifier') # qa_type = CharField(max_length=20, help_text='Type of QA review') # # # Process status tracking # qa_initiated = models.BooleanField(default=False) # images_reviewed = models.BooleanField(default=False) # report_reviewed = models.BooleanField(default=False) # discrepancies_identified = models.BooleanField(default=False) # feedback_provided = models.BooleanField(default=False) # qa_completed = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Quality Assurance Process' # verbose_name_plural = 'Quality Assurance Processes' # # # class QualityAssuranceFlow(Flow): # """ # Radiology Quality Assurance Workflow # # This flow manages quality assurance reviews including # image quality, report accuracy, and peer review. # """ # # process_class = QualityAssuranceProcess # # # Flow definition # start = ( # flow_func(this.start_qa_review) # .Next(this.review_images) # ) # # review_images = ( # flow_view(ImageQualityReviewView) # .Permission('radiology.can_review_image_quality') # .Next(this.review_report) # ) # # review_report = ( # flow_view(ReportQualityReviewView) # .Permission('radiology.can_review_report_quality') # .Next(this.identify_discrepancies) # ) # # identify_discrepancies = ( # flow_func(this.assess_discrepancies) # .Next(this.provide_feedback) # ) # # provide_feedback = ( # flow_view(QAFeedbackView) # .Permission('radiology.can_provide_qa_feedback') # .Next(this.finalize_qa) # ) # # finalize_qa = ( # flow_func(this.complete_qa_review) # .Next(this.end) # ) # # end = flow_func(this.end_qa_review) # # # Flow functions # def start_qa_review(self, activation): # """Initialize the QA review process""" # process = activation.process # # # Notify QA staff # self.notify_qa_staff(process.study_id, process.qa_type) # # def assess_discrepancies(self, activation): # """Assess for discrepancies""" # process = activation.process # # # Check for discrepancies # discrepancies = self.check_discrepancies(process.study_id) # # if discrepancies: # process.discrepancies_identified = True # process.save() # # # Alert QA supervisor # self.alert_qa_supervisor(process.study_id, discrepancies) # # def complete_qa_review(self, activation): # """Finalize the QA review process""" # process = activation.process # # # Mark QA as completed # process.qa_completed = True # process.save() # # # Generate QA report # self.generate_qa_report(process.study_id, process.qa_type) # # def end_qa_review(self, activation): # """End the QA review workflow""" # process = activation.process # # # Update QA metrics # self.update_qa_metrics(process.study_id, process.qa_type) # # # Helper methods # def notify_qa_staff(self, study_id, qa_type): # """Notify QA staff""" # qa_staff = User.objects.filter( # groups__name='Radiology QA' # ) # # for staff in qa_staff: # send_mail( # subject=f'QA Review Required: {study_id}', # message=f'{qa_type} QA review required for study {study_id}.', # from_email='radiology@hospital.com', # recipient_list=[staff.email], # fail_silently=True # ) # # def check_discrepancies(self, study_id): # """Check for discrepancies""" # # This would implement discrepancy checking logic # return [] # # def alert_qa_supervisor(self, study_id, discrepancies): # """Alert QA supervisor of discrepancies""" # supervisors = User.objects.filter( # groups__name='Radiology QA Supervisors' # ) # # for supervisor in supervisors: # send_mail( # subject=f'QA Discrepancies Found: {study_id}', # message=f'Quality assurance discrepancies identified for study {study_id}.', # from_email='radiology@hospital.com', # recipient_list=[supervisor.email], # fail_silently=True # ) # # def generate_qa_report(self, study_id, qa_type): # """Generate QA report""" # # This would generate QA report # pass # # def update_qa_metrics(self, study_id, qa_type): # """Update QA metrics""" # # This would update QA metrics # pass # # # class EquipmentMaintenanceProcess(Process): # """ # Viewflow process model for radiology equipment maintenance # """ # equipment_id = CharField(max_length=50, help_text='Equipment identifier') # maintenance_type = CharField(max_length=20, help_text='Type of maintenance') # # # Process status tracking # maintenance_scheduled = models.BooleanField(default=False) # equipment_inspected = models.BooleanField(default=False) # maintenance_performed = models.BooleanField(default=False) # quality_testing_completed = models.BooleanField(default=False) # equipment_calibrated = models.BooleanField(default=False) # equipment_returned = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Equipment Maintenance Process' # verbose_name_plural = 'Equipment Maintenance Processes' # # # class EquipmentMaintenanceFlow(Flow): # """ # Radiology Equipment Maintenance Workflow # # This flow manages equipment maintenance including scheduling, # inspection, repair, calibration, and quality testing. # """ # # process_class = EquipmentMaintenanceProcess # # # Flow definition # start = ( # flow_func(this.start_equipment_maintenance) # .Next(this.schedule_maintenance) # ) # # schedule_maintenance = ( # flow_view(MaintenanceSchedulingView) # .Permission('radiology.can_schedule_maintenance') # .Next(this.inspect_equipment) # ) # # inspect_equipment = ( # flow_view(EquipmentInspectionView) # .Permission('radiology.can_inspect_equipment') # .Next(this.perform_maintenance) # ) # # perform_maintenance = ( # flow_view(MaintenanceExecutionView) # .Permission('radiology.can_perform_maintenance') # .Next(this.quality_testing) # ) # # quality_testing = ( # flow_view(QualityTestingView) # .Permission('radiology.can_perform_quality_testing') # .Next(this.calibrate_equipment) # ) # # calibrate_equipment = ( # flow_view(EquipmentCalibrationView) # .Permission('radiology.can_calibrate_equipment') # .Next(this.return_equipment) # ) # # return_equipment = ( # flow_func(this.complete_equipment_maintenance) # .Next(this.end) # ) # # end = flow_func(this.end_equipment_maintenance) # # # Flow functions # def start_equipment_maintenance(self, activation): # """Initialize the equipment maintenance process""" # process = activation.process # # # Notify maintenance staff # self.notify_maintenance_staff(process.equipment_id, process.maintenance_type) # # # Take equipment offline # self.take_equipment_offline(process.equipment_id) # # def complete_equipment_maintenance(self, activation): # """Finalize the equipment maintenance process""" # process = activation.process # # # Mark equipment as available # self.return_equipment_to_service(process.equipment_id) # # # Mark process as completed # process.equipment_returned = True # process.save() # # # Notify completion # self.notify_maintenance_completion(process.equipment_id) # # def end_equipment_maintenance(self, activation): # """End the equipment maintenance workflow""" # process = activation.process # # # Generate maintenance report # self.generate_maintenance_report(process.equipment_id, process.maintenance_type) # # # Helper methods # def notify_maintenance_staff(self, equipment_id, maintenance_type): # """Notify maintenance staff""" # maintenance_staff = User.objects.filter( # groups__name='Radiology Maintenance' # ) # # for staff in maintenance_staff: # send_mail( # subject=f'Equipment Maintenance Required: {equipment_id}', # message=f'{maintenance_type} maintenance required for equipment {equipment_id}.', # from_email='maintenance@hospital.com', # recipient_list=[staff.email], # fail_silently=True # ) # # def take_equipment_offline(self, equipment_id): # """Take equipment offline for maintenance""" # # This would update equipment status # pass # # def return_equipment_to_service(self, equipment_id): # """Return equipment to service""" # # This would update equipment status # pass # # def notify_maintenance_completion(self, equipment_id): # """Notify maintenance completion""" # # This would notify relevant staff # pass # # def generate_maintenance_report(self, equipment_id, maintenance_type): # """Generate maintenance report""" # # This would generate maintenance report # pass # # # # Celery tasks for background processing # @celery.job # def auto_schedule_studies(): # """Background task to automatically schedule imaging studies""" # try: # # This would perform automated study scheduling # return True # except Exception: # return False # # # @celery.job # def monitor_report_turnaround_times(): # """Background task to monitor report turnaround times""" # try: # # This would monitor reporting performance # return True # except Exception: # return False # # # @celery.job # def generate_radiology_metrics(): # """Background task to generate radiology performance metrics""" # try: # # This would generate performance reports # return True # except Exception: # return False # # # @celery.job # def auto_assign_radiologists(): # """Background task to automatically assign radiologists to studies""" # try: # # This would auto-assign radiologists # return True # except Exception: # return False #