# """ # Viewflow workflows for pharmacy app. # Provides prescription processing, dispensing, and medication administration 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 Prescription, DispenseRecord, MedicationAdministration, DrugInteraction # from .views import ( # PrescriptionReviewView, DrugInteractionCheckView, InventoryCheckView, # MedicationPreparationView, PharmacistVerificationView, DispenseView, # PatientCounselingView, MedicationAdministrationView # ) # # # class PrescriptionProcess(Process): # """ # Viewflow process model for prescription processing # """ # prescription = ModelField(Prescription, help_text='Associated prescription') # # # Process status tracking # prescription_received = models.BooleanField(default=False) # clinical_review_completed = models.BooleanField(default=False) # drug_interactions_checked = models.BooleanField(default=False) # inventory_verified = models.BooleanField(default=False) # medication_prepared = models.BooleanField(default=False) # pharmacist_verified = models.BooleanField(default=False) # patient_counseled = models.BooleanField(default=False) # dispensed = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Prescription Process' # verbose_name_plural = 'Prescription Processes' # # # class PrescriptionFlow(Flow): # """ # Pharmacy Prescription Processing Workflow # # This flow manages the complete prescription processing from # receipt through dispensing and patient counseling. # """ # # process_class = PrescriptionProcess # # # Flow definition # start = ( # flow_func(this.start_prescription) # .Next(this.clinical_review) # ) # # clinical_review = ( # flow_view(PrescriptionReviewView) # .Permission('pharmacy.can_review_prescriptions') # .Next(this.check_drug_interactions) # ) # # check_drug_interactions = ( # flow_view(DrugInteractionCheckView) # .Permission('pharmacy.can_check_interactions') # .Next(this.verify_inventory) # ) # # verify_inventory = ( # flow_view(InventoryCheckView) # .Permission('pharmacy.can_check_inventory') # .Next(this.prepare_medication) # ) # # prepare_medication = ( # flow_view(MedicationPreparationView) # .Permission('pharmacy.can_prepare_medications') # .Next(this.pharmacist_verification) # ) # # pharmacist_verification = ( # flow_view(PharmacistVerificationView) # .Permission('pharmacy.can_verify_prescriptions') # .Next(this.dispense_medication) # ) # # dispense_medication = ( # flow_view(DispenseView) # .Permission('pharmacy.can_dispense_medications') # .Next(this.patient_counseling) # ) # # patient_counseling = ( # flow_view(PatientCounselingView) # .Permission('pharmacy.can_counsel_patients') # .Next(this.finalize_prescription) # ) # # finalize_prescription = ( # flow_func(this.complete_prescription) # .Next(this.end) # ) # # end = flow_func(this.end_prescription) # # # Flow functions # def start_prescription(self, activation): # """Initialize the prescription process""" # process = activation.process # prescription = process.prescription # # # Update prescription status # prescription.status = 'RECEIVED' # prescription.save() # # # Send notification to pharmacy staff # self.notify_pharmacy_staff(prescription) # # # Check for priority prescriptions # if prescription.priority in ['STAT', 'URGENT']: # self.notify_priority_prescription(prescription) # # def complete_prescription(self, activation): # """Finalize the prescription process""" # process = activation.process # prescription = process.prescription # # # Update prescription status # prescription.status = 'COMPLETED' # prescription.save() # # # Mark process as completed # process.dispensed = True # process.save() # # # Send completion notifications # self.notify_prescription_completion(prescription) # # # Schedule follow-up if needed # self.schedule_follow_up(prescription) # # def end_prescription(self, activation): # """End the prescription workflow""" # process = activation.process # # # Generate prescription summary report # self.generate_prescription_summary(process.prescription) # # # Helper methods # def notify_pharmacy_staff(self, prescription): # """Notify pharmacy staff of new prescription""" # from django.contrib.auth.models import Group # # pharmacy_staff = User.objects.filter( # groups__name='Pharmacy Staff' # ) # # for staff in pharmacy_staff: # send_mail( # subject=f'New Prescription: {prescription.prescription_number}', # message=f'New {prescription.get_priority_display()} prescription for {prescription.patient.get_full_name()}.', # from_email='pharmacy@hospital.com', # recipient_list=[staff.email], # fail_silently=True # ) # # def notify_priority_prescription(self, prescription): # """Notify of high priority prescription""" # pharmacists = User.objects.filter( # groups__name='Pharmacists' # ) # # for pharmacist in pharmacists: # send_mail( # subject=f'PRIORITY Prescription: {prescription.prescription_number}', # message=f'{prescription.get_priority_display()} prescription requires immediate attention.', # from_email='pharmacy@hospital.com', # recipient_list=[pharmacist.email], # fail_silently=True # ) # # def notify_prescription_completion(self, prescription): # """Notify prescribing physician of completion""" # if prescription.prescribing_physician and prescription.prescribing_physician.email: # send_mail( # subject=f'Prescription Dispensed: {prescription.prescription_number}', # message=f'Prescription has been dispensed for {prescription.patient.get_full_name()}.', # from_email='pharmacy@hospital.com', # recipient_list=[prescription.prescribing_physician.email], # fail_silently=True # ) # # def schedule_follow_up(self, prescription): # """Schedule follow-up for certain medications""" # # This would schedule follow-up based on medication type # pass # # def generate_prescription_summary(self, prescription): # """Generate prescription summary report""" # # This would generate a comprehensive prescription report # pass # # # class MedicationAdministrationProcess(Process): # """ # Viewflow process model for medication administration # """ # administration = ModelField(MedicationAdministration, help_text='Associated administration record') # # # Process status tracking # medication_prepared = models.BooleanField(default=False) # patient_identified = models.BooleanField(default=False) # medication_verified = models.BooleanField(default=False) # administration_completed = models.BooleanField(default=False) # response_documented = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Medication Administration Process' # verbose_name_plural = 'Medication Administration Processes' # # # class MedicationAdministrationFlow(Flow): # """ # Medication Administration Workflow # # This flow manages the medication administration process for inpatients # following the "5 Rights" of medication administration. # """ # # process_class = MedicationAdministrationProcess # # # Flow definition # start = ( # flow_func(this.start_administration) # .Next(this.prepare_medication) # ) # # prepare_medication = ( # flow_view(MedicationPreparationView) # .Permission('pharmacy.can_prepare_medications') # .Next(this.verify_patient) # ) # # verify_patient = ( # flow_view(PatientIdentificationView) # .Permission('pharmacy.can_administer_medications') # .Next(this.verify_medication) # ) # # verify_medication = ( # flow_view(MedicationVerificationView) # .Permission('pharmacy.can_administer_medications') # .Next(this.administer_medication) # ) # # administer_medication = ( # flow_view(MedicationAdministrationView) # .Permission('pharmacy.can_administer_medications') # .Next(this.document_response) # ) # # document_response = ( # flow_view(AdministrationDocumentationView) # .Permission('pharmacy.can_administer_medications') # .Next(this.finalize_administration) # ) # # finalize_administration = ( # flow_func(this.complete_administration) # .Next(this.end) # ) # # end = flow_func(this.end_administration) # # # Flow functions # def start_administration(self, activation): # """Initialize the administration process""" # process = activation.process # administration = process.administration # # # Update administration status # administration.status = 'SCHEDULED' # administration.save() # # # Check for overdue medications # if administration.is_overdue: # self.notify_overdue_medication(administration) # # def complete_administration(self, activation): # """Finalize the administration process""" # process = activation.process # administration = process.administration # # # Update administration status # administration.status = 'GIVEN' # administration.actual_datetime = timezone.now() # administration.save() # # # Mark process as completed # process.administration_completed = True # process.response_documented = True # process.save() # # # Check for adverse reactions # self.check_adverse_reactions(administration) # # def end_administration(self, activation): # """End the administration workflow""" # process = activation.process # # # Update medication administration record # self.update_mar(process.administration) # # # Helper methods # def notify_overdue_medication(self, administration): # """Notify nursing staff of overdue medication""" # nursing_staff = User.objects.filter( # groups__name='Nursing Staff', # profile__department=administration.patient.current_ward # ) # # for nurse in nursing_staff: # send_mail( # subject=f'Overdue Medication: {administration.patient.get_full_name()}', # message=f'Medication administration is overdue for {administration.prescription.medication.display_name}.', # from_email='pharmacy@hospital.com', # recipient_list=[nurse.email], # fail_silently=True # ) # # def check_adverse_reactions(self, administration): # """Check for potential adverse reactions""" # # This would implement adverse reaction monitoring # pass # # def update_mar(self, administration): # """Update Medication Administration Record""" # # This would update the MAR system # pass # # # class DrugInteractionProcess(Process): # """ # Viewflow process model for drug interaction checking # """ # patient_id = CharField(max_length=50, help_text='Patient identifier') # interaction_severity = CharField(max_length=20, help_text='Interaction severity level') # # # Process status tracking # interactions_identified = models.BooleanField(default=False) # clinical_review_completed = models.BooleanField(default=False) # physician_notified = models.BooleanField(default=False) # resolution_documented = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Drug Interaction Process' # verbose_name_plural = 'Drug Interaction Processes' # # # class DrugInteractionFlow(Flow): # """ # Drug Interaction Checking Workflow # # This flow manages drug interaction checking and clinical decision support. # """ # # process_class = DrugInteractionProcess # # # Flow definition # start = ( # flow_func(this.start_interaction_check) # .Next(this.identify_interactions) # ) # # identify_interactions = ( # flow_func(this.check_drug_interactions) # .Next(this.clinical_review) # ) # # clinical_review = ( # flow_view(InteractionReviewView) # .Permission('pharmacy.can_review_interactions') # .Next(this.notify_physician) # ) # # notify_physician = ( # flow_func(this.send_physician_notification) # .Next(this.document_resolution) # ) # # document_resolution = ( # flow_view(InteractionResolutionView) # .Permission('pharmacy.can_resolve_interactions') # .Next(this.finalize_interaction_check) # ) # # finalize_interaction_check = ( # flow_func(this.complete_interaction_check) # .Next(this.end) # ) # # end = flow_func(this.end_interaction_check) # # # Flow functions # def start_interaction_check(self, activation): # """Initialize the interaction checking process""" # process = activation.process # # # Log interaction check initiation # self.log_interaction_check(process.patient_id) # # def check_drug_interactions(self, activation): # """Check for drug interactions""" # process = activation.process # # # Perform interaction checking logic # interactions = self.perform_interaction_check(process.patient_id) # # if interactions: # process.interactions_identified = True # process.interaction_severity = self.determine_severity(interactions) # process.save() # # # Alert if severe interactions found # if process.interaction_severity in ['MAJOR', 'CONTRAINDICATED']: # self.alert_severe_interaction(process.patient_id, interactions) # # def send_physician_notification(self, activation): # """Send notification to prescribing physician""" # process = activation.process # # # Notify physician of interactions # self.notify_prescribing_physician(process.patient_id, process.interaction_severity) # # process.physician_notified = True # process.save() # # def complete_interaction_check(self, activation): # """Finalize the interaction checking process""" # process = activation.process # # # Mark process as completed # process.resolution_documented = True # process.save() # # def end_interaction_check(self, activation): # """End the interaction checking workflow""" # process = activation.process # # # Generate interaction report # self.generate_interaction_report(process.patient_id) # # # Helper methods # def log_interaction_check(self, patient_id): # """Log interaction check initiation""" # # This would log the interaction check # pass # # def perform_interaction_check(self, patient_id): # """Perform drug interaction checking""" # # This would implement interaction checking logic # return [] # # def determine_severity(self, interactions): # """Determine overall severity of interactions""" # # This would determine the highest severity level # return 'MINOR' # # def alert_severe_interaction(self, patient_id, interactions): # """Alert staff of severe interactions""" # # This would send immediate alerts # pass # # def notify_prescribing_physician(self, patient_id, severity): # """Notify prescribing physician""" # # This would send notification to physician # pass # # def generate_interaction_report(self, patient_id): # """Generate interaction checking report""" # # This would generate a comprehensive interaction report # pass # # # class InventoryManagementProcess(Process): # """ # Viewflow process model for pharmacy inventory management # """ # medication_id = CharField(max_length=50, help_text='Medication identifier') # action_type = CharField(max_length=20, help_text='Inventory action type') # # # Process status tracking # stock_checked = models.BooleanField(default=False) # order_placed = models.BooleanField(default=False) # shipment_received = models.BooleanField(default=False) # inventory_updated = models.BooleanField(default=False) # # class Meta: # verbose_name = 'Inventory Management Process' # verbose_name_plural = 'Inventory Management Processes' # # # class InventoryManagementFlow(Flow): # """ # Pharmacy Inventory Management Workflow # # This flow manages pharmacy inventory including ordering, receiving, and stock management. # """ # # process_class = InventoryManagementProcess # # # Flow definition # start = ( # flow_func(this.start_inventory_management) # .Next(this.check_stock_levels) # ) # # check_stock_levels = ( # flow_func(this.monitor_stock_levels) # .Next(this.place_order) # ) # # place_order = ( # flow_view(InventoryOrderView) # .Permission('pharmacy.can_manage_inventory') # .Next(this.receive_shipment) # ) # # receive_shipment = ( # flow_view(ShipmentReceiptView) # .Permission('pharmacy.can_receive_inventory') # .Next(this.update_inventory) # ) # # update_inventory = ( # flow_func(this.update_stock_levels) # .Next(this.finalize_inventory) # ) # # finalize_inventory = ( # flow_func(this.complete_inventory_management) # .Next(this.end) # ) # # end = flow_func(this.end_inventory_management) # # # Flow functions # def start_inventory_management(self, activation): # """Initialize the inventory management process""" # process = activation.process # # # Log inventory management initiation # self.log_inventory_action(process.medication_id, process.action_type) # # def monitor_stock_levels(self, activation): # """Monitor stock levels and identify low stock""" # process = activation.process # # # Check stock levels # low_stock_items = self.check_low_stock(process.medication_id) # # if low_stock_items: # process.stock_checked = True # process.save() # # # Alert pharmacy staff of low stock # self.alert_low_stock(low_stock_items) # # def update_stock_levels(self, activation): # """Update inventory stock levels""" # process = activation.process # # # Update stock levels in system # self.update_medication_stock(process.medication_id) # # process.inventory_updated = True # process.save() # # def complete_inventory_management(self, activation): # """Finalize the inventory management process""" # process = activation.process # # # Generate inventory report # self.generate_inventory_report(process.medication_id) # # def end_inventory_management(self, activation): # """End the inventory management workflow""" # process = activation.process # # # Archive inventory transaction # self.archive_inventory_transaction(process.medication_id) # # # Helper methods # def log_inventory_action(self, medication_id, action_type): # """Log inventory action""" # # This would log the inventory action # pass # # def check_low_stock(self, medication_id): # """Check for low stock items""" # # This would check stock levels # return [] # # def alert_low_stock(self, low_stock_items): # """Alert staff of low stock""" # # This would send low stock alerts # pass # # def update_medication_stock(self, medication_id): # """Update medication stock levels""" # # This would update stock levels # pass # # def generate_inventory_report(self, medication_id): # """Generate inventory report""" # # This would generate inventory report # pass # # def archive_inventory_transaction(self, medication_id): # """Archive inventory transaction""" # # This would archive the transaction # pass # # # # Celery tasks for background processing # @celery.job # def auto_check_drug_interactions(patient_id): # """Background task to automatically check drug interactions""" # try: # # This would perform automated interaction checking # return True # except Exception: # return False # # # @celery.job # def monitor_medication_adherence(patient_id): # """Background task to monitor medication adherence""" # try: # # This would monitor patient adherence # return True # except Exception: # return False # # # @celery.job # def generate_pharmacy_reports(): # """Background task to generate daily pharmacy reports""" # try: # # This would generate daily pharmacy reports # return True # except Exception: # return False # # # @celery.job # def auto_reorder_medications(): # """Background task to automatically reorder low stock medications""" # try: # # This would automatically reorder medications # return True # except Exception: # return False #