From 23158e9fbfacc8871a884eb12e263e9ad86d42f9 Mon Sep 17 00:00:00 2001 From: Marwan Alwali Date: Mon, 8 Sep 2025 03:00:23 +0300 Subject: [PATCH] update --- .DS_Store | Bin 14340 -> 14340 bytes .idea/misc.xml | 3 + accounts/__pycache__/flows.cpython-312.pyc | Bin 0 -> 178 bytes accounts/__pycache__/forms.cpython-312.pyc | Bin 11376 -> 11376 bytes accounts/__pycache__/views.cpython-312.pyc | Bin 51414 -> 51414 bytes accounts/flows.py | 800 ++ accounts/forms.py | 718 ++ accounts/views.py | 647 ++ analytics/.DS_Store | Bin 0 -> 6148 bytes analytics/__pycache__/flows.cpython-312.pyc | Bin 0 -> 179 bytes analytics/__pycache__/forms.cpython-312.pyc | Bin 15285 -> 15285 bytes analytics/__pycache__/views.cpython-312.pyc | Bin 62343 -> 62343 bytes analytics/flows.py | 845 ++ analytics/forms.py | 721 ++ analytics/views.py | 729 +- .../__pycache__/flows.cpython-312.pyc | Bin 0 -> 182 bytes .../__pycache__/forms.cpython-312.pyc | Bin 20609 -> 20609 bytes .../__pycache__/views.cpython-312.pyc | Bin 77727 -> 77727 bytes appointments/flows.py | 871 +++ appointments/forms.py | 748 ++ appointments/views.py | 904 +++ billing/__pycache__/flows.cpython-312.pyc | Bin 0 -> 177 bytes billing/__pycache__/forms.cpython-312.pyc | Bin 23807 -> 23807 bytes billing/__pycache__/urls.cpython-312.pyc | Bin 3711 -> 3975 bytes billing/__pycache__/views.cpython-312.pyc | Bin 54833 -> 61585 bytes billing/flows.py | 1022 +++ billing/forms.py | 787 ++ billing/urls.py | 7 +- billing/views.py | 697 +- blood_bank/__pycache__/forms.cpython-312.pyc | Bin 22517 -> 22517 bytes blood_bank/__pycache__/models.cpython-312.pyc | Bin 30892 -> 30890 bytes blood_bank/__pycache__/urls.cpython-312.pyc | Bin 4951 -> 5459 bytes blood_bank/__pycache__/views.cpython-312.pyc | Bin 55314 -> 57933 bytes blood_bank/models.py | 2 +- blood_bank/urls.py | 20 +- blood_bank/views.py | 365 +- .../__pycache__/flows.cpython-312.pyc | Bin 0 -> 184 bytes communications/flows.py | 1046 +++ core/__pycache__/admin.cpython-312.pyc | Bin 6717 -> 6717 bytes core/__pycache__/flows.cpython-312.pyc | Bin 0 -> 174 bytes core/__pycache__/forms.cpython-312.pyc | Bin 14214 -> 14214 bytes core/__pycache__/models.cpython-312.pyc | Bin 29809 -> 29813 bytes core/__pycache__/views.cpython-312.pyc | Bin 70333 -> 70333 bytes core/flows.py | 849 ++ core/models.py | 39 +- db.sqlite3 | Bin 39899136 -> 40321024 bytes emr/__pycache__/flows.cpython-312.pyc | Bin 0 -> 173 bytes emr/__pycache__/urls.cpython-312.pyc | Bin 3224 -> 3225 bytes emr/flows.py | 929 +++ emr/urls.py | 2 +- .../__pycache__/settings.cpython-312.pyc | Bin 7362 -> 7391 bytes hospital_management/settings.py | 2 + hr/__pycache__/flows.cpython-312.pyc | Bin 0 -> 172 bytes hr/__pycache__/models.cpython-312.pyc | Bin 38300 -> 41289 bytes hr/__pycache__/urls.cpython-312.pyc | Bin 6667 -> 6983 bytes hr/__pycache__/views.cpython-312.pyc | Bin 54505 -> 63182 bytes hr/flows.py | 846 ++ .../0002_trainingrecord_is_certified.py | 18 + ...rainingrecord_is_certified.cpython-312.pyc | Bin 0 -> 808 bytes hr/models.py | 700 +- hr/urls.py | 3 + hr/views.py | 324 +- inpatients/__pycache__/flows.cpython-312.pyc | Bin 0 -> 180 bytes inpatients/flows.py | 757 ++ integration/__pycache__/flows.cpython-312.pyc | Bin 0 -> 181 bytes integration/flows.py | 781 ++ inventory/__pycache__/flows.cpython-312.pyc | Bin 0 -> 179 bytes inventory/flows.py | 905 +++ laboratory/__pycache__/flows.cpython-312.pyc | Bin 0 -> 180 bytes laboratory/flows.py | 523 ++ logs/hospital_management.log | 6908 +++++++++++++++++ .../__pycache__/flows.cpython-312.pyc | Bin 0 -> 187 bytes operating_theatre/flows.py | 689 ++ patients/__pycache__/flows.cpython-312.pyc | Bin 0 -> 178 bytes patients/__pycache__/views.cpython-312.pyc | Bin 127317 -> 127425 bytes patients/flows.py | 761 ++ patients/views.py | 23 +- pharmacy/__pycache__/flows.cpython-312.pyc | Bin 0 -> 178 bytes pharmacy/flows.py | 672 ++ pyproject.toml | 40 +- quality/__pycache__/flows.cpython-312.pyc | Bin 0 -> 177 bytes quality/__pycache__/forms.cpython-312.pyc | Bin 22020 -> 22020 bytes quality/__pycache__/views.cpython-312.pyc | Bin 67177 -> 67177 bytes quality/flows.py | 983 +++ radiology/__pycache__/flows.cpython-312.pyc | Bin 0 -> 179 bytes radiology/flows.py | 746 ++ templates/.DS_Store | Bin 20484 -> 20484 bytes templates/billing/bills/bill_detail.html | 2 +- templates/billing/bills/bill_form.html | 942 +-- templates/billing/bills/bill_list.html | 748 +- templates/billing/claims/claim_detail.html | 46 +- templates/billing/claims/claim_form.html | 1172 ++- templates/billing/claims/claim_list.html | 240 +- .../blood_bank/issues/blood_issue_form.html | 2 +- .../requests/blood_request_list.html | 6 +- .../transfusions/transfusion_list.html | 122 +- .../schedule_assignment_confirm_delete.html | 0 .../schedule_assignment_detail.html | 0 .../schedule_assignment_form.html | 0 .../schedule_assignment_list.html | 0 templates/hr/dashboard.html | 2 +- .../department_confirm_delete.html | 0 .../{ => departments}/department_detail.html | 6 +- .../hr/{ => departments}/department_form.html | 0 .../hr/{ => departments}/department_list.html | 78 +- templates/hr/employees/employee_detail.html | 14 +- .../{ => employees}/employee_onboarding.html | 0 templates/hr/performance_review_detail.html | 722 -- .../{ => reviews}/performance_evaluation.html | 0 .../performance_review_confirm_delete.html | 0 .../hr/reviews/performance_review_detail.html | 494 ++ .../performance_review_form.html | 0 .../performance_review_list.html | 156 +- .../hr/{ => schedules}/schedule_detail.html | 44 +- .../hr/{ => schedules}/schedule_form.html | 0 .../hr/{ => schedules}/schedule_list.html | 54 +- .../{ => schedules}/schedule_management.html | 0 .../hr/{ => schedules}/schedule_publish.html | 0 .../time_entry_approve.html | 0 .../time_entry_confirm_delete.html | 0 .../{ => time_entries}/time_entry_detail.html | 12 +- .../{ => time_entries}/time_entry_form.html | 0 .../{ => time_entries}/time_entry_list.html | 150 +- .../hr/training/training_management.html | 369 + .../training_record_confirm_delete.html | 0 .../training_record_detail.html | 96 +- .../{ => training}/training_record_form.html | 2 +- .../{ => training}/training_record_list.html | 12 +- templates/hr/training_management.html | 1203 --- uv.lock | 580 +- 130 files changed, 30974 insertions(+), 4732 deletions(-) create mode 100644 accounts/__pycache__/flows.cpython-312.pyc create mode 100644 accounts/flows.py create mode 100644 analytics/.DS_Store create mode 100644 analytics/__pycache__/flows.cpython-312.pyc create mode 100644 analytics/flows.py create mode 100644 appointments/__pycache__/flows.cpython-312.pyc create mode 100644 appointments/flows.py create mode 100644 billing/__pycache__/flows.cpython-312.pyc create mode 100644 billing/flows.py create mode 100644 communications/__pycache__/flows.cpython-312.pyc create mode 100644 communications/flows.py create mode 100644 core/__pycache__/flows.cpython-312.pyc create mode 100644 core/flows.py create mode 100644 emr/__pycache__/flows.cpython-312.pyc create mode 100644 emr/flows.py create mode 100644 hr/__pycache__/flows.cpython-312.pyc create mode 100644 hr/flows.py create mode 100644 hr/migrations/0002_trainingrecord_is_certified.py create mode 100644 hr/migrations/__pycache__/0002_trainingrecord_is_certified.cpython-312.pyc create mode 100644 inpatients/__pycache__/flows.cpython-312.pyc create mode 100644 inpatients/flows.py create mode 100644 integration/__pycache__/flows.cpython-312.pyc create mode 100644 integration/flows.py create mode 100644 inventory/__pycache__/flows.cpython-312.pyc create mode 100644 inventory/flows.py create mode 100644 laboratory/__pycache__/flows.cpython-312.pyc create mode 100644 laboratory/flows.py create mode 100644 operating_theatre/__pycache__/flows.cpython-312.pyc create mode 100644 operating_theatre/flows.py create mode 100644 patients/__pycache__/flows.cpython-312.pyc create mode 100644 patients/flows.py create mode 100644 pharmacy/__pycache__/flows.cpython-312.pyc create mode 100644 pharmacy/flows.py create mode 100644 quality/__pycache__/flows.cpython-312.pyc create mode 100644 quality/flows.py create mode 100644 radiology/__pycache__/flows.cpython-312.pyc create mode 100644 radiology/flows.py rename templates/hr/{ => assignments}/schedule_assignment_confirm_delete.html (100%) rename templates/hr/{ => assignments}/schedule_assignment_detail.html (100%) rename templates/hr/{ => assignments}/schedule_assignment_form.html (100%) rename templates/hr/{ => assignments}/schedule_assignment_list.html (100%) rename templates/hr/{ => departments}/department_confirm_delete.html (100%) rename templates/hr/{ => departments}/department_detail.html (98%) rename templates/hr/{ => departments}/department_form.html (100%) rename templates/hr/{ => departments}/department_list.html (76%) rename templates/hr/{ => employees}/employee_onboarding.html (100%) delete mode 100644 templates/hr/performance_review_detail.html rename templates/hr/{ => reviews}/performance_evaluation.html (100%) rename templates/hr/{ => reviews}/performance_review_confirm_delete.html (100%) create mode 100644 templates/hr/reviews/performance_review_detail.html rename templates/hr/{ => reviews}/performance_review_form.html (100%) rename templates/hr/{ => reviews}/performance_review_list.html (75%) rename templates/hr/{ => schedules}/schedule_detail.html (94%) rename templates/hr/{ => schedules}/schedule_form.html (100%) rename templates/hr/{ => schedules}/schedule_list.html (86%) rename templates/hr/{ => schedules}/schedule_management.html (100%) rename templates/hr/{ => schedules}/schedule_publish.html (100%) rename templates/hr/{ => time_entries}/time_entry_approve.html (100%) rename templates/hr/{ => time_entries}/time_entry_confirm_delete.html (100%) rename templates/hr/{ => time_entries}/time_entry_detail.html (97%) rename templates/hr/{ => time_entries}/time_entry_form.html (100%) rename templates/hr/{ => time_entries}/time_entry_list.html (71%) create mode 100644 templates/hr/training/training_management.html rename templates/hr/{ => training}/training_record_confirm_delete.html (100%) rename templates/hr/{ => training}/training_record_detail.html (93%) rename templates/hr/{ => training}/training_record_form.html (99%) rename templates/hr/{ => training}/training_record_list.html (98%) delete mode 100644 templates/hr/training_management.html diff --git a/.DS_Store b/.DS_Store index 6932e4b1950c54c6a5979ac789b7290df678a282..feb9a3eed36c85b7ed7370592561982ac21cd4ed 100644 GIT binary patch delta 924 zcmcIiF=!KE6n@u6?%F2yZ<3mX8hV$zB!kkl)w)ZIbWjQwoJ7eb^&0%|{+Qa(3?hYY zF1fy4T-*dHhm(U8L^mn82#RD7#lflICipJxrFTQe4#)kx_kG`c-}nDJ&7Ed7j@xcfTJUX3kC)Qr)04s2Kp0|bY|#=m}N2HMnfplyq#C6f!&tz`EO zDzYalF-4lf`=ye%Sh_4JN791hy;9i|<+S8>(<4C<+^&WR_6^^%aeP1iPy} z!OvPgkn_(`v3TJUju%EwuJKBthkpukz(@_#Gq9l*QDypz#1O1QYhdS<&hdvn8L<3w zI!qyZNm|lD#^!OwSj4+VCIIVWeuolTqYL&g+|NpY6XxT-aRFZ%^T(WJ{9xqqy^)HV w=@}g?76)5sqm)S%OcFbi_5acLcBkm!&Do3eE}N{QS~dBe8t3HwYVwmmtKFIWQ$v07Ese6tiJBRcPij?7 zuGA5p9HnE#nNpmbla!yI!!UWGZslYy{SA{R=yOk;$2mD&P;Il3fDYs4UO^GY&91V? em^MDx$FiB-;2X>2N6O-pkLtQ&Q$D#@a4G=H-Bu3( diff --git a/.idea/misc.xml b/.idea/misc.xml index 9027e22a..cfe73808 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -14,4 +14,7 @@ + + \ No newline at end of file diff --git a/accounts/__pycache__/flows.cpython-312.pyc b/accounts/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b12ee7ba93c726307781001ba4c6767ec8201e1d GIT binary patch literal 178 zcmX@j%ge<81bQ<2GV+ob7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@T6{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqMw+YoL`z(QmmhrlV4t}S5SG2!zMRBr8Fniu80+A10xU@gBTx~85tRin1L(+n4~aZ literal 0 HcmV?d00001 diff --git a/accounts/__pycache__/forms.cpython-312.pyc b/accounts/__pycache__/forms.cpython-312.pyc index 5dca14a01dd7a72efc63ec3f9aba2de1cc1e91ab..6708f72124721833020d9e6bb11410ff26ae6a80 100644 GIT binary patch delta 23 dcmewm@gaimG%qg~0}$xR?8}Jk+sK!s0{~s52QmNv delta 23 dcmewm@gaimG%qg~0}wpa?#Q^Qu#qoG2LNPK2hacj diff --git a/accounts/__pycache__/views.cpython-312.pyc b/accounts/__pycache__/views.cpython-312.pyc index 46b14088d46429693082101222a3185c96ef2911..44e99a6d8e271d47d4bb34ed706d2659f9351f7f 100644 GIT binary patch delta 25 fcmcaMk@?z0X1>$Byj%=GpeM60Lu39%z7r<^XVnN; delta 25 gcmcaMk@?z0X1>$Byj%=G@axj5j43V~`A(bw0CrRf*8l(j diff --git a/accounts/flows.py b/accounts/flows.py new file mode 100644 index 00000000..989b74ad --- /dev/null +++ b/accounts/flows.py @@ -0,0 +1,800 @@ +# """ +# Viewflow workflows for accounts app. +# Provides user management, authentication, and security workflows. +# """ +# +# from viewflow import this, jsonstore +# from viewflow.workflow import lock, flow, act +# # from viewflow.base import flow_func +# # from viewflow.workflow.base import Flow +# from viewflow.workflow import celery +# # from viewflow.decorators import flow_view +# from viewflow.jsonstore import CharField +# from viewflow.forms import ModelForm +# from viewflow.fields import ModelField +# from viewflow.workflow.flow.views import CreateProcessView, UpdateProcessView +# from viewflow.workflow.models import Process, Task +# 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 User, TwoFactorDevice, SocialAccount, UserSession, PasswordHistory +# from .views import * +# +# +# class UserOnboardingProcess(Process): +# """ +# Viewflow process model for user onboarding +# """ +# user = ModelField(User, help_text='Associated user') +# +# # Process status tracking +# registration_submitted = models.BooleanField(default=False) +# account_created = models.BooleanField(default=False) +# email_verified = models.BooleanField(default=False) +# profile_completed = models.BooleanField(default=False) +# permissions_assigned = models.BooleanField(default=False) +# security_setup = models.BooleanField(default=False) +# training_completed = models.BooleanField(default=False) +# onboarding_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'User Onboarding Process' +# verbose_name_plural = 'User Onboarding Processes' +# +# +# class UserOnboardingFlow(flow.Flow): +# """ +# User Onboarding Workflow +# +# This flow manages complete user onboarding from registration +# through account setup, security configuration, and training. +# """ +# +# process_class = UserOnboardingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_user_onboarding) +# .Next(this.register_user) +# ) +# +# register_user = ( +# flow_view(UserRegistrationView) +# .Permission('accounts.can_register_users') +# .Next(this.create_account) +# ) +# +# create_account = ( +# flow_func(this.setup_user_account) +# .Next(this.verify_email) +# ) +# +# verify_email = ( +# flow_view(AccountActivationView) +# .Permission('accounts.can_activate_accounts') +# .Next(this.complete_profile) +# ) +# +# complete_profile = ( +# flow_func(this.setup_user_profile) +# .Next(this.assign_permissions) +# ) +# +# assign_permissions = ( +# flow_view(PermissionManagementView) +# .Permission('accounts.can_manage_permissions') +# .Next(this.setup_security) +# ) +# +# setup_security = ( +# flow_view(TwoFactorSetupView) +# .Permission('accounts.can_setup_security') +# .Next(this.complete_training) +# ) +# +# complete_training = ( +# flow_func(this.assign_training_modules) +# .Next(this.finalize_onboarding) +# ) +# +# finalize_onboarding = ( +# flow_func(this.complete_user_onboarding) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_user_onboarding) +# +# # Flow functions +# def start_user_onboarding(self, activation): +# """Initialize the user onboarding process""" +# process = activation.process +# user = process.user +# +# # Send onboarding notification +# self.notify_onboarding_start(user) +# +# # Create onboarding checklist +# self.create_onboarding_checklist(user) +# +# def setup_user_account(self, activation): +# """Setup user account with initial configuration""" +# process = activation.process +# user = process.user +# +# # Configure account settings +# self.configure_account_settings(user) +# +# # Mark account created +# process.account_created = True +# process.save() +# +# # Send welcome email +# self.send_welcome_email(user) +# +# def setup_user_profile(self, activation): +# """Setup user profile information""" +# process = activation.process +# user = process.user +# +# # Complete profile setup +# self.complete_profile_setup(user) +# +# # Mark profile completed +# process.profile_completed = True +# process.save() +# +# # Generate employee ID if needed +# self.generate_employee_id(user) +# +# def assign_training_modules(self, activation): +# """Assign required training modules""" +# process = activation.process +# user = process.user +# +# # Assign role-based training +# self.assign_role_training(user) +# +# # Mark training assigned +# process.training_completed = True +# process.save() +# +# # Send training notifications +# self.notify_training_assignment(user) +# +# def complete_user_onboarding(self, activation): +# """Complete the user onboarding process""" +# process = activation.process +# user = process.user +# +# # Activate user account +# user.is_active = True +# user.save() +# +# # Mark onboarding completed +# process.onboarding_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_onboarding_completion(user) +# +# # Create initial session +# self.create_initial_session(user) +# +# def end_user_onboarding(self, activation): +# """End the user onboarding workflow""" +# process = activation.process +# +# # Generate onboarding summary +# self.generate_onboarding_summary(process.user) +# +# # Helper methods +# def notify_onboarding_start(self, user): +# """Notify onboarding start""" +# # Notify HR and IT teams +# hr_staff = User.objects.filter(groups__name='HR Staff') +# for staff in hr_staff: +# send_mail( +# subject=f'New User Onboarding: {user.get_full_name()}', +# message=f'User onboarding process started for {user.username}.', +# from_email='accounts@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def create_onboarding_checklist(self, user): +# """Create onboarding checklist""" +# # This would create a checklist for the user +# pass +# +# def configure_account_settings(self, user): +# """Configure initial account settings""" +# # This would set up default account settings +# pass +# +# def send_welcome_email(self, user): +# """Send welcome email to new user""" +# if user.email: +# send_mail( +# subject='Welcome to Hospital Management System', +# message=f'Welcome {user.get_full_name()}! Your account has been created.', +# from_email='accounts@hospital.com', +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# def complete_profile_setup(self, user): +# """Complete user profile setup""" +# # This would complete profile configuration +# pass +# +# def generate_employee_id(self, user): +# """Generate employee ID for user""" +# if not user.employee_id: +# # Generate unique employee ID +# user.employee_id = f"EMP{user.id:06d}" +# user.save() +# +# def assign_role_training(self, user): +# """Assign role-based training modules""" +# # This would assign training based on user role +# pass +# +# def notify_training_assignment(self, user): +# """Notify training assignment""" +# if user.email: +# send_mail( +# subject='Training Modules Assigned', +# message='Training modules have been assigned to your account.', +# from_email='training@hospital.com', +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# def notify_onboarding_completion(self, user): +# """Notify onboarding completion""" +# if user.email: +# send_mail( +# subject='Onboarding Complete', +# message='Your onboarding process has been completed successfully.', +# from_email='accounts@hospital.com', +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# def create_initial_session(self, user): +# """Create initial user session""" +# # This would create the first user session +# pass +# +# def generate_onboarding_summary(self, user): +# """Generate onboarding summary""" +# # This would generate onboarding completion report +# pass +# +# +# class SecurityManagementProcess(Process): +# """ +# Viewflow process model for security management +# """ +# user = ModelField(User, help_text='Associated user') +# +# # Process status tracking +# security_assessment = models.BooleanField(default=False) +# two_factor_setup = models.BooleanField(default=False) +# password_policy_applied = models.BooleanField(default=False) +# session_configured = models.BooleanField(default=False) +# audit_completed = models.BooleanField(default=False) +# compliance_verified = models.BooleanField(default=False) +# security_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Security Management Process' +# verbose_name_plural = 'Security Management Processes' +# +# +# class SecurityManagementFlow(flow.Flow): +# """ +# Security Management Workflow +# +# This flow manages user security setup including two-factor +# authentication, password policies, and compliance verification. +# """ +# +# process_class = SecurityManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_security_management) +# .Next(this.assess_security) +# ) +# +# assess_security = ( +# flow_view(SecurityAuditView) +# .Permission('accounts.can_audit_security') +# .Next(this.setup_two_factor) +# ) +# +# setup_two_factor = ( +# flow_view(TwoFactorSetupView) +# .Permission('accounts.can_setup_two_factor') +# .Next(this.apply_password_policy) +# ) +# +# apply_password_policy = ( +# flow_func(this.enforce_password_policy) +# .Next(this.configure_session) +# ) +# +# configure_session = ( +# flow_view(SessionManagementView) +# .Permission('accounts.can_manage_sessions') +# .Next(this.complete_audit) +# ) +# +# complete_audit = ( +# flow_func(this.perform_security_audit) +# .Next(this.verify_compliance) +# ) +# +# verify_compliance = ( +# flow_view(ComplianceCheckView) +# .Permission('accounts.can_verify_compliance') +# .Next(this.finalize_security) +# ) +# +# finalize_security = ( +# flow_func(this.complete_security_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_security_management) +# +# # Flow functions +# def start_security_management(self, activation): +# """Initialize the security management process""" +# process = activation.process +# user = process.user +# +# # Send security setup notification +# self.notify_security_setup(user) +# +# # Create security checklist +# self.create_security_checklist(user) +# +# def enforce_password_policy(self, activation): +# """Enforce password policy requirements""" +# process = activation.process +# user = process.user +# +# # Apply password policy +# self.apply_password_requirements(user) +# +# # Mark password policy applied +# process.password_policy_applied = True +# process.save() +# +# # Create password history entry +# self.create_password_history(user) +# +# def perform_security_audit(self, activation): +# """Perform comprehensive security audit""" +# process = activation.process +# user = process.user +# +# # Conduct security audit +# audit_results = self.conduct_security_audit(user) +# +# # Mark audit completed +# process.audit_completed = True +# process.save() +# +# # Store audit results +# self.store_audit_results(user, audit_results) +# +# def complete_security_management(self, activation): +# """Complete the security management process""" +# process = activation.process +# user = process.user +# +# # Mark security completed +# process.security_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_security_completion(user) +# +# # Schedule security review +# self.schedule_security_review(user) +# +# def end_security_management(self, activation): +# """End the security management workflow""" +# process = activation.process +# +# # Generate security summary +# self.generate_security_summary(process.user) +# +# # Helper methods +# def notify_security_setup(self, user): +# """Notify security setup start""" +# security_team = User.objects.filter(groups__name='Security Team') +# for staff in security_team: +# send_mail( +# subject=f'Security Setup: {user.get_full_name()}', +# message=f'Security setup process started for {user.username}.', +# from_email='security@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def create_security_checklist(self, user): +# """Create security setup checklist""" +# # This would create security checklist +# pass +# +# def apply_password_requirements(self, user): +# """Apply password policy requirements""" +# # This would enforce password policy +# pass +# +# def create_password_history(self, user): +# """Create password history entry""" +# # This would create password history record +# pass +# +# def conduct_security_audit(self, user): +# """Conduct comprehensive security audit""" +# # This would perform security audit +# return {'status': 'passed', 'issues': []} +# +# def store_audit_results(self, user, results): +# """Store security audit results""" +# # This would store audit results +# pass +# +# def notify_security_completion(self, user): +# """Notify security setup completion""" +# if user.email: +# send_mail( +# subject='Security Setup Complete', +# message='Your security setup has been completed successfully.', +# from_email='security@hospital.com', +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# def schedule_security_review(self, user): +# """Schedule periodic security review""" +# # Schedule security review task +# schedule_security_review.apply_async( +# args=[user.id], +# countdown=86400 * 90 # 90 days +# ) +# +# def generate_security_summary(self, user): +# """Generate security setup summary""" +# # This would generate security summary +# pass +# +# +# class AccountDeactivationProcess(Process): +# """ +# Viewflow process model for account deactivation +# """ +# user = ModelField(User, help_text='Associated user') +# +# # Process status tracking +# deactivation_requested = models.BooleanField(default=False) +# data_backup_completed = models.BooleanField(default=False) +# access_revoked = models.BooleanField(default=False) +# sessions_terminated = models.BooleanField(default=False) +# notifications_sent = models.BooleanField(default=False) +# account_archived = models.BooleanField(default=False) +# deactivation_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Account Deactivation Process' +# verbose_name_plural = 'Account Deactivation Processes' +# +# +# class AccountDeactivationFlow(flow.Flow): +# """ +# Account Deactivation Workflow +# +# This flow manages secure account deactivation including +# data backup, access revocation, and proper archival. +# """ +# +# process_class = AccountDeactivationProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_account_deactivation) +# .Next(this.request_deactivation) +# ) +# +# request_deactivation = ( +# flow_view(AccountDeactivationView) +# .Permission('accounts.can_deactivate_accounts') +# .Next(this.backup_data) +# ) +# +# backup_data = ( +# flow_func(this.perform_data_backup) +# .Next(this.revoke_access) +# ) +# +# revoke_access = ( +# flow_func(this.revoke_user_access) +# .Next(this.terminate_sessions) +# ) +# +# terminate_sessions = ( +# flow_func(this.end_user_sessions) +# .Next(this.send_notifications) +# ) +# +# send_notifications = ( +# flow_func(this.notify_deactivation) +# .Next(this.archive_account) +# ) +# +# archive_account = ( +# flow_func(this.archive_user_account) +# .Next(this.complete_deactivation) +# ) +# +# complete_deactivation = ( +# flow_func(this.finalize_account_deactivation) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_account_deactivation) +# +# # Flow functions +# def start_account_deactivation(self, activation): +# """Initialize the account deactivation process""" +# process = activation.process +# user = process.user +# +# # Send deactivation notification +# self.notify_deactivation_start(user) +# +# # Create deactivation checklist +# self.create_deactivation_checklist(user) +# +# def perform_data_backup(self, activation): +# """Perform user data backup""" +# process = activation.process +# user = process.user +# +# # Backup user data +# self.backup_user_data(user) +# +# # Mark backup completed +# process.data_backup_completed = True +# process.save() +# +# # Verify backup integrity +# self.verify_backup_integrity(user) +# +# def revoke_user_access(self, activation): +# """Revoke user access and permissions""" +# process = activation.process +# user = process.user +# +# # Revoke all permissions +# self.revoke_permissions(user) +# +# # Mark access revoked +# process.access_revoked = True +# process.save() +# +# # Log access revocation +# self.log_access_revocation(user) +# +# def end_user_sessions(self, activation): +# """Terminate all user sessions""" +# process = activation.process +# user = process.user +# +# # End all active sessions +# self.terminate_all_sessions(user) +# +# # Mark sessions terminated +# process.sessions_terminated = True +# process.save() +# +# # Log session termination +# self.log_session_termination(user) +# +# def notify_deactivation(self, activation): +# """Send deactivation notifications""" +# process = activation.process +# user = process.user +# +# # Send notifications to relevant parties +# self.send_deactivation_notifications(user) +# +# # Mark notifications sent +# process.notifications_sent = True +# process.save() +# +# def archive_user_account(self, activation): +# """Archive user account""" +# process = activation.process +# user = process.user +# +# # Archive account data +# self.archive_account_data(user) +# +# # Mark account archived +# process.account_archived = True +# process.save() +# +# # Update account status +# self.update_account_status(user) +# +# def finalize_account_deactivation(self, activation): +# """Finalize the account deactivation process""" +# process = activation.process +# user = process.user +# +# # Deactivate user account +# user.is_active = False +# user.save() +# +# # Mark deactivation completed +# process.deactivation_completed = True +# process.save() +# +# # Send final notifications +# self.notify_deactivation_completion(user) +# +# def end_account_deactivation(self, activation): +# """End the account deactivation workflow""" +# process = activation.process +# +# # Generate deactivation summary +# self.generate_deactivation_summary(process.user) +# +# # Helper methods +# def notify_deactivation_start(self, user): +# """Notify deactivation start""" +# hr_staff = User.objects.filter(groups__name='HR Staff') +# for staff in hr_staff: +# send_mail( +# subject=f'Account Deactivation: {user.get_full_name()}', +# message=f'Account deactivation process started for {user.username}.', +# from_email='accounts@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def create_deactivation_checklist(self, user): +# """Create deactivation checklist""" +# # This would create deactivation checklist +# pass +# +# def backup_user_data(self, user): +# """Backup user data""" +# # This would backup all user data +# pass +# +# def verify_backup_integrity(self, user): +# """Verify backup integrity""" +# # This would verify backup completeness +# pass +# +# def revoke_permissions(self, user): +# """Revoke all user permissions""" +# # This would revoke all permissions +# user.groups.clear() +# user.user_permissions.clear() +# +# def log_access_revocation(self, user): +# """Log access revocation""" +# # This would log the access revocation +# pass +# +# def terminate_all_sessions(self, user): +# """Terminate all user sessions""" +# user.user_sessions.filter(is_active=True).update( +# is_active=False, +# ended_at=timezone.now() +# ) +# +# def log_session_termination(self, user): +# """Log session termination""" +# # This would log session termination +# pass +# +# def send_deactivation_notifications(self, user): +# """Send deactivation notifications""" +# # This would send notifications to relevant parties +# pass +# +# def archive_account_data(self, user): +# """Archive account data""" +# # This would archive account data +# pass +# +# def update_account_status(self, user): +# """Update account status""" +# # This would update account status +# pass +# +# def notify_deactivation_completion(self, user): +# """Notify deactivation completion""" +# # This would notify completion +# pass +# +# def generate_deactivation_summary(self, user): +# """Generate deactivation summary""" +# # This would generate deactivation summary +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def schedule_security_review(user_id): +# """Background task to schedule security review""" +# try: +# user = User.objects.get(id=user_id) +# +# # Create security review task +# # This would create a security review task +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def cleanup_expired_sessions(): +# """Background task to cleanup expired sessions""" +# try: +# # Cleanup expired sessions +# expired_sessions = UserSession.objects.filter( +# expires_at__lt=timezone.now(), +# is_active=True +# ) +# +# for session in expired_sessions: +# session.end_session() +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def audit_user_accounts(): +# """Background task to audit user accounts""" +# try: +# # This would perform periodic user account audits +# return True +# except Exception: +# return False +# +# +# @celery.job +# def enforce_password_expiry(): +# """Background task to enforce password expiry""" +# try: +# # This would enforce password expiry policies +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_security_reports(): +# """Background task to generate security reports""" +# try: +# # This would generate periodic security reports +# return True +# except Exception: +# return False +# diff --git a/accounts/forms.py b/accounts/forms.py index e0fcebca..229d940f 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -223,3 +223,721 @@ class PasswordChangeForm(forms.Form): self.user.save() return self.user + +# from django import forms +# from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm +# from django.contrib.auth.models import User, Group +# from django.core.exceptions import ValidationError +# from django.utils import timezone +# from django.contrib.auth.password_validation import validate_password +# from crispy_forms.helper import FormHelper +# from crispy_forms.layout import Layout, Fieldset, Submit, Row, Column, HTML, Div +# from crispy_forms.bootstrap import FormActions +# +# from .models import User, TwoFactorDevice, SocialAccount, UserSession, PasswordHistory +# +# +# class UserRegistrationForm(UserCreationForm): +# """ +# Form for user registration in onboarding workflow +# """ +# first_name = forms.CharField( +# max_length=150, +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# last_name = forms.CharField( +# max_length=150, +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# email = forms.EmailField( +# required=True, +# widget=forms.EmailInput(attrs={'class': 'form-control'}) +# ) +# employee_id = forms.CharField( +# max_length=50, +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# department = forms.ModelChoiceField( +# queryset=None, # Will be set in __init__ +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# job_title = forms.CharField( +# max_length=200, +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# phone_number = forms.CharField( +# max_length=20, +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# start_date = forms.DateField( +# required=True, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# manager = forms.ModelChoiceField( +# queryset=None, # Will be set in __init__ +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# +# class Meta: +# model = User +# fields = [ +# 'username', 'first_name', 'last_name', 'email', 'employee_id', +# 'department', 'job_title', 'phone_number', 'start_date', 'manager', +# 'password1', 'password2' +# ] +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# # Set querysets based on tenant +# if tenant: +# from core.models import Department +# self.fields['department'].queryset = Department.objects.filter(tenant=tenant) +# self.fields['manager'].queryset = User.objects.filter( +# tenant=tenant, +# is_active=True, +# groups__name__in=['Managers', 'Department Heads'] +# ) +# +# # Crispy forms helper +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'User Information', +# Row( +# Column('first_name', css_class='form-group col-md-6 mb-0'), +# Column('last_name', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('username', css_class='form-group col-md-6 mb-0'), +# Column('email', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('employee_id', css_class='form-group col-md-6 mb-0'), +# Column('phone_number', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Employment Information', +# Row( +# Column('department', css_class='form-group col-md-6 mb-0'), +# Column('job_title', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('start_date', css_class='form-group col-md-6 mb-0'), +# Column('manager', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Security', +# Row( +# Column('password1', css_class='form-group col-md-6 mb-0'), +# Column('password2', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# FormActions( +# Submit('submit', 'Register User', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean_email(self): +# email = self.cleaned_data.get('email') +# if User.objects.filter(email=email).exists(): +# raise ValidationError('A user with this email already exists.') +# return email +# +# def clean_employee_id(self): +# employee_id = self.cleaned_data.get('employee_id') +# if employee_id and User.objects.filter(employee_id=employee_id).exists(): +# raise ValidationError('A user with this employee ID already exists.') +# return employee_id +# +# +# class AccountActivationForm(forms.Form): +# """ +# Form for account activation in onboarding workflow +# """ +# activation_code = forms.CharField( +# max_length=100, +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# terms_accepted = forms.BooleanField( +# required=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# privacy_policy_accepted = forms.BooleanField( +# required=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Account Activation', +# 'activation_code', +# HTML('
'), +# 'terms_accepted', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'privacy_policy_accepted', +# HTML( +# ''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Activate Account', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class TwoFactorSetupForm(forms.ModelForm): +# """ +# Form for two-factor authentication setup +# """ +# device_name = forms.CharField( +# max_length=100, +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# device_type = forms.ChoiceField( +# choices=[ +# ('totp', 'Authenticator App (TOTP)'), +# ('sms', 'SMS'), +# ('email', 'Email'), +# ('backup_codes', 'Backup Codes') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# phone_number = forms.CharField( +# max_length=20, +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# verification_code = forms.CharField( +# max_length=10, +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# +# class Meta: +# model = TwoFactorDevice +# fields = ['device_name', 'device_type', 'phone_number'] +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Two-Factor Authentication Setup', +# 'device_name', +# 'device_type', +# 'phone_number', +# HTML( +# '
Enter the verification code from your authenticator app or device.
'), +# 'verification_code' +# ), +# FormActions( +# Submit('submit', 'Setup Two-Factor Auth', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# device_type = cleaned_data.get('device_type') +# phone_number = cleaned_data.get('phone_number') +# +# if device_type == 'sms' and not phone_number: +# raise ValidationError('Phone number is required for SMS two-factor authentication.') +# +# return cleaned_data +# +# +# class PermissionManagementForm(forms.Form): +# """ +# Form for managing user permissions +# """ +# groups = forms.ModelMultipleChoiceField( +# queryset=Group.objects.all(), +# required=False, +# widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) +# ) +# is_staff = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# is_superuser = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# access_level = forms.ChoiceField( +# choices=[ +# ('basic', 'Basic Access'), +# ('standard', 'Standard Access'), +# ('advanced', 'Advanced Access'), +# ('admin', 'Administrator Access') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# department_access = forms.ModelMultipleChoiceField( +# queryset=None, # Will be set in __init__ +# required=False, +# widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# from core.models import Department +# self.fields['department_access'].queryset = Department.objects.filter(tenant=tenant) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'User Permissions', +# 'access_level', +# HTML('
'), +# 'is_staff', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'is_superuser', +# HTML(''), +# HTML('
') +# ), +# Fieldset( +# 'Group Memberships', +# 'groups' +# ), +# Fieldset( +# 'Department Access', +# 'department_access' +# ), +# FormActions( +# Submit('submit', 'Update Permissions', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class SecurityAuditForm(forms.Form): +# """ +# Form for security audit configuration +# """ +# audit_type = forms.ChoiceField( +# choices=[ +# ('comprehensive', 'Comprehensive Security Audit'), +# ('password_policy', 'Password Policy Audit'), +# ('access_review', 'Access Rights Review'), +# ('session_audit', 'Session Security Audit'), +# ('two_factor_audit', 'Two-Factor Authentication Audit') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# include_inactive_users = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# check_password_strength = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# review_login_attempts = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# analyze_session_security = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# generate_report = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Security Audit Configuration', +# 'audit_type', +# HTML('
'), +# 'include_inactive_users', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'check_password_strength', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'review_login_attempts', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'analyze_session_security', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'generate_report', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Start Security Audit', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class SessionManagementForm(forms.Form): +# """ +# Form for session management configuration +# """ +# session_timeout = forms.IntegerField( +# min_value=5, +# max_value=1440, +# initial=30, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# max_concurrent_sessions = forms.IntegerField( +# min_value=1, +# max_value=10, +# initial=3, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# require_secure_cookies = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# enable_session_monitoring = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# log_session_events = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# auto_logout_inactive = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Session Configuration', +# Row( +# Column('session_timeout', css_class='form-group col-md-6 mb-0'), +# Column('max_concurrent_sessions', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# HTML('
'), +# 'require_secure_cookies', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'enable_session_monitoring', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'log_session_events', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'auto_logout_inactive', +# HTML( +# ''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Update Session Settings', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class ComplianceCheckForm(forms.Form): +# """ +# Form for compliance verification +# """ +# compliance_standards = forms.MultipleChoiceField( +# choices=[ +# ('hipaa', 'HIPAA Compliance'), +# ('gdpr', 'GDPR Compliance'), +# ('sox', 'SOX Compliance'), +# ('pci_dss', 'PCI DSS Compliance'), +# ('iso27001', 'ISO 27001 Compliance') +# ], +# required=True, +# widget=forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}) +# ) +# check_password_policies = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# verify_access_controls = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# audit_user_permissions = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# check_data_encryption = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# generate_compliance_report = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Compliance Standards', +# 'compliance_standards' +# ), +# Fieldset( +# 'Compliance Checks', +# HTML('
'), +# 'check_password_policies', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'verify_access_controls', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'audit_user_permissions', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'check_data_encryption', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'generate_compliance_report', +# HTML( +# ''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Start Compliance Check', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class AccountDeactivationForm(forms.Form): +# """ +# Form for account deactivation +# """ +# deactivation_reason = forms.ChoiceField( +# choices=[ +# ('termination', 'Employment Termination'), +# ('resignation', 'Employee Resignation'), +# ('transfer', 'Department Transfer'), +# ('leave', 'Extended Leave'), +# ('security', 'Security Concerns'), +# ('other', 'Other Reason') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# deactivation_date = forms.DateField( +# required=True, +# initial=timezone.now().date(), +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# backup_data = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# transfer_ownership = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# new_owner = forms.ModelChoiceField( +# queryset=None, # Will be set in __init__ +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# notify_stakeholders = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# additional_notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) +# ) +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['new_owner'].queryset = User.objects.filter( +# tenant=tenant, +# is_active=True +# ).exclude(id=self.instance.id if hasattr(self, 'instance') else None) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Deactivation Details', +# Row( +# Column('deactivation_reason', css_class='form-group col-md-6 mb-0'), +# Column('deactivation_date', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'additional_notes' +# ), +# Fieldset( +# 'Data Management', +# HTML('
'), +# 'backup_data', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'transfer_ownership', +# HTML(''), +# HTML('
'), +# 'new_owner' +# ), +# Fieldset( +# 'Notifications', +# HTML('
'), +# 'notify_stakeholders', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Deactivate Account', css_class='btn btn-danger'), +# HTML('Cancel') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# transfer_ownership = cleaned_data.get('transfer_ownership') +# new_owner = cleaned_data.get('new_owner') +# +# if transfer_ownership and not new_owner: +# raise ValidationError('New owner must be selected when transferring ownership.') +# +# return cleaned_data +# +# +# class PasswordResetForm(forms.Form): +# """ +# Form for password reset +# """ +# email = forms.EmailField( +# required=True, +# widget=forms.EmailInput(attrs={'class': 'form-control'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Password Reset', +# 'email', +# HTML( +# '
Enter your email address and we will send you a link to reset your password.
') +# ), +# FormActions( +# Submit('submit', 'Send Reset Link', css_class='btn btn-primary'), +# HTML('Back to Login') +# ) +# ) +# +# def clean_email(self): +# email = self.cleaned_data.get('email') +# if not User.objects.filter(email=email, is_active=True).exists(): +# raise ValidationError('No active user found with this email address.') +# return email +# +# +# class PasswordChangeForm(PasswordChangeForm): +# """ +# Enhanced password change form +# """ +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# # Add CSS classes +# for field in self.fields.values(): +# field.widget.attrs['class'] = 'form-control' +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Change Password', +# 'old_password', +# 'new_password1', +# 'new_password2', +# HTML( +# '
Your password must contain at least 8 characters and cannot be too similar to your other personal information.
') +# ), +# FormActions( +# Submit('submit', 'Change Password', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# diff --git a/accounts/views.py b/accounts/views.py index 5a14c533..615079e8 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -2474,3 +2474,650 @@ def upload_avatar(request, pk): # # # +# from django.shortcuts import render, redirect, get_object_or_404 +# from django.contrib.auth import login, logout, authenticate +# from django.contrib.auth.decorators import login_required, permission_required +# from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +# from django.contrib import messages +# from django.views.generic import ( +# CreateView, UpdateView, DeleteView, DetailView, ListView, FormView +# ) +# from django.urls import reverse_lazy, reverse +# from django.http import JsonResponse, HttpResponse +# from django.utils import timezone +# from django.db import transaction, models +# from django.core.mail import send_mail +# from django.conf import settings +# from django.contrib.auth.models import Group +# from viewflow.workflow.flow.views import CreateProcessView, UpdateProcessView +# +# from .models import User, TwoFactorDevice, SocialAccount, UserSession, PasswordHistory +# from .forms import ( +# UserRegistrationForm, AccountActivationForm, TwoFactorSetupForm, +# PermissionManagementForm, SecurityAuditForm, SessionManagementForm, +# ComplianceCheckForm, AccountDeactivationForm, PasswordResetForm, +# PasswordChangeForm +# ) +# from .flows import UserOnboardingFlow, SecurityManagementFlow, AccountDeactivationFlow +# +# +# class UserRegistrationView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for user registration in onboarding workflow +# """ +# model = User +# form_class = UserRegistrationForm +# template_name = 'accounts/user_registration.html' +# permission_required = 'accounts.can_register_users' +# flow_class = UserOnboardingFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create user +# user = form.save(commit=False) +# user.tenant = self.request.user.tenant +# user.is_active = False # Will be activated in workflow +# user.created_by = self.request.user +# user.save() +# +# # Start onboarding workflow +# process = self.flow_class.start.run( +# user=user, +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'User registration initiated for {user.get_full_name()}. ' +# f'Onboarding workflow started.' +# ) +# +# return redirect('accounts:user_detail', pk=user.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Register New User' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Users', 'url': reverse('accounts:user_list')}, +# {'name': 'Register User', 'url': ''} +# ] +# return context +# +# +# class AccountActivationView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for account activation in onboarding workflow +# """ +# form_class = AccountActivationForm +# template_name = 'accounts/account_activation.html' +# permission_required = 'accounts.can_activate_accounts' +# +# def get_success_url(self): +# return reverse('accounts:user_detail', kwargs={'pk': self.kwargs['pk']}) +# +# def form_valid(self, form): +# user = get_object_or_404(User, pk=self.kwargs['pk']) +# activation_code = form.cleaned_data['activation_code'] +# +# # Verify activation code (implement your verification logic) +# if self.verify_activation_code(user, activation_code): +# user.is_active = True +# user.email_verified = True +# user.activated_at = timezone.now() +# user.save() +# +# # Send welcome email +# self.send_welcome_email(user) +# +# messages.success( +# self.request, +# f'Account activated successfully for {user.get_full_name()}.' +# ) +# else: +# messages.error(self.request, 'Invalid activation code.') +# return self.form_invalid(form) +# +# return super().form_valid(form) +# +# def verify_activation_code(self, user, code): +# """Verify activation code (implement your logic)""" +# # This would implement actual verification logic +# return True +# +# def send_welcome_email(self, user): +# """Send welcome email to activated user""" +# if user.email: +# send_mail( +# subject='Welcome to Hospital Management System', +# message=f'Welcome {user.get_full_name()}! Your account has been activated.', +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['user'] = get_object_or_404(User, pk=self.kwargs['pk']) +# context['title'] = 'Activate Account' +# return context +# +# +# class TwoFactorSetupView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): +# """ +# View for two-factor authentication setup +# """ +# model = TwoFactorDevice +# form_class = TwoFactorSetupForm +# template_name = 'accounts/two_factor_setup.html' +# permission_required = 'accounts.can_setup_two_factor' +# +# def get_success_url(self): +# return reverse('accounts:security_settings') +# +# def form_valid(self, form): +# device = form.save(commit=False) +# device.user = self.request.user +# device.is_active = True +# device.created_at = timezone.now() +# +# # Generate device-specific configuration +# device.configuration = self.generate_device_config(device.device_type) +# device.save() +# +# messages.success( +# self.request, +# 'Two-factor authentication has been set up successfully.' +# ) +# +# return super().form_valid(form) +# +# def generate_device_config(self, device_type): +# """Generate device-specific configuration""" +# if device_type == 'totp': +# # Generate TOTP secret +# import pyotp +# return {'secret': pyotp.random_base32()} +# elif device_type == 'backup_codes': +# # Generate backup codes +# import secrets +# codes = [secrets.token_hex(4) for _ in range(10)] +# return {'codes': codes} +# return {} +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Setup Two-Factor Authentication' +# return context +# +# +# class PermissionManagementView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for managing user permissions +# """ +# form_class = PermissionManagementForm +# template_name = 'accounts/permission_management.html' +# permission_required = 'accounts.can_manage_permissions' +# +# def get_success_url(self): +# return reverse('accounts:user_detail', kwargs={'pk': self.kwargs['pk']}) +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def get_initial(self): +# user = get_object_or_404(User, pk=self.kwargs['pk']) +# return { +# 'groups': user.groups.all(), +# 'is_staff': user.is_staff, +# 'is_superuser': user.is_superuser, +# 'access_level': getattr(user, 'access_level', 'basic'), +# 'department_access': getattr(user, 'department_access', []) +# } +# +# def form_valid(self, form): +# user = get_object_or_404(User, pk=self.kwargs['pk']) +# +# with transaction.atomic(): +# # Update user permissions +# user.groups.set(form.cleaned_data['groups']) +# user.is_staff = form.cleaned_data['is_staff'] +# user.is_superuser = form.cleaned_data['is_superuser'] +# user.access_level = form.cleaned_data['access_level'] +# user.save() +# +# # Log permission changes +# self.log_permission_changes(user, form.cleaned_data) +# +# messages.success( +# self.request, +# f'Permissions updated successfully for {user.get_full_name()}.' +# ) +# +# return super().form_valid(form) +# +# def log_permission_changes(self, user, changes): +# """Log permission changes for audit""" +# from core.models import AuditLogEntry +# AuditLogEntry.objects.create( +# tenant=user.tenant, +# user=self.request.user, +# event_type='PERMISSION_CHANGE', +# action='UPDATE', +# object_type='User', +# object_id=str(user.id), +# details=changes, +# ip_address=self.request.META.get('REMOTE_ADDR'), +# user_agent=self.request.META.get('HTTP_USER_AGENT', '') +# ) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['user'] = get_object_or_404(User, pk=self.kwargs['pk']) +# context['title'] = 'Manage Permissions' +# return context +# +# +# class SecurityAuditView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for security audit configuration +# """ +# form_class = SecurityAuditForm +# template_name = 'accounts/security_audit.html' +# permission_required = 'accounts.can_audit_security' +# +# def get_success_url(self): +# return reverse('accounts:security_dashboard') +# +# def form_valid(self, form): +# audit_config = form.cleaned_data +# +# # Start security audit workflow +# process = SecurityManagementFlow.start.run( +# user=self.request.user, +# audit_config=audit_config, +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# 'Security audit has been initiated. You will receive a notification when complete.' +# ) +# +# return super().form_valid(form) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Security Audit' +# context['recent_audits'] = self.get_recent_audits() +# return context +# +# def get_recent_audits(self): +# """Get recent security audits""" +# # This would return recent audit records +# return [] +# +# +# class SessionManagementView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for session management configuration +# """ +# form_class = SessionManagementForm +# template_name = 'accounts/session_management.html' +# permission_required = 'accounts.can_manage_sessions' +# +# def get_success_url(self): +# return reverse('accounts:security_settings') +# +# def get_initial(self): +# # Get current session settings +# return { +# 'session_timeout': getattr(settings, 'SESSION_COOKIE_AGE', 1800) // 60, +# 'max_concurrent_sessions': 3, +# 'require_secure_cookies': getattr(settings, 'SESSION_COOKIE_SECURE', True), +# 'enable_session_monitoring': True, +# 'log_session_events': True, +# 'auto_logout_inactive': True +# } +# +# def form_valid(self, form): +# config = form.cleaned_data +# +# # Update session configuration +# self.update_session_config(config) +# +# messages.success( +# self.request, +# 'Session management settings updated successfully.' +# ) +# +# return super().form_valid(form) +# +# def update_session_config(self, config): +# """Update session configuration""" +# # This would update session configuration +# pass +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Session Management' +# context['active_sessions'] = self.get_active_sessions() +# return context +# +# def get_active_sessions(self): +# """Get active user sessions""" +# return UserSession.objects.filter( +# user=self.request.user, +# is_active=True +# ).order_by('-created_at') +# +# +# class ComplianceCheckView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for compliance verification +# """ +# form_class = ComplianceCheckForm +# template_name = 'accounts/compliance_check.html' +# permission_required = 'accounts.can_verify_compliance' +# +# def get_success_url(self): +# return reverse('accounts:compliance_dashboard') +# +# def form_valid(self, form): +# compliance_config = form.cleaned_data +# +# # Start compliance check +# self.start_compliance_check(compliance_config) +# +# messages.success( +# self.request, +# 'Compliance check has been initiated. Results will be available shortly.' +# ) +# +# return super().form_valid(form) +# +# def start_compliance_check(self, config): +# """Start compliance verification process""" +# # This would start compliance checking +# pass +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Compliance Check' +# context['compliance_status'] = self.get_compliance_status() +# return context +# +# def get_compliance_status(self): +# """Get current compliance status""" +# return { +# 'hipaa': 'compliant', +# 'gdpr': 'compliant', +# 'sox': 'pending', +# 'pci_dss': 'non_compliant', +# 'iso27001': 'compliant' +# } +# +# +# class AccountDeactivationView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for account deactivation +# """ +# form_class = AccountDeactivationForm +# template_name = 'accounts/account_deactivation.html' +# permission_required = 'accounts.can_deactivate_accounts' +# +# def get_success_url(self): +# return reverse('accounts:user_list') +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# user = get_object_or_404(User, pk=self.kwargs['pk']) +# deactivation_config = form.cleaned_data +# +# # Start account deactivation workflow +# process = AccountDeactivationFlow.start.run( +# user=user, +# deactivation_config=deactivation_config, +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Account deactivation initiated for {user.get_full_name()}.' +# ) +# +# return super().form_valid(form) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['user'] = get_object_or_404(User, pk=self.kwargs['pk']) +# context['title'] = 'Deactivate Account' +# return context +# +# +# class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for listing users +# """ +# model = User +# template_name = 'accounts/user_list.html' +# context_object_name = 'users' +# permission_required = 'accounts.view_user' +# paginate_by = 25 +# +# def get_queryset(self): +# queryset = User.objects.filter(tenant=self.request.user.tenant) +# +# # Apply filters +# search = self.request.GET.get('search') +# if search: +# queryset = queryset.filter( +# models.Q(first_name__icontains=search) | +# models.Q(last_name__icontains=search) | +# models.Q(email__icontains=search) | +# models.Q(username__icontains=search) +# ) +# +# department = self.request.GET.get('department') +# if department: +# queryset = queryset.filter(department_id=department) +# +# status = self.request.GET.get('status') +# if status == 'active': +# queryset = queryset.filter(is_active=True) +# elif status == 'inactive': +# queryset = queryset.filter(is_active=False) +# +# return queryset.order_by('last_name', 'first_name') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Users' +# context['departments'] = self.get_departments() +# context['search'] = self.request.GET.get('search', '') +# context['selected_department'] = self.request.GET.get('department', '') +# context['selected_status'] = self.request.GET.get('status', '') +# return context +# +# def get_departments(self): +# """Get departments for filter""" +# from core.models import Department +# return Department.objects.filter(tenant=self.request.user.tenant) +# +# +# class UserDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# """ +# View for user details +# """ +# model = User +# template_name = 'accounts/user_detail.html' +# context_object_name = 'user' +# permission_required = 'accounts.view_user' +# +# def get_queryset(self): +# return User.objects.filter(tenant=self.request.user.tenant) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# user = self.object +# context['title'] = f'{user.get_full_name()}' +# context['two_factor_devices'] = user.two_factor_devices.filter(is_active=True) +# context['recent_sessions'] = user.user_sessions.order_by('-created_at')[:5] +# context['password_history'] = user.password_history.order_by('-created_at')[:5] +# return context +# +# +# class SecurityDashboardView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for security dashboard +# """ +# template_name = 'accounts/security_dashboard.html' +# permission_required = 'accounts.view_security_dashboard' +# +# def get_queryset(self): +# return None +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Security Dashboard' +# context['security_metrics'] = self.get_security_metrics() +# context['recent_alerts'] = self.get_recent_security_alerts() +# context['compliance_status'] = self.get_compliance_status() +# return context +# +# def get_security_metrics(self): +# """Get security metrics""" +# tenant = self.request.user.tenant +# return { +# 'total_users': User.objects.filter(tenant=tenant).count(), +# 'active_users': User.objects.filter(tenant=tenant, is_active=True).count(), +# 'users_with_2fa': User.objects.filter( +# tenant=tenant, +# two_factor_devices__is_active=True +# ).distinct().count(), +# 'failed_logins_today': 0, # Would be calculated from audit logs +# 'password_expiring_soon': 0 # Would be calculated from password history +# } +# +# def get_recent_security_alerts(self): +# """Get recent security alerts""" +# # This would return recent security alerts +# return [] +# +# def get_compliance_status(self): +# """Get compliance status""" +# return { +# 'hipaa': 'compliant', +# 'gdpr': 'compliant', +# 'sox': 'pending', +# 'pci_dss': 'non_compliant', +# 'iso27001': 'compliant' +# } +# +# +# # AJAX Views +# @login_required +# @permission_required('accounts.can_manage_sessions') +# def terminate_session_ajax(request, session_id): +# """AJAX view to terminate user session""" +# if request.method == 'POST': +# try: +# session = UserSession.objects.get( +# id=session_id, +# user__tenant=request.user.tenant +# ) +# session.end_session() +# +# return JsonResponse({ +# 'success': True, +# 'message': 'Session terminated successfully.' +# }) +# except UserSession.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'Session not found.' +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# @login_required +# @permission_required('accounts.can_reset_passwords') +# def reset_password_ajax(request, user_id): +# """AJAX view to reset user password""" +# if request.method == 'POST': +# try: +# user = User.objects.get( +# id=user_id, +# tenant=request.user.tenant +# ) +# +# # Generate temporary password +# import secrets +# temp_password = secrets.token_urlsafe(12) +# user.set_password(temp_password) +# user.must_change_password = True +# user.save() +# +# # Send password reset email +# send_mail( +# subject='Password Reset', +# message=f'Your temporary password is: {temp_password}', +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# return JsonResponse({ +# 'success': True, +# 'message': 'Password reset successfully. User will receive email with temporary password.' +# }) +# except User.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'User not found.' +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# @login_required +# def user_search_ajax(request): +# """AJAX view for user search""" +# query = request.GET.get('q', '') +# if len(query) < 2: +# return JsonResponse({'users': []}) +# +# users = User.objects.filter( +# tenant=request.user.tenant, +# is_active=True +# ).filter( +# models.Q(first_name__icontains=query) | +# models.Q(last_name__icontains=query) | +# models.Q(email__icontains=query) | +# models.Q(username__icontains=query) +# )[:10] +# +# user_data = [ +# { +# 'id': user.id, +# 'name': user.get_full_name(), +# 'email': user.email, +# 'department': user.department.name if user.department else '' +# } +# for user in users +# ] +# +# return JsonResponse({'users': user_data}) +# diff --git a/analytics/.DS_Store b/analytics/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc yq7TwkS(2Gtte=*XUtX+NP'), +# 'schedule_execution', +# HTML( +# ''), +# HTML(''), +# 'execution_time' +# ), +# FormActions( +# Submit('submit', 'Generate Report', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean_parameters(self): +# parameters = self.cleaned_data.get('parameters') +# if parameters: +# try: +# json.loads(parameters) +# except json.JSONDecodeError: +# raise ValidationError('Parameters must be valid JSON.') +# return parameters +# +# def clean(self): +# cleaned_data = super().clean() +# schedule_execution = cleaned_data.get('schedule_execution') +# execution_time = cleaned_data.get('execution_time') +# +# if schedule_execution and not execution_time: +# raise ValidationError('Execution time is required when scheduling execution.') +# +# return cleaned_data +# +# +# class DashboardCreationForm(forms.ModelForm): +# """ +# Form for dashboard creation +# """ +# layout_template = forms.ChoiceField( +# choices=[ +# ('grid_2x2', '2x2 Grid'), +# ('grid_3x3', '3x3 Grid'), +# ('sidebar_main', 'Sidebar + Main'), +# ('top_bottom', 'Top + Bottom'), +# ('custom', 'Custom Layout') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# copy_from_dashboard = forms.ModelChoiceField( +# queryset=None, +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# +# class Meta: +# model = Dashboard +# fields = [ +# 'name', 'description', 'dashboard_type', 'layout_template', +# 'refresh_interval', 'is_public', 'allowed_roles', +# 'copy_from_dashboard' +# ] +# widgets = { +# 'name': forms.TextInput(attrs={'class': 'form-control'}), +# 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), +# 'dashboard_type': forms.Select(attrs={'class': 'form-control'}), +# 'refresh_interval': forms.NumberInput(attrs={'class': 'form-control'}), +# 'is_public': forms.CheckboxInput(attrs={'class': 'form-check-input'}), +# 'allowed_roles': forms.Textarea(attrs={'class': 'form-control', 'rows': 2}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['copy_from_dashboard'].queryset = Dashboard.objects.filter( +# tenant=tenant, +# is_active=True +# ) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Dashboard Information', +# Row( +# Column('name', css_class='form-group col-md-6 mb-0'), +# Column('dashboard_type', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'description' +# ), +# Fieldset( +# 'Layout Configuration', +# Row( +# Column('layout_template', css_class='form-group col-md-6 mb-0'), +# Column('refresh_interval', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'copy_from_dashboard' +# ), +# Fieldset( +# 'Access Control', +# HTML('
'), +# 'is_public', +# HTML(''), +# HTML('
'), +# 'allowed_roles' +# ), +# FormActions( +# Submit('submit', 'Create Dashboard', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class DataSourceConfigurationForm(forms.ModelForm): +# """ +# Form for data source configuration +# """ +# test_connection = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = DataSource +# fields = [ +# 'name', 'description', 'source_type', 'connection_config', +# 'query_config', 'refresh_interval', 'is_active', +# 'test_connection' +# ] +# widgets = { +# 'name': forms.TextInput(attrs={'class': 'form-control'}), +# 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), +# 'source_type': forms.Select(attrs={'class': 'form-control'}), +# 'connection_config': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}), +# 'query_config': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}), +# 'refresh_interval': forms.NumberInput(attrs={'class': 'form-control'}), +# 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# } +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Data Source Information', +# Row( +# Column('name', css_class='form-group col-md-6 mb-0'), +# Column('source_type', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'description' +# ), +# Fieldset( +# 'Connection Configuration', +# 'connection_config', +# HTML('Enter connection details in JSON format') +# ), +# Fieldset( +# 'Query Configuration', +# 'query_config', +# HTML('Enter query configuration in JSON format') +# ), +# Fieldset( +# 'Settings', +# Row( +# Column('refresh_interval', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# HTML('
'), +# 'is_active', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'test_connection', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Save Data Source', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean_connection_config(self): +# config = self.cleaned_data.get('connection_config') +# if config: +# try: +# json.loads(config) +# except json.JSONDecodeError: +# raise ValidationError('Connection configuration must be valid JSON.') +# return config +# +# def clean_query_config(self): +# config = self.cleaned_data.get('query_config') +# if config: +# try: +# json.loads(config) +# except json.JSONDecodeError: +# raise ValidationError('Query configuration must be valid JSON.') +# return config +# +# +# class MetricCalculationForm(forms.ModelForm): +# """ +# Form for metric calculation configuration +# """ +# calculate_now = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# date_range_start = forms.DateField( +# required=False, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# date_range_end = forms.DateField( +# required=False, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# +# class Meta: +# model = MetricDefinition +# fields = [ +# 'name', 'description', 'metric_type', 'data_source', +# 'calculation_config', 'aggregation_period', 'target_value', +# 'warning_threshold', 'critical_threshold', 'unit_of_measure', +# 'calculate_now', 'date_range_start', 'date_range_end' +# ] +# widgets = { +# 'name': forms.TextInput(attrs={'class': 'form-control'}), +# 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), +# 'metric_type': forms.Select(attrs={'class': 'form-control'}), +# 'data_source': forms.Select(attrs={'class': 'form-control'}), +# 'calculation_config': forms.Textarea(attrs={'class': 'form-control', 'rows': 4}), +# 'aggregation_period': forms.Select(attrs={'class': 'form-control'}), +# 'target_value': forms.NumberInput(attrs={'class': 'form-control'}), +# 'warning_threshold': forms.NumberInput(attrs={'class': 'form-control'}), +# 'critical_threshold': forms.NumberInput(attrs={'class': 'form-control'}), +# 'unit_of_measure': forms.TextInput(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['data_source'].queryset = DataSource.objects.filter(tenant=tenant) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Metric Definition', +# Row( +# Column('name', css_class='form-group col-md-6 mb-0'), +# Column('metric_type', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'description', +# Row( +# Column('data_source', css_class='form-group col-md-6 mb-0'), +# Column('aggregation_period', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'calculation_config' +# ), +# Fieldset( +# 'Thresholds and Targets', +# Row( +# Column('target_value', css_class='form-group col-md-4 mb-0'), +# Column('warning_threshold', css_class='form-group col-md-4 mb-0'), +# Column('critical_threshold', css_class='form-group col-md-4 mb-0'), +# css_class='form-row' +# ), +# 'unit_of_measure' +# ), +# Fieldset( +# 'Calculation Options', +# HTML('
'), +# 'calculate_now', +# HTML(''), +# HTML('
'), +# Row( +# Column('date_range_start', css_class='form-group col-md-6 mb-0'), +# Column('date_range_end', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# FormActions( +# Submit('submit', 'Save Metric', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean_calculation_config(self): +# config = self.cleaned_data.get('calculation_config') +# if config: +# try: +# json.loads(config) +# except json.JSONDecodeError: +# raise ValidationError('Calculation configuration must be valid JSON.') +# return config +# +# +# class QualityAssuranceForm(forms.Form): +# """ +# Form for quality assurance configuration +# """ +# check_data_accuracy = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# validate_calculations = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# verify_data_sources = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# check_performance = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# generate_qa_report = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# qa_threshold = forms.DecimalField( +# max_digits=5, +# decimal_places=2, +# initial=95.0, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Quality Assurance Checks', +# HTML('
'), +# 'check_data_accuracy', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'validate_calculations', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'verify_data_sources', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'check_performance', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'generate_qa_report', +# HTML(''), +# HTML('
') +# ), +# Fieldset( +# 'Quality Threshold', +# 'qa_threshold', +# HTML('Minimum quality score percentage (0-100)') +# ), +# FormActions( +# Submit('submit', 'Start Quality Check', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class DistributionForm(forms.Form): +# """ +# Form for report distribution configuration +# """ +# distribution_method = forms.ChoiceField( +# choices=[ +# ('email', 'Email'), +# ('download', 'Download Link'), +# ('ftp', 'FTP Upload'), +# ('api', 'API Endpoint'), +# ('dashboard', 'Dashboard Publication') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# recipients = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) +# ) +# subject = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# message = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) +# ) +# schedule_distribution = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# distribution_time = forms.DateTimeField( +# required=False, +# widget=forms.DateTimeInput(attrs={'class': 'form-control', 'type': 'datetime-local'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Distribution Method', +# 'distribution_method', +# 'recipients', +# HTML('Enter email addresses separated by commas') +# ), +# Fieldset( +# 'Message Content', +# 'subject', +# 'message' +# ), +# Fieldset( +# 'Scheduling', +# HTML('
'), +# 'schedule_distribution', +# HTML(''), +# HTML('
'), +# 'distribution_time' +# ), +# FormActions( +# Submit('submit', 'Distribute Report', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# distribution_method = cleaned_data.get('distribution_method') +# recipients = cleaned_data.get('recipients') +# schedule_distribution = cleaned_data.get('schedule_distribution') +# distribution_time = cleaned_data.get('distribution_time') +# +# if distribution_method == 'email' and not recipients: +# raise ValidationError('Recipients are required for email distribution.') +# +# if schedule_distribution and not distribution_time: +# raise ValidationError('Distribution time is required when scheduling distribution.') +# +# return cleaned_data +# +# +# class VisualizationForm(forms.Form): +# """ +# Form for visualization configuration +# """ +# chart_type = forms.ChoiceField( +# choices=[ +# ('line', 'Line Chart'), +# ('bar', 'Bar Chart'), +# ('pie', 'Pie Chart'), +# ('scatter', 'Scatter Plot'), +# ('heatmap', 'Heat Map'), +# ('gauge', 'Gauge'), +# ('table', 'Data Table') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# title = forms.CharField( +# required=True, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# x_axis_label = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# y_axis_label = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# color_scheme = forms.ChoiceField( +# choices=[ +# ('default', 'Default'), +# ('blue', 'Blue Theme'), +# ('green', 'Green Theme'), +# ('red', 'Red Theme'), +# ('purple', 'Purple Theme'), +# ('custom', 'Custom Colors') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# show_legend = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# show_grid = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Chart Configuration', +# Row( +# Column('chart_type', css_class='form-group col-md-6 mb-0'), +# Column('color_scheme', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'title' +# ), +# Fieldset( +# 'Axis Labels', +# Row( +# Column('x_axis_label', css_class='form-group col-md-6 mb-0'), +# Column('y_axis_label', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Display Options', +# HTML('
'), +# 'show_legend', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'show_grid', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Create Visualization', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class AnalysisForm(forms.Form): +# """ +# Form for data analysis configuration +# """ +# analysis_type = forms.ChoiceField( +# choices=[ +# ('descriptive', 'Descriptive Analysis'), +# ('trend', 'Trend Analysis'), +# ('correlation', 'Correlation Analysis'), +# ('regression', 'Regression Analysis'), +# ('forecasting', 'Forecasting'), +# ('anomaly', 'Anomaly Detection') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# data_source = forms.ModelChoiceField( +# queryset=None, +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# date_range_start = forms.DateField( +# required=True, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# date_range_end = forms.DateField( +# required=True, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# confidence_level = forms.DecimalField( +# max_digits=5, +# decimal_places=2, +# initial=95.0, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# generate_insights = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['data_source'].queryset = DataSource.objects.filter(tenant=tenant) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Analysis Configuration', +# Row( +# Column('analysis_type', css_class='form-group col-md-6 mb-0'), +# Column('data_source', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('date_range_start', css_class='form-group col-md-6 mb-0'), +# Column('date_range_end', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'confidence_level' +# ), +# Fieldset( +# 'Options', +# HTML('
'), +# 'generate_insights', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Start Analysis', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# diff --git a/analytics/views.py b/analytics/views.py index b95327ea..9f2fa7af 100644 --- a/analytics/views.py +++ b/analytics/views.py @@ -3157,4 +3157,731 @@ def report_list(request): # 'count': len(results) # } # -# return render(request, 'analytics/partials/search_results.html', context) \ No newline at end of file +# return render(request, 'analytics/partials/search_results.html', context) + + +# from django.shortcuts import render, redirect, get_object_or_404 +# from django.contrib.auth.decorators import login_required, permission_required +# from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +# from django.contrib import messages +# from django.views.generic import ( +# CreateView, UpdateView, DeleteView, DetailView, ListView, FormView +# ) +# from django.urls import reverse_lazy, reverse +# from django.http import JsonResponse, HttpResponse +# from django.utils import timezone +# from django.db import transaction +# from django.core.mail import send_mail +# from django.conf import settings +# from viewflow.views import CreateProcessView, UpdateProcessView +# import json +# +# from .models import Dashboard, DashboardWidget, DataSource, Report, MetricDefinition, ReportExecution +# from .forms import ( +# ReportGenerationForm, DashboardCreationForm, DataSourceConfigurationForm, +# MetricCalculationForm, QualityAssuranceForm, DistributionForm, +# VisualizationForm, AnalysisForm +# ) +# from .flows import ReportGenerationFlow, DashboardManagementFlow, MetricCalculationFlow +# +# +# class ReportGenerationView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for report generation workflow +# """ +# model = Report +# form_class = ReportGenerationForm +# template_name = 'analytics/report_generation.html' +# permission_required = 'analytics.can_generate_reports' +# flow_class = ReportGenerationFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create report +# report = form.save(commit=False) +# report.tenant = self.request.user.tenant +# report.created_by = self.request.user +# report.save() +# +# # Save many-to-many relationships +# form.save_m2m() +# +# # Start report generation workflow +# process = self.flow_class.start.run( +# report=report, +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Report generation initiated for "{report.name}". ' +# f'You will be notified when the report is ready.' +# ) +# +# return redirect('analytics:report_detail', pk=report.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Generate Report' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Analytics', 'url': reverse('analytics:dashboard')}, +# {'name': 'Reports', 'url': reverse('analytics:report_list')}, +# {'name': 'Generate Report', 'url': ''} +# ] +# return context +# +# +# class DashboardCreationView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for dashboard creation workflow +# """ +# model = Dashboard +# form_class = DashboardCreationForm +# template_name = 'analytics/dashboard_creation.html' +# permission_required = 'analytics.can_create_dashboards' +# flow_class = DashboardManagementFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create dashboard +# dashboard = form.save(commit=False) +# dashboard.tenant = self.request.user.tenant +# dashboard.created_by = self.request.user +# dashboard.save() +# +# # Start dashboard creation workflow +# process = self.flow_class.start.run( +# dashboard=dashboard, +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Dashboard "{dashboard.name}" created successfully. ' +# f'You can now add widgets and configure the layout.' +# ) +# +# return redirect('analytics:dashboard_detail', pk=dashboard.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Create Dashboard' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Analytics', 'url': reverse('analytics:dashboard')}, +# {'name': 'Dashboards', 'url': reverse('analytics:dashboard_list')}, +# {'name': 'Create Dashboard', 'url': ''} +# ] +# return context +# +# +# class DataSourceConfigurationView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): +# """ +# View for data source configuration +# """ +# model = DataSource +# form_class = DataSourceConfigurationForm +# template_name = 'analytics/data_source_configuration.html' +# permission_required = 'analytics.can_configure_data_sources' +# +# def get_success_url(self): +# return reverse('analytics:data_source_detail', kwargs={'pk': self.object.pk}) +# +# def form_valid(self, form): +# data_source = form.save(commit=False) +# data_source.tenant = self.request.user.tenant +# data_source.created_by = self.request.user +# data_source.save() +# +# # Test connection if requested +# if form.cleaned_data.get('test_connection'): +# connection_result = self.test_data_source_connection(data_source) +# if connection_result['success']: +# messages.success( +# self.request, +# f'Data source "{data_source.name}" configured successfully. Connection test passed.' +# ) +# else: +# messages.warning( +# self.request, +# f'Data source "{data_source.name}" configured, but connection test failed: {connection_result["error"]}' +# ) +# else: +# messages.success( +# self.request, +# f'Data source "{data_source.name}" configured successfully.' +# ) +# +# return super().form_valid(form) +# +# def test_data_source_connection(self, data_source): +# """Test data source connection""" +# try: +# # Implement connection testing logic based on source type +# if data_source.source_type == 'database': +# return self.test_database_connection(data_source) +# elif data_source.source_type == 'api': +# return self.test_api_connection(data_source) +# elif data_source.source_type == 'file': +# return self.test_file_connection(data_source) +# else: +# return {'success': True} +# except Exception as e: +# return {'success': False, 'error': str(e)} +# +# def test_database_connection(self, data_source): +# """Test database connection""" +# # Implement database connection testing +# return {'success': True} +# +# def test_api_connection(self, data_source): +# """Test API connection""" +# # Implement API connection testing +# return {'success': True} +# +# def test_file_connection(self, data_source): +# """Test file connection""" +# # Implement file connection testing +# return {'success': True} +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Configure Data Source' +# return context +# +# +# class MetricCalculationView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for metric calculation workflow +# """ +# model = MetricDefinition +# form_class = MetricCalculationForm +# template_name = 'analytics/metric_calculation.html' +# permission_required = 'analytics.can_calculate_metrics' +# flow_class = MetricCalculationFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create metric definition +# metric = form.save(commit=False) +# metric.tenant = self.request.user.tenant +# metric.created_by = self.request.user +# metric.save() +# +# # Start metric calculation workflow +# process = self.flow_class.start.run( +# metric=metric, +# calculate_now=form.cleaned_data.get('calculate_now', False), +# date_range_start=form.cleaned_data.get('date_range_start'), +# date_range_end=form.cleaned_data.get('date_range_end'), +# created_by=self.request.user +# ) +# +# if form.cleaned_data.get('calculate_now'): +# messages.success( +# self.request, +# f'Metric "{metric.name}" created and calculation initiated. ' +# f'Results will be available shortly.' +# ) +# else: +# messages.success( +# self.request, +# f'Metric "{metric.name}" created successfully.' +# ) +# +# return redirect('analytics:metric_detail', pk=metric.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Calculate Metric' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Analytics', 'url': reverse('analytics:dashboard')}, +# {'name': 'Metrics', 'url': reverse('analytics:metric_list')}, +# {'name': 'Calculate Metric', 'url': ''} +# ] +# return context +# +# +# class QualityAssuranceView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for quality assurance configuration +# """ +# form_class = QualityAssuranceForm +# template_name = 'analytics/quality_assurance.html' +# permission_required = 'analytics.can_perform_qa' +# +# def get_success_url(self): +# return reverse('analytics:dashboard') +# +# def form_valid(self, form): +# qa_config = form.cleaned_data +# +# # Start quality assurance process +# self.start_quality_assurance(qa_config) +# +# messages.success( +# self.request, +# 'Quality assurance process initiated. You will receive a notification when complete.' +# ) +# +# return super().form_valid(form) +# +# def start_quality_assurance(self, config): +# """Start quality assurance process""" +# # This would start the QA process +# pass +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Quality Assurance' +# context['qa_metrics'] = self.get_qa_metrics() +# return context +# +# def get_qa_metrics(self): +# """Get quality assurance metrics""" +# return { +# 'data_accuracy': 98.5, +# 'calculation_accuracy': 99.2, +# 'source_reliability': 97.8, +# 'performance_score': 95.6 +# } +# +# +# class DistributionView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for report distribution +# """ +# form_class = DistributionForm +# template_name = 'analytics/distribution.html' +# permission_required = 'analytics.can_distribute_reports' +# +# def get_success_url(self): +# return reverse('analytics:report_detail', kwargs={'pk': self.kwargs['pk']}) +# +# def form_valid(self, form): +# report = get_object_or_404(Report, pk=self.kwargs['pk']) +# distribution_config = form.cleaned_data +# +# # Start distribution process +# self.distribute_report(report, distribution_config) +# +# messages.success( +# self.request, +# f'Report "{report.name}" distribution initiated.' +# ) +# +# return super().form_valid(form) +# +# def distribute_report(self, report, config): +# """Distribute report based on configuration""" +# method = config['distribution_method'] +# +# if method == 'email': +# self.distribute_via_email(report, config) +# elif method == 'download': +# self.create_download_link(report, config) +# elif method == 'ftp': +# self.upload_to_ftp(report, config) +# elif method == 'api': +# self.publish_to_api(report, config) +# elif method == 'dashboard': +# self.publish_to_dashboard(report, config) +# +# def distribute_via_email(self, report, config): +# """Distribute report via email""" +# recipients = [email.strip() for email in config['recipients'].split(',')] +# +# send_mail( +# subject=config.get('subject', f'Report: {report.name}'), +# message=config.get('message', f'Please find the attached report: {report.name}'), +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=recipients, +# fail_silently=False +# ) +# +# def create_download_link(self, report, config): +# """Create download link for report""" +# # Implement download link creation +# pass +# +# def upload_to_ftp(self, report, config): +# """Upload report to FTP server""" +# # Implement FTP upload +# pass +# +# def publish_to_api(self, report, config): +# """Publish report to API endpoint""" +# # Implement API publication +# pass +# +# def publish_to_dashboard(self, report, config): +# """Publish report to dashboard""" +# # Implement dashboard publication +# pass +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['report'] = get_object_or_404(Report, pk=self.kwargs['pk']) +# context['title'] = 'Distribute Report' +# return context +# +# +# class VisualizationView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for visualization configuration +# """ +# form_class = VisualizationForm +# template_name = 'analytics/visualization.html' +# permission_required = 'analytics.can_create_visualizations' +# +# def get_success_url(self): +# return reverse('analytics:dashboard_detail', kwargs={'pk': self.kwargs['pk']}) +# +# def form_valid(self, form): +# dashboard = get_object_or_404(Dashboard, pk=self.kwargs['pk']) +# visualization_config = form.cleaned_data +# +# # Create visualization widget +# widget = self.create_visualization_widget(dashboard, visualization_config) +# +# messages.success( +# self.request, +# f'Visualization "{visualization_config["title"]}" added to dashboard.' +# ) +# +# return super().form_valid(form) +# +# def create_visualization_widget(self, dashboard, config): +# """Create visualization widget""" +# widget = DashboardWidget.objects.create( +# dashboard=dashboard, +# widget_type='chart', +# title=config['title'], +# configuration=config, +# position_x=0, +# position_y=0, +# width=6, +# height=4, +# created_by=self.request.user +# ) +# return widget +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['dashboard'] = get_object_or_404(Dashboard, pk=self.kwargs['pk']) +# context['title'] = 'Create Visualization' +# return context +# +# +# class AnalysisView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for data analysis +# """ +# form_class = AnalysisForm +# template_name = 'analytics/analysis.html' +# permission_required = 'analytics.can_perform_analysis' +# +# def get_success_url(self): +# return reverse('analytics:dashboard') +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# analysis_config = form.cleaned_data +# +# # Start analysis process +# analysis_result = self.perform_analysis(analysis_config) +# +# messages.success( +# self.request, +# 'Data analysis completed successfully. Results are available in the dashboard.' +# ) +# +# return super().form_valid(form) +# +# def perform_analysis(self, config): +# """Perform data analysis""" +# analysis_type = config['analysis_type'] +# +# if analysis_type == 'descriptive': +# return self.descriptive_analysis(config) +# elif analysis_type == 'trend': +# return self.trend_analysis(config) +# elif analysis_type == 'correlation': +# return self.correlation_analysis(config) +# elif analysis_type == 'regression': +# return self.regression_analysis(config) +# elif analysis_type == 'forecasting': +# return self.forecasting_analysis(config) +# elif analysis_type == 'anomaly': +# return self.anomaly_detection(config) +# +# def descriptive_analysis(self, config): +# """Perform descriptive analysis""" +# # Implement descriptive analysis +# return {} +# +# def trend_analysis(self, config): +# """Perform trend analysis""" +# # Implement trend analysis +# return {} +# +# def correlation_analysis(self, config): +# """Perform correlation analysis""" +# # Implement correlation analysis +# return {} +# +# def regression_analysis(self, config): +# """Perform regression analysis""" +# # Implement regression analysis +# return {} +# +# def forecasting_analysis(self, config): +# """Perform forecasting analysis""" +# # Implement forecasting analysis +# return {} +# +# def anomaly_detection(self, config): +# """Perform anomaly detection""" +# # Implement anomaly detection +# return {} +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Data Analysis' +# return context +# +# +# class DashboardListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for listing dashboards +# """ +# model = Dashboard +# template_name = 'analytics/dashboard_list.html' +# context_object_name = 'dashboards' +# permission_required = 'analytics.view_dashboard' +# paginate_by = 20 +# +# def get_queryset(self): +# queryset = Dashboard.objects.filter(tenant=self.request.user.tenant) +# +# # Apply filters +# search = self.request.GET.get('search') +# if search: +# queryset = queryset.filter(name__icontains=search) +# +# dashboard_type = self.request.GET.get('type') +# if dashboard_type: +# queryset = queryset.filter(dashboard_type=dashboard_type) +# +# return queryset.order_by('-created_at') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Dashboards' +# context['search'] = self.request.GET.get('search', '') +# context['selected_type'] = self.request.GET.get('type', '') +# return context +# +# +# class DashboardDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# """ +# View for dashboard details +# """ +# model = Dashboard +# template_name = 'analytics/dashboard_detail.html' +# context_object_name = 'dashboard' +# permission_required = 'analytics.view_dashboard' +# +# def get_queryset(self): +# return Dashboard.objects.filter(tenant=self.request.user.tenant) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# dashboard = self.object +# context['title'] = dashboard.name +# context['widgets'] = dashboard.widgets.filter(is_active=True).order_by('position_y', 'position_x') +# context['can_edit'] = self.request.user.has_perm('analytics.change_dashboard') +# return context +# +# +# class ReportListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for listing reports +# """ +# model = Report +# template_name = 'analytics/report_list.html' +# context_object_name = 'reports' +# permission_required = 'analytics.view_report' +# paginate_by = 20 +# +# def get_queryset(self): +# queryset = Report.objects.filter(tenant=self.request.user.tenant) +# +# # Apply filters +# search = self.request.GET.get('search') +# if search: +# queryset = queryset.filter(name__icontains=search) +# +# report_type = self.request.GET.get('type') +# if report_type: +# queryset = queryset.filter(report_type=report_type) +# +# return queryset.order_by('-created_at') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Reports' +# context['search'] = self.request.GET.get('search', '') +# context['selected_type'] = self.request.GET.get('type', '') +# return context +# +# +# class ReportDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# """ +# View for report details +# """ +# model = Report +# template_name = 'analytics/report_detail.html' +# context_object_name = 'report' +# permission_required = 'analytics.view_report' +# +# def get_queryset(self): +# return Report.objects.filter(tenant=self.request.user.tenant) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# report = self.object +# context['title'] = report.name +# context['executions'] = report.executions.order_by('-created_at')[:10] +# context['can_generate'] = self.request.user.has_perm('analytics.can_generate_reports') +# return context +# +# +# # AJAX Views +# @login_required +# @permission_required('analytics.can_test_data_sources') +# def test_data_source_ajax(request, data_source_id): +# """AJAX view to test data source connection""" +# if request.method == 'POST': +# try: +# data_source = DataSource.objects.get( +# id=data_source_id, +# tenant=request.user.tenant +# ) +# +# # Test connection +# result = test_data_source_connection(data_source) +# +# return JsonResponse({ +# 'success': result['success'], +# 'message': 'Connection successful' if result['success'] else result.get('error', 'Connection failed') +# }) +# except DataSource.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'Data source not found.' +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# @login_required +# @permission_required('analytics.can_calculate_metrics') +# def calculate_metric_ajax(request, metric_id): +# """AJAX view to calculate metric""" +# if request.method == 'POST': +# try: +# metric = MetricDefinition.objects.get( +# id=metric_id, +# tenant=request.user.tenant +# ) +# +# # Start metric calculation +# process = MetricCalculationFlow.start.run( +# metric=metric, +# calculate_now=True, +# created_by=request.user +# ) +# +# return JsonResponse({ +# 'success': True, +# 'message': 'Metric calculation initiated.' +# }) +# except MetricDefinition.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'Metric not found.' +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# @login_required +# def dashboard_data_ajax(request, dashboard_id): +# """AJAX view to get dashboard data""" +# try: +# dashboard = Dashboard.objects.get( +# id=dashboard_id, +# tenant=request.user.tenant +# ) +# +# widgets_data = [] +# for widget in dashboard.widgets.filter(is_active=True): +# widget_data = { +# 'id': widget.id, +# 'title': widget.title, +# 'type': widget.widget_type, +# 'position': { +# 'x': widget.position_x, +# 'y': widget.position_y, +# 'width': widget.width, +# 'height': widget.height +# }, +# 'data': widget.get_data() # This would be implemented in the model +# } +# widgets_data.append(widget_data) +# +# return JsonResponse({ +# 'success': True, +# 'dashboard': { +# 'id': dashboard.id, +# 'name': dashboard.name, +# 'widgets': widgets_data +# } +# }) +# except Dashboard.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'Dashboard not found.' +# }) +# +# +# def test_data_source_connection(data_source): +# """Test data source connection""" +# try: +# # Implement connection testing logic +# return {'success': True} +# except Exception as e: +# return {'success': False, 'error': str(e)} +# diff --git a/appointments/__pycache__/flows.cpython-312.pyc b/appointments/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..218b52df2f97f08c51e71cd60d155cd205ca9fe1 GIT binary patch literal 182 zcmX@j%ge<81bQ<2GPaj7Fgylv(7|UGpvZKFN(N0vzm*I{OhDdekeXki`k}?CMaBBL ziACj!d5JmYi8+}-PF`tod_hruR%&vIenx(AL1sx}PCQUJF+DXmHLoPTxU#q;H8;M@ zL_e{hAU`v&1SDFlpO%wfUaVJ8d5gm)H$SB`C)KWq6=(}15Ep|OADI~$8H<>KEC9o2 BGJ^mB literal 0 HcmV?d00001 diff --git a/appointments/__pycache__/forms.cpython-312.pyc b/appointments/__pycache__/forms.cpython-312.pyc index 18bfe31a54fc8e9cf8fe48d90628057930382105..f0c15bd1f3561a54eaa79b009e0c7160642a5464 100644 GIT binary patch delta 25 fcmZo%$k@1$k?%AwFBbz4=*jHMn7V5tUvU5cT&D+x delta 25 fcmZo%$k@1$k?%AwFBbz4EOYPAc;UK{uQ&hzVG9S> diff --git a/appointments/__pycache__/views.cpython-312.pyc b/appointments/__pycache__/views.cpython-312.pyc index 29ac94d535e31858a564f9cf4eeb655c13d6687d..8992cf75de1812e5382c091636c894a8445045bc 100644 GIT binary patch delta 29 jcmbP#pJo1i7XH(`yj%=GpeM60W05CQBmY)@#tHfWiWmrV delta 29 kcmbP#pJo1i7XH(`yj%=G@I_}w#+luWjr?2r87Jri0GkpC-v9sr diff --git a/appointments/flows.py b/appointments/flows.py new file mode 100644 index 00000000..f68bbf2e --- /dev/null +++ b/appointments/flows.py @@ -0,0 +1,871 @@ +# """ +# Viewflow workflows for appointments app. +# Provides appointment scheduling, confirmation, and queue management 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 AppointmentRequest, SlotAvailability, WaitingQueue, QueueEntry +# from .views import ( +# AppointmentRequestView, AvailabilityCheckView, AppointmentSchedulingView, +# AppointmentConfirmationView, ReminderView, CheckInView, QueueManagementView, +# TelemedicineSetupView, AppointmentCompletionView, ReschedulingView, +# CancellationView, NoShowHandlingView +# ) +# +# +# class AppointmentSchedulingProcess(Process): +# """ +# Viewflow process model for appointment scheduling +# """ +# appointment_request = ModelField(AppointmentRequest, help_text='Associated appointment request') +# +# # Process status tracking +# request_submitted = models.BooleanField(default=False) +# availability_checked = models.BooleanField(default=False) +# appointment_scheduled = models.BooleanField(default=False) +# confirmation_sent = models.BooleanField(default=False) +# reminders_scheduled = models.BooleanField(default=False) +# patient_checked_in = models.BooleanField(default=False) +# appointment_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Appointment Scheduling Process' +# verbose_name_plural = 'Appointment Scheduling Processes' +# +# +# class AppointmentSchedulingFlow(Flow): +# """ +# Appointment Scheduling Workflow +# +# This flow manages the complete appointment lifecycle from +# request through scheduling, confirmation, and completion. +# """ +# +# process_class = AppointmentSchedulingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_appointment_scheduling) +# .Next(this.submit_request) +# ) +# +# submit_request = ( +# flow_view(AppointmentRequestView) +# .Permission('appointments.can_submit_requests') +# .Next(this.check_availability) +# ) +# +# check_availability = ( +# flow_view(AvailabilityCheckView) +# .Permission('appointments.can_check_availability') +# .Next(this.schedule_appointment) +# ) +# +# schedule_appointment = ( +# flow_view(AppointmentSchedulingView) +# .Permission('appointments.can_schedule_appointments') +# .Next(this.send_confirmation) +# ) +# +# send_confirmation = ( +# flow_view(AppointmentConfirmationView) +# .Permission('appointments.can_send_confirmations') +# .Next(this.schedule_reminders) +# ) +# +# schedule_reminders = ( +# flow_func(this.setup_reminders) +# .Next(this.check_in_patient) +# ) +# +# check_in_patient = ( +# flow_view(CheckInView) +# .Permission('appointments.can_check_in_patients') +# .Next(this.complete_appointment) +# ) +# +# complete_appointment = ( +# flow_func(this.finalize_appointment) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_appointment_scheduling) +# +# # Flow functions +# def start_appointment_scheduling(self, activation): +# """Initialize the appointment scheduling process""" +# process = activation.process +# appointment = process.appointment_request +# +# # Update appointment status +# appointment.status = 'REQUESTED' +# appointment.save() +# +# # Send notification to scheduling staff +# self.notify_scheduling_staff(appointment) +# +# # Check for urgent appointments +# if appointment.priority in ['HIGH', 'URGENT'] or appointment.urgency_score >= 8: +# self.notify_urgent_appointment(appointment) +# +# def setup_reminders(self, activation): +# """Setup appointment reminders""" +# process = activation.process +# appointment = process.appointment_request +# +# # Mark reminders as scheduled +# process.reminders_scheduled = True +# process.save() +# +# # Schedule reminder tasks +# self.schedule_appointment_reminders(appointment) +# +# # Send immediate confirmation if telemedicine +# if appointment.is_telemedicine: +# self.setup_telemedicine_meeting(appointment) +# +# def finalize_appointment(self, activation): +# """Finalize the appointment process""" +# process = activation.process +# appointment = process.appointment_request +# +# # Update appointment status +# appointment.status = 'COMPLETED' +# appointment.completed_at = timezone.now() +# appointment.save() +# +# # Mark process as completed +# process.appointment_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_appointment_completion(appointment) +# +# # Update provider schedule +# self.update_provider_schedule(appointment) +# +# # Generate follow-up recommendations +# self.generate_follow_up_recommendations(appointment) +# +# def end_appointment_scheduling(self, activation): +# """End the appointment scheduling workflow""" +# process = activation.process +# +# # Generate appointment summary +# self.generate_appointment_summary(process.appointment_request) +# +# # Helper methods +# def notify_scheduling_staff(self, appointment): +# """Notify scheduling staff of new appointment request""" +# from django.contrib.auth.models import Group +# +# scheduling_staff = User.objects.filter( +# groups__name='Scheduling Staff' +# ) +# +# for staff in scheduling_staff: +# send_mail( +# subject=f'New Appointment Request: {appointment.patient.get_full_name()}', +# message=f'New {appointment.get_appointment_type_display()} appointment request for {appointment.specialty}.', +# from_email='scheduling@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_urgent_appointment(self, appointment): +# """Notify of urgent appointment request""" +# scheduling_managers = User.objects.filter( +# groups__name='Scheduling Managers' +# ) +# +# for manager in scheduling_managers: +# send_mail( +# subject=f'URGENT Appointment Request: {appointment.patient.get_full_name()}', +# message=f'{appointment.get_priority_display()} appointment request requires immediate attention.', +# from_email='scheduling@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def schedule_appointment_reminders(self, appointment): +# """Schedule appointment reminder tasks""" +# if appointment.scheduled_datetime: +# # Schedule 24-hour reminder +# reminder_24h = appointment.scheduled_datetime - timedelta(hours=24) +# if reminder_24h > timezone.now(): +# send_appointment_reminder.apply_async( +# args=[appointment.id, '24_hour'], +# eta=reminder_24h +# ) +# +# # Schedule 2-hour reminder +# reminder_2h = appointment.scheduled_datetime - timedelta(hours=2) +# if reminder_2h > timezone.now(): +# send_appointment_reminder.apply_async( +# args=[appointment.id, '2_hour'], +# eta=reminder_2h +# ) +# +# def setup_telemedicine_meeting(self, appointment): +# """Setup telemedicine meeting details""" +# # This would integrate with telemedicine platforms +# pass +# +# def notify_appointment_completion(self, appointment): +# """Notify appointment completion""" +# # Notify patient +# if appointment.patient.email: +# send_mail( +# subject='Appointment Completed', +# message=f'Your appointment with {appointment.provider.get_full_name()} has been completed.', +# from_email='appointments@hospital.com', +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def update_provider_schedule(self, appointment): +# """Update provider schedule after appointment""" +# # This would update provider availability +# pass +# +# def generate_follow_up_recommendations(self, appointment): +# """Generate follow-up appointment recommendations""" +# # This would analyze appointment and suggest follow-ups +# pass +# +# def generate_appointment_summary(self, appointment): +# """Generate appointment summary""" +# # This would generate appointment summary report +# pass +# +# +# class AppointmentConfirmationProcess(Process): +# """ +# Viewflow process model for appointment confirmation +# """ +# appointment_request = ModelField(AppointmentRequest, help_text='Associated appointment request') +# +# # Process status tracking +# confirmation_requested = models.BooleanField(default=False) +# patient_contacted = models.BooleanField(default=False) +# confirmation_received = models.BooleanField(default=False) +# details_updated = models.BooleanField(default=False) +# confirmation_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Appointment Confirmation Process' +# verbose_name_plural = 'Appointment Confirmation Processes' +# +# +# class AppointmentConfirmationFlow(Flow): +# """ +# Appointment Confirmation Workflow +# +# This flow manages appointment confirmation including patient +# contact, confirmation receipt, and detail updates. +# """ +# +# process_class = AppointmentConfirmationProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_confirmation) +# .Next(this.request_confirmation) +# ) +# +# request_confirmation = ( +# flow_func(this.send_confirmation_request) +# .Next(this.contact_patient) +# ) +# +# contact_patient = ( +# flow_view(PatientContactView) +# .Permission('appointments.can_contact_patients') +# .Next(this.receive_confirmation) +# ) +# +# receive_confirmation = ( +# flow_view(ConfirmationReceiptView) +# .Permission('appointments.can_receive_confirmations') +# .Next(this.update_details) +# ) +# +# update_details = ( +# flow_view(DetailUpdateView) +# .Permission('appointments.can_update_details') +# .Next(this.complete_confirmation) +# ) +# +# complete_confirmation = ( +# flow_func(this.finalize_confirmation) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_confirmation) +# +# # Flow functions +# def start_confirmation(self, activation): +# """Initialize the confirmation process""" +# process = activation.process +# appointment = process.appointment_request +# +# # Send confirmation request +# self.send_confirmation_request(appointment) +# +# def send_confirmation_request(self, activation): +# """Send confirmation request to patient""" +# process = activation.process +# appointment = process.appointment_request +# +# # Mark confirmation requested +# process.confirmation_requested = True +# process.save() +# +# # Send confirmation request via preferred method +# self.send_confirmation_via_preferred_method(appointment) +# +# def finalize_confirmation(self, activation): +# """Finalize the confirmation process""" +# process = activation.process +# appointment = process.appointment_request +# +# # Update appointment status +# appointment.status = 'CONFIRMED' +# appointment.save() +# +# # Mark process as completed +# process.confirmation_completed = True +# process.save() +# +# # Send confirmation completion notification +# self.notify_confirmation_completion(appointment) +# +# def end_confirmation(self, activation): +# """End the confirmation workflow""" +# process = activation.process +# +# # Log confirmation completion +# self.log_confirmation_completion(process.appointment_request) +# +# # Helper methods +# def send_confirmation_via_preferred_method(self, appointment): +# """Send confirmation via patient's preferred method""" +# preferences = appointment.reminder_preferences +# +# if preferences.get('email', True) and appointment.patient.email: +# self.send_email_confirmation(appointment) +# +# if preferences.get('sms', False) and appointment.patient.phone: +# self.send_sms_confirmation(appointment) +# +# if preferences.get('phone', False): +# self.schedule_phone_confirmation(appointment) +# +# def send_email_confirmation(self, appointment): +# """Send email confirmation""" +# send_mail( +# subject='Appointment Confirmation Required', +# message=f'Please confirm your appointment on {appointment.scheduled_datetime}.', +# from_email='appointments@hospital.com', +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def send_sms_confirmation(self, appointment): +# """Send SMS confirmation""" +# # This would integrate with SMS service +# pass +# +# def schedule_phone_confirmation(self, appointment): +# """Schedule phone confirmation call""" +# # This would schedule a phone call task +# pass +# +# def notify_confirmation_completion(self, appointment): +# """Notify confirmation completion""" +# # Notify scheduling staff +# scheduling_staff = User.objects.filter( +# groups__name='Scheduling Staff' +# ) +# +# for staff in scheduling_staff: +# send_mail( +# subject=f'Appointment Confirmed: {appointment.patient.get_full_name()}', +# message=f'Patient has confirmed appointment for {appointment.scheduled_datetime}.', +# from_email='appointments@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def log_confirmation_completion(self, appointment): +# """Log confirmation completion""" +# # This would log confirmation details +# pass +# +# +# class QueueManagementProcess(Process): +# """ +# Viewflow process model for queue management +# """ +# queue_entry = ModelField(QueueEntry, help_text='Associated queue entry') +# +# # Process status tracking +# patient_queued = models.BooleanField(default=False) +# position_assigned = models.BooleanField(default=False) +# wait_time_estimated = models.BooleanField(default=False) +# patient_called = models.BooleanField(default=False) +# service_started = models.BooleanField(default=False) +# service_completed = models.BooleanField(default=False) +# queue_exited = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Queue Management Process' +# verbose_name_plural = 'Queue Management Processes' +# +# +# class QueueManagementFlow(Flow): +# """ +# Queue Management Workflow +# +# This flow manages patient flow through waiting queues +# including position assignment and service coordination. +# """ +# +# process_class = QueueManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_queue_management) +# .Next(this.queue_patient) +# ) +# +# queue_patient = ( +# flow_view(PatientQueuingView) +# .Permission('appointments.can_queue_patients') +# .Next(this.assign_position) +# ) +# +# assign_position = ( +# flow_func(this.calculate_queue_position) +# .Next(this.estimate_wait_time) +# ) +# +# estimate_wait_time = ( +# flow_func(this.calculate_wait_time) +# .Next(this.call_patient) +# ) +# +# call_patient = ( +# flow_view(PatientCallingView) +# .Permission('appointments.can_call_patients') +# .Next(this.start_service) +# ) +# +# start_service = ( +# flow_view(ServiceStartView) +# .Permission('appointments.can_start_service') +# .Next(this.complete_service) +# ) +# +# complete_service = ( +# flow_view(ServiceCompletionView) +# .Permission('appointments.can_complete_service') +# .Next(this.exit_queue) +# ) +# +# exit_queue = ( +# flow_func(this.finalize_queue_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_queue_management) +# +# # Flow functions +# def start_queue_management(self, activation): +# """Initialize the queue management process""" +# process = activation.process +# entry = process.queue_entry +# +# # Update entry status +# entry.status = 'WAITING' +# entry.save() +# +# # Send queue notification +# self.notify_queue_entry(entry) +# +# def calculate_queue_position(self, activation): +# """Calculate and assign queue position""" +# process = activation.process +# entry = process.queue_entry +# +# # Calculate position based on priority and arrival time +# position = self.determine_queue_position(entry) +# entry.queue_position = position +# entry.save() +# +# # Mark position assigned +# process.position_assigned = True +# process.save() +# +# # Update other queue positions +# self.update_queue_positions(entry.queue) +# +# def calculate_wait_time(self, activation): +# """Calculate estimated wait time""" +# process = activation.process +# entry = process.queue_entry +# +# # Calculate estimated service time +# estimated_time = self.estimate_service_time(entry) +# entry.estimated_service_time = estimated_time +# entry.save() +# +# # Mark wait time estimated +# process.wait_time_estimated = True +# process.save() +# +# # Send wait time notification +# self.notify_wait_time(entry) +# +# def finalize_queue_management(self, activation): +# """Finalize the queue management process""" +# process = activation.process +# entry = process.queue_entry +# +# # Update entry status +# entry.status = 'COMPLETED' +# entry.served_at = timezone.now() +# entry.save() +# +# # Mark process as completed +# process.queue_exited = True +# process.save() +# +# # Update queue metrics +# self.update_queue_metrics(entry) +# +# # Notify next patient +# self.notify_next_patient(entry.queue) +# +# def end_queue_management(self, activation): +# """End the queue management workflow""" +# process = activation.process +# +# # Generate queue summary +# self.generate_queue_summary(process.queue_entry) +# +# # Helper methods +# def notify_queue_entry(self, entry): +# """Notify patient of queue entry""" +# if entry.patient.email: +# send_mail( +# subject='Added to Waiting Queue', +# message=f'You have been added to the {entry.queue.name} queue.', +# from_email='appointments@hospital.com', +# recipient_list=[entry.patient.email], +# fail_silently=True +# ) +# +# def determine_queue_position(self, entry): +# """Determine queue position based on priority""" +# # This would implement priority-based positioning logic +# return entry.queue.current_queue_size + 1 +# +# def update_queue_positions(self, queue): +# """Update positions for all entries in queue""" +# entries = queue.queue_entries.filter(status='WAITING').order_by('priority_score', 'joined_at') +# for i, entry in enumerate(entries, 1): +# entry.queue_position = i +# entry.save() +# +# def estimate_service_time(self, entry): +# """Estimate service time for queue entry""" +# queue = entry.queue +# position = entry.queue_position +# avg_service_time = queue.average_service_time_minutes +# +# estimated_minutes = position * avg_service_time +# return timezone.now() + timedelta(minutes=estimated_minutes) +# +# def notify_wait_time(self, entry): +# """Notify patient of estimated wait time""" +# if entry.patient.email and entry.estimated_service_time: +# wait_minutes = int((entry.estimated_service_time - timezone.now()).total_seconds() / 60) +# send_mail( +# subject='Queue Wait Time Update', +# message=f'Your estimated wait time is {wait_minutes} minutes.', +# from_email='appointments@hospital.com', +# recipient_list=[entry.patient.email], +# fail_silently=True +# ) +# +# def update_queue_metrics(self, entry): +# """Update queue performance metrics""" +# # This would update queue analytics +# pass +# +# def notify_next_patient(self, queue): +# """Notify next patient in queue""" +# next_entry = queue.queue_entries.filter( +# status='WAITING' +# ).order_by('queue_position').first() +# +# if next_entry: +# self.notify_patient_ready(next_entry) +# +# def notify_patient_ready(self, entry): +# """Notify patient they are ready to be called""" +# if entry.patient.email: +# send_mail( +# subject='Ready for Appointment', +# message='You will be called shortly for your appointment.', +# from_email='appointments@hospital.com', +# recipient_list=[entry.patient.email], +# fail_silently=True +# ) +# +# def generate_queue_summary(self, entry): +# """Generate queue management summary""" +# # This would generate queue analytics +# pass +# +# +# class TelemedicineSetupProcess(Process): +# """ +# Viewflow process model for telemedicine setup +# """ +# appointment_request = ModelField(AppointmentRequest, help_text='Associated appointment request') +# +# # Process status tracking +# platform_selected = models.BooleanField(default=False) +# meeting_created = models.BooleanField(default=False) +# credentials_sent = models.BooleanField(default=False) +# technical_check_completed = models.BooleanField(default=False) +# meeting_ready = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Telemedicine Setup Process' +# verbose_name_plural = 'Telemedicine Setup Processes' +# +# +# class TelemedicineSetupFlow(Flow): +# """ +# Telemedicine Setup Workflow +# +# This flow manages telemedicine appointment setup including +# platform selection, meeting creation, and technical verification. +# """ +# +# process_class = TelemedicineSetupProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_telemedicine_setup) +# .Next(this.select_platform) +# ) +# +# select_platform = ( +# flow_view(PlatformSelectionView) +# .Permission('appointments.can_select_platforms') +# .Next(this.create_meeting) +# ) +# +# create_meeting = ( +# flow_view(MeetingCreationView) +# .Permission('appointments.can_create_meetings') +# .Next(this.send_credentials) +# ) +# +# send_credentials = ( +# flow_view(CredentialSendingView) +# .Permission('appointments.can_send_credentials') +# .Next(this.technical_check) +# ) +# +# technical_check = ( +# flow_view(TechnicalCheckView) +# .Permission('appointments.can_perform_technical_checks') +# .Next(this.finalize_setup) +# ) +# +# finalize_setup = ( +# flow_func(this.complete_telemedicine_setup) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_telemedicine_setup) +# +# # Flow functions +# def start_telemedicine_setup(self, activation): +# """Initialize the telemedicine setup process""" +# process = activation.process +# appointment = process.appointment_request +# +# # Mark as telemedicine appointment +# appointment.is_telemedicine = True +# appointment.save() +# +# # Send setup notification +# self.notify_telemedicine_setup(appointment) +# +# def complete_telemedicine_setup(self, activation): +# """Finalize the telemedicine setup process""" +# process = activation.process +# appointment = process.appointment_request +# +# # Mark meeting as ready +# process.meeting_ready = True +# process.save() +# +# # Send final meeting details +# self.send_final_meeting_details(appointment) +# +# # Schedule pre-meeting reminder +# self.schedule_pre_meeting_reminder(appointment) +# +# def end_telemedicine_setup(self, activation): +# """End the telemedicine setup workflow""" +# process = activation.process +# +# # Log setup completion +# self.log_telemedicine_setup(process.appointment_request) +# +# # Helper methods +# def notify_telemedicine_setup(self, appointment): +# """Notify patient of telemedicine setup""" +# if appointment.patient.email: +# send_mail( +# subject='Telemedicine Appointment Setup', +# message='Your telemedicine appointment is being set up. You will receive meeting details shortly.', +# from_email='telemedicine@hospital.com', +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def send_final_meeting_details(self, appointment): +# """Send final meeting details to patient""" +# if appointment.patient.email: +# send_mail( +# subject='Telemedicine Meeting Details', +# message=f'Meeting URL: {appointment.meeting_url}\nMeeting ID: {appointment.meeting_id}', +# from_email='telemedicine@hospital.com', +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def schedule_pre_meeting_reminder(self, appointment): +# """Schedule pre-meeting reminder""" +# if appointment.scheduled_datetime: +# reminder_time = appointment.scheduled_datetime - timedelta(minutes=15) +# if reminder_time > timezone.now(): +# send_telemedicine_reminder.apply_async( +# args=[appointment.id], +# eta=reminder_time +# ) +# +# def log_telemedicine_setup(self, appointment): +# """Log telemedicine setup completion""" +# # This would log setup details +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def send_appointment_reminder(appointment_id, reminder_type): +# """Background task to send appointment reminders""" +# try: +# appointment = AppointmentRequest.objects.get(id=appointment_id) +# +# if reminder_type == '24_hour': +# subject = 'Appointment Reminder - Tomorrow' +# message = f'Reminder: You have an appointment tomorrow at {appointment.scheduled_datetime}.' +# elif reminder_type == '2_hour': +# subject = 'Appointment Reminder - 2 Hours' +# message = f'Reminder: You have an appointment in 2 hours at {appointment.scheduled_datetime}.' +# +# if appointment.patient.email: +# send_mail( +# subject=subject, +# message=message, +# from_email='appointments@hospital.com', +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def send_telemedicine_reminder(appointment_id): +# """Background task to send telemedicine pre-meeting reminder""" +# try: +# appointment = AppointmentRequest.objects.get(id=appointment_id) +# +# if appointment.patient.email: +# send_mail( +# subject='Telemedicine Meeting Starting Soon', +# message=f'Your telemedicine appointment starts in 15 minutes. Meeting URL: {appointment.meeting_url}', +# from_email='telemedicine@hospital.com', +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def auto_confirm_appointments(): +# """Background task to automatically confirm appointments""" +# try: +# # This would implement auto-confirmation logic +# return True +# except Exception: +# return False +# +# +# @celery.job +# def manage_no_shows(): +# """Background task to manage no-show appointments""" +# try: +# # This would identify and handle no-show appointments +# return True +# except Exception: +# return False +# +# +# @celery.job +# def optimize_schedules(): +# """Background task to optimize provider schedules""" +# try: +# # This would implement schedule optimization +# return True +# except Exception: +# return False +# +# +# @celery.job +# def update_queue_positions(): +# """Background task to update queue positions""" +# try: +# # This would update queue positions and wait times +# return True +# except Exception: +# return False +# diff --git a/appointments/forms.py b/appointments/forms.py index 2d353f5c..776859a9 100644 --- a/appointments/forms.py +++ b/appointments/forms.py @@ -439,3 +439,751 @@ class SlotSearchForm(forms.Form): role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT'] ).order_by('last_name', 'first_name') + +# from django import forms +# from django.core.exceptions import ValidationError +# from django.utils import timezone +# from django.contrib.auth.models import User +# from crispy_forms.helper import FormHelper +# from crispy_forms.layout import Layout, Fieldset, Submit, Row, Column, HTML, Div +# from crispy_forms.bootstrap import FormActions +# from datetime import datetime, timedelta +# +# from .models import Appointment, AppointmentConfirmation, Queue, TelemedicineSession +# from patients.models import Patient +# from core.models import Department +# +# +# class AppointmentSchedulingForm(forms.ModelForm): +# """ +# Form for appointment scheduling +# """ +# patient_search = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={ +# 'class': 'form-control', +# 'placeholder': 'Search patient by name, ID, or phone...', +# 'data-toggle': 'patient-search' +# }) +# ) +# preferred_time_1 = forms.TimeField( +# required=False, +# widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) +# ) +# preferred_time_2 = forms.TimeField( +# required=False, +# widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) +# ) +# preferred_time_3 = forms.TimeField( +# required=False, +# widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) +# ) +# special_instructions = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# send_confirmation = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# send_reminder = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = Appointment +# fields = [ +# 'patient', 'provider', 'department', 'appointment_type', +# 'appointment_date', 'appointment_time', 'duration', +# 'urgency', 'reason', 'notes', 'special_instructions', +# 'send_confirmation', 'send_reminder' +# ] +# widgets = { +# 'patient': forms.Select(attrs={'class': 'form-control'}), +# 'provider': forms.Select(attrs={'class': 'form-control'}), +# 'department': forms.Select(attrs={'class': 'form-control'}), +# 'appointment_type': forms.Select(attrs={'class': 'form-control'}), +# 'appointment_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), +# 'appointment_time': forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}), +# 'duration': forms.NumberInput(attrs={'class': 'form-control'}), +# 'urgency': forms.Select(attrs={'class': 'form-control'}), +# 'reason': forms.TextInput(attrs={'class': 'form-control'}), +# 'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['patient'].queryset = Patient.objects.filter(tenant=tenant) +# self.fields['provider'].queryset = User.objects.filter( +# tenant=tenant, +# groups__name__in=['Doctors', 'Nurses', 'Specialists'] +# ) +# self.fields['department'].queryset = Department.objects.filter(tenant=tenant) +# +# # Set minimum date to today +# self.fields['appointment_date'].widget.attrs['min'] = timezone.now().date().isoformat() +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Patient Information', +# 'patient_search', +# 'patient' +# ), +# Fieldset( +# 'Appointment Details', +# Row( +# Column('provider', css_class='form-group col-md-6 mb-0'), +# Column('department', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('appointment_type', css_class='form-group col-md-6 mb-0'), +# Column('urgency', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('appointment_date', css_class='form-group col-md-4 mb-0'), +# Column('appointment_time', css_class='form-group col-md-4 mb-0'), +# Column('duration', css_class='form-group col-md-4 mb-0'), +# css_class='form-row' +# ), +# 'reason', +# 'notes', +# 'special_instructions' +# ), +# Fieldset( +# 'Preferred Times (Alternative Options)', +# Row( +# Column('preferred_time_1', css_class='form-group col-md-4 mb-0'), +# Column('preferred_time_2', css_class='form-group col-md-4 mb-0'), +# Column('preferred_time_3', css_class='form-group col-md-4 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Notifications', +# HTML('
'), +# 'send_confirmation', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'send_reminder', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Schedule Appointment', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# appointment_date = cleaned_data.get('appointment_date') +# appointment_time = cleaned_data.get('appointment_time') +# provider = cleaned_data.get('provider') +# +# if appointment_date and appointment_time: +# appointment_datetime = datetime.combine(appointment_date, appointment_time) +# +# # Check if appointment is in the past +# if appointment_datetime < timezone.now(): +# raise ValidationError('Appointment cannot be scheduled in the past.') +# +# # Check provider availability +# if provider and self.check_provider_conflict(provider, appointment_datetime): +# raise ValidationError('Provider is not available at the selected time.') +# +# return cleaned_data +# +# def check_provider_conflict(self, provider, appointment_datetime): +# """Check if provider has conflicting appointments""" +# duration = self.cleaned_data.get('duration', 30) +# end_time = appointment_datetime + timedelta(minutes=duration) +# +# conflicts = Appointment.objects.filter( +# provider=provider, +# appointment_date=appointment_datetime.date(), +# status__in=['scheduled', 'confirmed', 'in_progress'] +# ).exclude(id=self.instance.id if self.instance else None) +# +# for conflict in conflicts: +# conflict_start = datetime.combine(conflict.appointment_date, conflict.appointment_time) +# conflict_end = conflict_start + timedelta(minutes=conflict.duration) +# +# if (appointment_datetime < conflict_end and end_time > conflict_start): +# return True +# +# return False +# +# +# class AppointmentConfirmationForm(forms.ModelForm): +# """ +# Form for appointment confirmation +# """ +# confirmation_method = forms.ChoiceField( +# choices=[ +# ('phone', 'Phone Call'), +# ('email', 'Email'), +# ('sms', 'SMS'), +# ('in_person', 'In Person'), +# ('online', 'Online Portal') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# contact_attempts = forms.IntegerField( +# initial=1, +# min_value=1, +# max_value=5, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# confirmation_notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# reschedule_requested = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# new_preferred_date = forms.DateField( +# required=False, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# new_preferred_time = forms.TimeField( +# required=False, +# widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) +# ) +# +# class Meta: +# model = AppointmentConfirmation +# fields = [ +# 'confirmation_method', 'contact_attempts', 'confirmation_notes', +# 'reschedule_requested', 'new_preferred_date', 'new_preferred_time' +# ] +# +# def __init__(self, *args, **kwargs): +# appointment = kwargs.pop('appointment', None) +# super().__init__(*args, **kwargs) +# +# self.appointment = appointment +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Confirmation Details', +# Row( +# Column('confirmation_method', css_class='form-group col-md-6 mb-0'), +# Column('contact_attempts', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'confirmation_notes' +# ), +# Fieldset( +# 'Reschedule Request', +# HTML('
'), +# 'reschedule_requested', +# HTML( +# ''), +# HTML('
'), +# Row( +# Column('new_preferred_date', css_class='form-group col-md-6 mb-0'), +# Column('new_preferred_time', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# FormActions( +# Submit('submit', 'Confirm Appointment', css_class='btn btn-primary'), +# HTML( +# 'Cancel') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# reschedule_requested = cleaned_data.get('reschedule_requested') +# new_preferred_date = cleaned_data.get('new_preferred_date') +# new_preferred_time = cleaned_data.get('new_preferred_time') +# +# if reschedule_requested: +# if not new_preferred_date: +# raise ValidationError('New preferred date is required when reschedule is requested.') +# if not new_preferred_time: +# raise ValidationError('New preferred time is required when reschedule is requested.') +# +# return cleaned_data +# +# +# class QueueManagementForm(forms.ModelForm): +# """ +# Form for queue management +# """ +# estimated_wait_time = forms.IntegerField( +# required=False, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# priority_adjustment = forms.ChoiceField( +# choices=[ +# ('none', 'No Change'), +# ('increase', 'Increase Priority'), +# ('decrease', 'Decrease Priority') +# ], +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# queue_notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# notify_patient = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = Queue +# fields = [ +# 'queue_type', 'priority', 'estimated_wait_time', +# 'priority_adjustment', 'queue_notes', 'notify_patient' +# ] +# widgets = { +# 'queue_type': forms.Select(attrs={'class': 'form-control'}), +# 'priority': forms.Select(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Queue Configuration', +# Row( +# Column('queue_type', css_class='form-group col-md-6 mb-0'), +# Column('priority', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('estimated_wait_time', css_class='form-group col-md-6 mb-0'), +# Column('priority_adjustment', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'queue_notes' +# ), +# Fieldset( +# 'Notifications', +# HTML('
'), +# 'notify_patient', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Update Queue', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class TelemedicineSetupForm(forms.ModelForm): +# """ +# Form for telemedicine session setup +# """ +# platform = forms.ChoiceField( +# choices=[ +# ('zoom', 'Zoom'), +# ('teams', 'Microsoft Teams'), +# ('webex', 'Cisco Webex'), +# ('meet', 'Google Meet'), +# ('custom', 'Custom Platform') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# test_connection = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# send_instructions = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# backup_phone = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# technical_support_contact = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# session_recording = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = TelemedicineSession +# fields = [ +# 'platform', 'meeting_url', 'meeting_id', 'meeting_password', +# 'test_connection', 'send_instructions', 'backup_phone', +# 'technical_support_contact', 'session_recording' +# ] +# widgets = { +# 'meeting_url': forms.URLInput(attrs={'class': 'form-control'}), +# 'meeting_id': forms.TextInput(attrs={'class': 'form-control'}), +# 'meeting_password': forms.TextInput(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# appointment = kwargs.pop('appointment', None) +# super().__init__(*args, **kwargs) +# +# self.appointment = appointment +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Platform Configuration', +# 'platform', +# 'meeting_url', +# Row( +# Column('meeting_id', css_class='form-group col-md-6 mb-0'), +# Column('meeting_password', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Support Information', +# Row( +# Column('backup_phone', css_class='form-group col-md-6 mb-0'), +# Column('technical_support_contact', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Session Options', +# HTML('
'), +# 'test_connection', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'send_instructions', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'session_recording', +# HTML( +# ''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Setup Telemedicine', css_class='btn btn-primary'), +# HTML( +# 'Cancel') +# ) +# ) +# +# def clean_meeting_url(self): +# meeting_url = self.cleaned_data.get('meeting_url') +# platform = self.cleaned_data.get('platform') +# +# if platform and meeting_url: +# # Validate URL format based on platform +# if platform == 'zoom' and 'zoom.us' not in meeting_url: +# raise ValidationError('Invalid Zoom meeting URL format.') +# elif platform == 'teams' and 'teams.microsoft.com' not in meeting_url: +# raise ValidationError('Invalid Microsoft Teams meeting URL format.') +# elif platform == 'webex' and 'webex.com' not in meeting_url: +# raise ValidationError('Invalid Webex meeting URL format.') +# elif platform == 'meet' and 'meet.google.com' not in meeting_url: +# raise ValidationError('Invalid Google Meet URL format.') +# +# return meeting_url +# +# +# class AppointmentRescheduleForm(forms.Form): +# """ +# Form for appointment rescheduling +# """ +# new_date = forms.DateField( +# required=True, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# new_time = forms.TimeField( +# required=True, +# widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) +# ) +# new_provider = forms.ModelChoiceField( +# queryset=None, +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# reschedule_reason = forms.ChoiceField( +# choices=[ +# ('patient_request', 'Patient Request'), +# ('provider_unavailable', 'Provider Unavailable'), +# ('emergency', 'Emergency'), +# ('equipment_issue', 'Equipment Issue'), +# ('other', 'Other') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# notify_patient = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# appointment = kwargs.pop('appointment', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['new_provider'].queryset = User.objects.filter( +# tenant=tenant, +# groups__name__in=['Doctors', 'Nurses', 'Specialists'] +# ) +# +# # Set minimum date to today +# self.fields['new_date'].widget.attrs['min'] = timezone.now().date().isoformat() +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'New Appointment Details', +# Row( +# Column('new_date', css_class='form-group col-md-6 mb-0'), +# Column('new_time', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'new_provider' +# ), +# Fieldset( +# 'Reschedule Information', +# 'reschedule_reason', +# 'notes' +# ), +# Fieldset( +# 'Notifications', +# HTML('
'), +# 'notify_patient', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Reschedule Appointment', css_class='btn btn-primary'), +# HTML( +# 'Cancel') +# ) +# ) +# +# +# class AppointmentCancellationForm(forms.Form): +# """ +# Form for appointment cancellation +# """ +# cancellation_reason = forms.ChoiceField( +# choices=[ +# ('patient_request', 'Patient Request'), +# ('provider_unavailable', 'Provider Unavailable'), +# ('patient_no_show', 'Patient No Show'), +# ('emergency', 'Emergency'), +# ('equipment_failure', 'Equipment Failure'), +# ('other', 'Other') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# cancellation_notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# offer_reschedule = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# notify_patient = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# refund_required = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Cancellation Details', +# 'cancellation_reason', +# 'cancellation_notes' +# ), +# Fieldset( +# 'Follow-up Actions', +# HTML('
'), +# 'offer_reschedule', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'notify_patient', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'refund_required', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Cancel Appointment', css_class='btn btn-danger'), +# HTML( +# 'Back') +# ) +# ) +# +# +# class AppointmentCheckInForm(forms.Form): +# """ +# Form for appointment check-in +# """ +# arrival_time = forms.TimeField( +# initial=timezone.now().time(), +# widget=forms.TimeInput(attrs={'class': 'form-control', 'type': 'time'}) +# ) +# insurance_verified = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# copay_collected = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# forms_completed = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# vitals_required = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# special_needs = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 2}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Check-in Information', +# 'arrival_time', +# 'special_needs' +# ), +# Fieldset( +# 'Pre-visit Tasks', +# HTML('
'), +# 'insurance_verified', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'copay_collected', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'forms_completed', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'vitals_required', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Check In Patient', css_class='btn btn-primary'), +# HTML( +# 'Cancel') +# ) +# ) +# +# +# class BulkAppointmentForm(forms.Form): +# """ +# Form for bulk appointment operations +# """ +# action = forms.ChoiceField( +# choices=[ +# ('confirm', 'Confirm Appointments'), +# ('reschedule', 'Reschedule Appointments'), +# ('cancel', 'Cancel Appointments'), +# ('send_reminders', 'Send Reminders') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# appointment_ids = forms.CharField( +# widget=forms.HiddenInput() +# ) +# bulk_date = forms.DateField( +# required=False, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# bulk_reason = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# notify_patients = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# 'appointment_ids', +# Fieldset( +# 'Bulk Operation', +# 'action', +# 'bulk_date', +# 'bulk_reason' +# ), +# Fieldset( +# 'Notifications', +# HTML('
'), +# 'notify_patients', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Execute Bulk Operation', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# diff --git a/appointments/views.py b/appointments/views.py index eb643ade..d3ed1966 100644 --- a/appointments/views.py +++ b/appointments/views.py @@ -3209,3 +3209,907 @@ def reschedule_appointment(request, appointment_id): # 'appointment': session.appointment # }) # + + +# from django.shortcuts import render, redirect, get_object_or_404 +# from django.contrib.auth.decorators import login_required, permission_required +# from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +# from django.contrib import messages +# from django.views.generic import ( +# CreateView, UpdateView, DeleteView, DetailView, ListView, FormView +# ) +# from django.urls import reverse_lazy, reverse +# from django.http import JsonResponse, HttpResponse +# from django.utils import timezone +# from django.db import transaction +# from django.core.mail import send_mail +# from django.conf import settings +# from django.db.models import Q, Count +# from viewflow.views import CreateProcessView, UpdateProcessView +# from datetime import datetime, timedelta +# import json +# +# from .models import Appointment, AppointmentConfirmation, Queue, TelemedicineSession +# from .forms import ( +# AppointmentSchedulingForm, AppointmentConfirmationForm, QueueManagementForm, +# TelemedicineSetupForm, AppointmentRescheduleForm, AppointmentCancellationForm, +# AppointmentCheckInForm, BulkAppointmentForm +# ) +# from .flows import AppointmentSchedulingFlow, AppointmentConfirmationFlow, QueueManagementFlow, TelemedicineSetupFlow +# from patients.models import Patient +# +# +# class AppointmentSchedulingView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for appointment scheduling workflow +# """ +# model = Appointment +# form_class = AppointmentSchedulingForm +# template_name = 'appointments/appointment_scheduling.html' +# permission_required = 'appointments.can_schedule_appointments' +# flow_class = AppointmentSchedulingFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create appointment +# appointment = form.save(commit=False) +# appointment.tenant = self.request.user.tenant +# appointment.scheduled_by = self.request.user +# appointment.status = 'scheduled' +# appointment.save() +# +# # Start appointment scheduling workflow +# process = self.flow_class.start.run( +# appointment=appointment, +# send_confirmation=form.cleaned_data.get('send_confirmation', True), +# send_reminder=form.cleaned_data.get('send_reminder', True), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Appointment scheduled successfully for {appointment.patient.get_full_name()} ' +# f'on {appointment.appointment_date} at {appointment.appointment_time}.' +# ) +# +# return redirect('appointments:appointment_detail', pk=appointment.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Schedule Appointment' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Appointments', 'url': reverse('appointments:appointment_list')}, +# {'name': 'Schedule Appointment', 'url': ''} +# ] +# context['available_slots'] = self.get_available_slots() +# return context +# +# def get_available_slots(self): +# """Get available appointment slots for the next 7 days""" +# slots = [] +# today = timezone.now().date() +# +# for i in range(7): +# date = today + timedelta(days=i) +# day_slots = self.get_slots_for_date(date) +# if day_slots: +# slots.append({ +# 'date': date, +# 'slots': day_slots +# }) +# +# return slots +# +# def get_slots_for_date(self, date): +# """Get available slots for a specific date""" +# # This would implement slot availability logic +# return [] +# +# +# class AppointmentConfirmationView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for appointment confirmation workflow +# """ +# model = AppointmentConfirmation +# form_class = AppointmentConfirmationForm +# template_name = 'appointments/appointment_confirmation.html' +# permission_required = 'appointments.can_confirm_appointments' +# flow_class = AppointmentConfirmationFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# return kwargs +# +# def form_valid(self, form): +# appointment = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# +# with transaction.atomic(): +# # Create confirmation record +# confirmation = form.save(commit=False) +# confirmation.appointment = appointment +# confirmation.confirmed_by = self.request.user +# confirmation.confirmed_at = timezone.now() +# confirmation.save() +# +# # Update appointment status +# if form.cleaned_data.get('reschedule_requested'): +# appointment.status = 'reschedule_requested' +# appointment.save() +# +# # Start rescheduling process +# messages.info( +# self.request, +# 'Patient requested reschedule. Please process the reschedule request.' +# ) +# return redirect('appointments:appointment_reschedule', pk=appointment.pk) +# else: +# appointment.status = 'confirmed' +# appointment.save() +# +# # Start confirmation workflow +# process = self.flow_class.start.run( +# appointment=appointment, +# confirmation=confirmation, +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Appointment confirmed for {appointment.patient.get_full_name()}.' +# ) +# +# return redirect('appointments:appointment_detail', pk=appointment.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# context['title'] = 'Confirm Appointment' +# return context +# +# +# class QueueManagementView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for queue management workflow +# """ +# model = Queue +# form_class = QueueManagementForm +# template_name = 'appointments/queue_management.html' +# permission_required = 'appointments.can_manage_queue' +# flow_class = QueueManagementFlow +# +# def form_valid(self, form): +# appointment = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# +# with transaction.atomic(): +# # Create or update queue entry +# queue_entry, created = Queue.objects.get_or_create( +# appointment=appointment, +# defaults={ +# 'tenant': self.request.user.tenant, +# 'patient': appointment.patient, +# 'provider': appointment.provider, +# 'department': appointment.department, +# 'created_by': self.request.user +# } +# ) +# +# # Update queue entry with form data +# for field in form.cleaned_data: +# if hasattr(queue_entry, field): +# setattr(queue_entry, field, form.cleaned_data[field]) +# +# queue_entry.save() +# +# # Start queue management workflow +# process = self.flow_class.start.run( +# queue_entry=queue_entry, +# appointment=appointment, +# notify_patient=form.cleaned_data.get('notify_patient', True), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Queue updated for {appointment.patient.get_full_name()}. ' +# f'Position: {queue_entry.position}, Wait time: {queue_entry.estimated_wait_time} minutes.' +# ) +# +# return redirect('appointments:queue_list') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# context['title'] = 'Manage Queue' +# context['current_queue'] = self.get_current_queue() +# return context +# +# def get_current_queue(self): +# """Get current queue status""" +# return Queue.objects.filter( +# tenant=self.request.user.tenant, +# status='waiting' +# ).order_by('priority', 'created_at') +# +# +# class TelemedicineSetupView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for telemedicine setup workflow +# """ +# model = TelemedicineSession +# form_class = TelemedicineSetupForm +# template_name = 'appointments/telemedicine_setup.html' +# permission_required = 'appointments.can_setup_telemedicine' +# flow_class = TelemedicineSetupFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# return kwargs +# +# def form_valid(self, form): +# appointment = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# +# with transaction.atomic(): +# # Create telemedicine session +# session = form.save(commit=False) +# session.appointment = appointment +# session.tenant = self.request.user.tenant +# session.created_by = self.request.user +# session.save() +# +# # Update appointment type +# appointment.appointment_type = 'telemedicine' +# appointment.save() +# +# # Start telemedicine setup workflow +# process = self.flow_class.start.run( +# session=session, +# appointment=appointment, +# test_connection=form.cleaned_data.get('test_connection', True), +# send_instructions=form.cleaned_data.get('send_instructions', True), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Telemedicine session setup completed for {appointment.patient.get_full_name()}. ' +# f'Meeting details have been sent to the patient.' +# ) +# +# return redirect('appointments:appointment_detail', pk=appointment.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['appointment_id']) +# context['title'] = 'Setup Telemedicine' +# return context +# +# +# class AppointmentRescheduleView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for appointment rescheduling +# """ +# form_class = AppointmentRescheduleForm +# template_name = 'appointments/appointment_reschedule.html' +# permission_required = 'appointments.can_reschedule_appointments' +# +# def get_success_url(self): +# return reverse('appointments:appointment_detail', kwargs={'pk': self.kwargs['pk']}) +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# kwargs['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# return kwargs +# +# def form_valid(self, form): +# appointment = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# +# with transaction.atomic(): +# # Store original appointment details +# original_date = appointment.appointment_date +# original_time = appointment.appointment_time +# original_provider = appointment.provider +# +# # Update appointment +# appointment.appointment_date = form.cleaned_data['new_date'] +# appointment.appointment_time = form.cleaned_data['new_time'] +# if form.cleaned_data.get('new_provider'): +# appointment.provider = form.cleaned_data['new_provider'] +# appointment.status = 'rescheduled' +# appointment.save() +# +# # Log reschedule +# self.log_reschedule(appointment, original_date, original_time, original_provider, form.cleaned_data) +# +# # Send notifications +# if form.cleaned_data.get('notify_patient'): +# self.send_reschedule_notification(appointment, form.cleaned_data) +# +# messages.success( +# self.request, +# f'Appointment rescheduled successfully. New date: {appointment.appointment_date}, ' +# f'New time: {appointment.appointment_time}.' +# ) +# +# return super().form_valid(form) +# +# def log_reschedule(self, appointment, original_date, original_time, original_provider, form_data): +# """Log reschedule details""" +# from core.models import AuditLogEntry +# AuditLogEntry.objects.create( +# tenant=appointment.tenant, +# user=self.request.user, +# event_type='APPOINTMENT_RESCHEDULE', +# action='UPDATE', +# object_type='Appointment', +# object_id=str(appointment.id), +# details={ +# 'original_date': original_date.isoformat(), +# 'original_time': original_time.isoformat(), +# 'original_provider': original_provider.get_full_name() if original_provider else None, +# 'new_date': form_data['new_date'].isoformat(), +# 'new_time': form_data['new_time'].isoformat(), +# 'new_provider': form_data['new_provider'].get_full_name() if form_data.get('new_provider') else None, +# 'reason': form_data['reschedule_reason'], +# 'notes': form_data.get('notes', '') +# }, +# ip_address=self.request.META.get('REMOTE_ADDR'), +# user_agent=self.request.META.get('HTTP_USER_AGENT', '') +# ) +# +# def send_reschedule_notification(self, appointment, form_data): +# """Send reschedule notification to patient""" +# if appointment.patient.email: +# send_mail( +# subject='Appointment Rescheduled', +# message=f'Your appointment has been rescheduled to {appointment.appointment_date} at {appointment.appointment_time}.', +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# context['title'] = 'Reschedule Appointment' +# return context +# +# +# class AppointmentCancellationView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for appointment cancellation +# """ +# form_class = AppointmentCancellationForm +# template_name = 'appointments/appointment_cancellation.html' +# permission_required = 'appointments.can_cancel_appointments' +# +# def get_success_url(self): +# return reverse('appointments:appointment_list') +# +# def form_valid(self, form): +# appointment = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# +# with transaction.atomic(): +# # Update appointment status +# appointment.status = 'cancelled' +# appointment.cancelled_at = timezone.now() +# appointment.cancelled_by = self.request.user +# appointment.cancellation_reason = form.cleaned_data['cancellation_reason'] +# appointment.cancellation_notes = form.cleaned_data.get('cancellation_notes', '') +# appointment.save() +# +# # Handle follow-up actions +# if form.cleaned_data.get('offer_reschedule'): +# self.offer_reschedule(appointment) +# +# if form.cleaned_data.get('notify_patient'): +# self.send_cancellation_notification(appointment, form.cleaned_data) +# +# if form.cleaned_data.get('refund_required'): +# self.process_refund(appointment) +# +# messages.success( +# self.request, +# f'Appointment cancelled for {appointment.patient.get_full_name()}.' +# ) +# +# return super().form_valid(form) +# +# def offer_reschedule(self, appointment): +# """Offer reschedule options to patient""" +# # This would implement reschedule offering logic +# pass +# +# def send_cancellation_notification(self, appointment, form_data): +# """Send cancellation notification to patient""" +# if appointment.patient.email: +# send_mail( +# subject='Appointment Cancelled', +# message=f'Your appointment on {appointment.appointment_date} has been cancelled. Reason: {form_data["cancellation_reason"]}', +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def process_refund(self, appointment): +# """Process refund if required""" +# # This would implement refund processing logic +# pass +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# context['title'] = 'Cancel Appointment' +# return context +# +# +# class AppointmentCheckInView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for appointment check-in +# """ +# form_class = AppointmentCheckInForm +# template_name = 'appointments/appointment_checkin.html' +# permission_required = 'appointments.can_checkin_patients' +# +# def get_success_url(self): +# return reverse('appointments:appointment_detail', kwargs={'pk': self.kwargs['pk']}) +# +# def form_valid(self, form): +# appointment = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# +# with transaction.atomic(): +# # Update appointment status +# appointment.status = 'checked_in' +# appointment.checked_in_at = timezone.now() +# appointment.checked_in_by = self.request.user +# appointment.arrival_time = form.cleaned_data['arrival_time'] +# appointment.save() +# +# # Create queue entry if needed +# if not hasattr(appointment, 'queue_entry'): +# Queue.objects.create( +# appointment=appointment, +# tenant=appointment.tenant, +# patient=appointment.patient, +# provider=appointment.provider, +# department=appointment.department, +# queue_type='check_in', +# priority='normal', +# status='waiting', +# created_by=self.request.user +# ) +# +# # Handle pre-visit tasks +# self.process_checkin_tasks(appointment, form.cleaned_data) +# +# messages.success( +# self.request, +# f'{appointment.patient.get_full_name()} checked in successfully.' +# ) +# +# return super().form_valid(form) +# +# def process_checkin_tasks(self, appointment, form_data): +# """Process check-in tasks""" +# tasks = [] +# +# if form_data.get('insurance_verified'): +# tasks.append('Insurance verified') +# if form_data.get('copay_collected'): +# tasks.append('Copay collected') +# if form_data.get('forms_completed'): +# tasks.append('Forms completed') +# if form_data.get('vitals_required'): +# tasks.append('Vitals required') +# +# # Log completed tasks +# if tasks: +# from core.models import AuditLogEntry +# AuditLogEntry.objects.create( +# tenant=appointment.tenant, +# user=self.request.user, +# event_type='APPOINTMENT_CHECKIN', +# action='UPDATE', +# object_type='Appointment', +# object_id=str(appointment.id), +# details={ +# 'completed_tasks': tasks, +# 'special_needs': form_data.get('special_needs', '') +# }, +# ip_address=self.request.META.get('REMOTE_ADDR'), +# user_agent=self.request.META.get('HTTP_USER_AGENT', '') +# ) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['appointment'] = get_object_or_404(Appointment, pk=self.kwargs['pk']) +# context['title'] = 'Check In Patient' +# return context +# +# +# class BulkAppointmentView(LoginRequiredMixin, PermissionRequiredMixin, FormView): +# """ +# View for bulk appointment operations +# """ +# form_class = BulkAppointmentForm +# template_name = 'appointments/bulk_appointment.html' +# permission_required = 'appointments.can_bulk_manage_appointments' +# +# def get_success_url(self): +# return reverse('appointments:appointment_list') +# +# def form_valid(self, form): +# appointment_ids = form.cleaned_data['appointment_ids'].split(',') +# appointments = Appointment.objects.filter( +# id__in=appointment_ids, +# tenant=self.request.user.tenant +# ) +# +# action = form.cleaned_data['action'] +# +# with transaction.atomic(): +# if action == 'confirm': +# self.bulk_confirm(appointments, form.cleaned_data) +# elif action == 'reschedule': +# self.bulk_reschedule(appointments, form.cleaned_data) +# elif action == 'cancel': +# self.bulk_cancel(appointments, form.cleaned_data) +# elif action == 'send_reminders': +# self.bulk_send_reminders(appointments, form.cleaned_data) +# +# messages.success( +# self.request, +# f'Bulk operation "{action}" completed for {appointments.count()} appointments.' +# ) +# +# return super().form_valid(form) +# +# def bulk_confirm(self, appointments, form_data): +# """Bulk confirm appointments""" +# for appointment in appointments: +# appointment.status = 'confirmed' +# appointment.save() +# +# if form_data.get('notify_patients'): +# self.send_confirmation_notification(appointment) +# +# def bulk_reschedule(self, appointments, form_data): +# """Bulk reschedule appointments""" +# new_date = form_data.get('bulk_date') +# if new_date: +# for appointment in appointments: +# appointment.appointment_date = new_date +# appointment.status = 'rescheduled' +# appointment.save() +# +# if form_data.get('notify_patients'): +# self.send_reschedule_notification(appointment, form_data) +# +# def bulk_cancel(self, appointments, form_data): +# """Bulk cancel appointments""" +# for appointment in appointments: +# appointment.status = 'cancelled' +# appointment.cancelled_at = timezone.now() +# appointment.cancelled_by = self.request.user +# appointment.cancellation_reason = 'bulk_cancellation' +# appointment.cancellation_notes = form_data.get('bulk_reason', '') +# appointment.save() +# +# if form_data.get('notify_patients'): +# self.send_cancellation_notification(appointment, form_data) +# +# def bulk_send_reminders(self, appointments, form_data): +# """Bulk send reminders""" +# for appointment in appointments: +# if form_data.get('notify_patients'): +# self.send_reminder_notification(appointment) +# +# def send_confirmation_notification(self, appointment): +# """Send confirmation notification""" +# if appointment.patient.email: +# send_mail( +# subject='Appointment Confirmed', +# message=f'Your appointment on {appointment.appointment_date} at {appointment.appointment_time} has been confirmed.', +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def send_reminder_notification(self, appointment): +# """Send reminder notification""" +# if appointment.patient.email: +# send_mail( +# subject='Appointment Reminder', +# message=f'Reminder: You have an appointment on {appointment.appointment_date} at {appointment.appointment_time}.', +# from_email=settings.DEFAULT_FROM_EMAIL, +# recipient_list=[appointment.patient.email], +# fail_silently=True +# ) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Bulk Appointment Operations' +# return context +# +# +# class AppointmentListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for listing appointments +# """ +# model = Appointment +# template_name = 'appointments/appointment_list.html' +# context_object_name = 'appointments' +# permission_required = 'appointments.view_appointment' +# paginate_by = 25 +# +# def get_queryset(self): +# queryset = Appointment.objects.filter(tenant=self.request.user.tenant) +# +# # Apply filters +# search = self.request.GET.get('search') +# if search: +# queryset = queryset.filter( +# Q(patient__first_name__icontains=search) | +# Q(patient__last_name__icontains=search) | +# Q(provider__first_name__icontains=search) | +# Q(provider__last_name__icontains=search) | +# Q(reason__icontains=search) +# ) +# +# status = self.request.GET.get('status') +# if status: +# queryset = queryset.filter(status=status) +# +# date_from = self.request.GET.get('date_from') +# if date_from: +# queryset = queryset.filter(appointment_date__gte=date_from) +# +# date_to = self.request.GET.get('date_to') +# if date_to: +# queryset = queryset.filter(appointment_date__lte=date_to) +# +# provider = self.request.GET.get('provider') +# if provider: +# queryset = queryset.filter(provider_id=provider) +# +# return queryset.order_by('appointment_date', 'appointment_time') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Appointments' +# context['providers'] = self.get_providers() +# context['search'] = self.request.GET.get('search', '') +# context['selected_status'] = self.request.GET.get('status', '') +# context['selected_provider'] = self.request.GET.get('provider', '') +# context['date_from'] = self.request.GET.get('date_from', '') +# context['date_to'] = self.request.GET.get('date_to', '') +# return context +# +# def get_providers(self): +# """Get providers for filter""" +# from django.contrib.auth.models import User +# return User.objects.filter( +# tenant=self.request.user.tenant, +# groups__name__in=['Doctors', 'Nurses', 'Specialists'] +# ).distinct() +# +# +# class AppointmentDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# """ +# View for appointment details +# """ +# model = Appointment +# template_name = 'appointments/appointment_detail.html' +# context_object_name = 'appointment' +# permission_required = 'appointments.view_appointment' +# +# def get_queryset(self): +# return Appointment.objects.filter(tenant=self.request.user.tenant) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# appointment = self.object +# context['title'] = f'Appointment - {appointment.patient.get_full_name()}' +# context['confirmation'] = getattr(appointment, 'confirmation', None) +# context['queue_entry'] = getattr(appointment, 'queue_entry', None) +# context['telemedicine_session'] = getattr(appointment, 'telemedicine_session', None) +# context['can_edit'] = self.request.user.has_perm('appointments.change_appointment') +# context['can_cancel'] = self.request.user.has_perm('appointments.can_cancel_appointments') +# context['can_reschedule'] = self.request.user.has_perm('appointments.can_reschedule_appointments') +# return context +# +# +# class QueueListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for listing queue entries +# """ +# model = Queue +# template_name = 'appointments/queue_list.html' +# context_object_name = 'queue_entries' +# permission_required = 'appointments.view_queue' +# +# def get_queryset(self): +# queryset = Queue.objects.filter(tenant=self.request.user.tenant) +# +# # Apply filters +# status = self.request.GET.get('status', 'waiting') +# if status: +# queryset = queryset.filter(status=status) +# +# department = self.request.GET.get('department') +# if department: +# queryset = queryset.filter(department_id=department) +# +# return queryset.order_by('priority', 'created_at') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Patient Queue' +# context['departments'] = self.get_departments() +# context['selected_status'] = self.request.GET.get('status', 'waiting') +# context['selected_department'] = self.request.GET.get('department', '') +# context['queue_stats'] = self.get_queue_stats() +# return context +# +# def get_departments(self): +# """Get departments for filter""" +# from core.models import Department +# return Department.objects.filter(tenant=self.request.user.tenant) +# +# def get_queue_stats(self): +# """Get queue statistics""" +# return { +# 'total_waiting': Queue.objects.filter( +# tenant=self.request.user.tenant, +# status='waiting' +# ).count(), +# 'average_wait_time': 25, # Would be calculated +# 'longest_wait': 45 # Would be calculated +# } +# +# +# # AJAX Views +# @login_required +# @permission_required('appointments.view_appointment') +# def appointment_availability_ajax(request): +# """AJAX view to check appointment availability""" +# date = request.GET.get('date') +# provider_id = request.GET.get('provider_id') +# +# if not date or not provider_id: +# return JsonResponse({'success': False, 'message': 'Missing parameters'}) +# +# try: +# from django.contrib.auth.models import User +# provider = User.objects.get(id=provider_id, tenant=request.user.tenant) +# appointment_date = datetime.strptime(date, '%Y-%m-%d').date() +# +# # Get existing appointments for the date +# existing_appointments = Appointment.objects.filter( +# provider=provider, +# appointment_date=appointment_date, +# status__in=['scheduled', 'confirmed', 'in_progress'] +# ) +# +# # Generate available slots +# available_slots = generate_available_slots(appointment_date, existing_appointments) +# +# return JsonResponse({ +# 'success': True, +# 'slots': available_slots +# }) +# except Exception as e: +# return JsonResponse({'success': False, 'message': str(e)}) +# +# +# @login_required +# @permission_required('appointments.view_patient') +# def patient_search_ajax(request): +# """AJAX view for patient search""" +# query = request.GET.get('q', '') +# if len(query) < 2: +# return JsonResponse({'patients': []}) +# +# patients = Patient.objects.filter( +# tenant=request.user.tenant +# ).filter( +# Q(first_name__icontains=query) | +# Q(last_name__icontains=query) | +# Q(patient_id__icontains=query) | +# Q(phone_number__icontains=query) +# )[:10] +# +# patient_data = [ +# { +# 'id': patient.id, +# 'name': patient.get_full_name(), +# 'patient_id': patient.patient_id, +# 'phone': patient.phone_number, +# 'email': patient.email +# } +# for patient in patients +# ] +# +# return JsonResponse({'patients': patient_data}) +# +# +# @login_required +# @permission_required('appointments.can_manage_queue') +# def update_queue_position_ajax(request): +# """AJAX view to update queue position""" +# if request.method == 'POST': +# try: +# data = json.loads(request.body) +# queue_id = data.get('queue_id') +# new_position = data.get('new_position') +# +# queue_entry = Queue.objects.get( +# id=queue_id, +# tenant=request.user.tenant +# ) +# +# queue_entry.position = new_position +# queue_entry.save() +# +# return JsonResponse({ +# 'success': True, +# 'message': 'Queue position updated successfully.' +# }) +# except Queue.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'Queue entry not found.' +# }) +# except Exception as e: +# return JsonResponse({ +# 'success': False, +# 'message': str(e) +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# def generate_available_slots(date, existing_appointments): +# """Generate available appointment slots for a date""" +# slots = [] +# start_time = datetime.strptime('09:00', '%H:%M').time() +# end_time = datetime.strptime('17:00', '%H:%M').time() +# slot_duration = 30 # minutes +# +# current_time = datetime.combine(date, start_time) +# end_datetime = datetime.combine(date, end_time) +# +# while current_time < end_datetime: +# slot_time = current_time.time() +# +# # Check if slot is available +# is_available = True +# for appointment in existing_appointments: +# appointment_start = datetime.combine(date, appointment.appointment_time) +# appointment_end = appointment_start + timedelta(minutes=appointment.duration) +# +# slot_start = current_time +# slot_end = current_time + timedelta(minutes=slot_duration) +# +# if slot_start < appointment_end and slot_end > appointment_start: +# is_available = False +# break +# +# if is_available: +# slots.append({ +# 'time': slot_time.strftime('%H:%M'), +# 'available': True +# }) +# +# current_time += timedelta(minutes=slot_duration) +# +# return slots +# diff --git a/billing/__pycache__/flows.cpython-312.pyc b/billing/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0341c050d6100e735d45bcbcf9f7f53576f20d7 GIT binary patch literal 177 zcmX@j%ge<81bQ<2GBg_)7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@SR{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc yqMwwRlara3uAi2ZUtX+NP>-~dl?Ct delta 25 fcmeyrlkxvfM!wU$yj%=G@K|<2#?G{jd>>-~edr03 diff --git a/billing/__pycache__/urls.cpython-312.pyc b/billing/__pycache__/urls.cpython-312.pyc index 1100ee350baa9516f4edda24b853f3078597b03e..dd846f07336c3001f2650c9ba9cd9ff5c634abaa 100644 GIT binary patch delta 1177 zcmZ9LPlysx9LIGWx7Bf6T^(KjySi>_v(C2LZfcwM2csaC3M#0>Fxwk!LT#CGp}Z`e z>J-Sk?8!O??LpXc*9am|5G1eN3YMT#r+RO67AtwFbKV80RAlKT5=Lf+LIotWd#HkWiNpo-(#KI|vb67`~+f6%ZlhD2lI| zF=GNTf{P>L~@psc$Js0aP7`V zaNh7N;*}25!-Quu)q5+DfyGzmeVgcMLBQ3y>!7$_kFvj#z@h@hzx1*(%n$irAEVrc5bC)+WJ zTS}mbN&L6e%=y(v$m`#3pW#6_r7gkOdl`26Vrm9GZmuwii4 zo%!T>tm48J2+?%ODEUfDO{>WcZ1Xp(v%g|e;?5|^tW04?;5CRdxlP7Wqa7%!gk|08A@*8d|-CIH+ z&G9G(-V%U|#TTb07A0pCDS~t;O}61F=CTAb8G*RCXYx*-;>{tvrx+DwXRuzEFt{jT vu%Z46i~CI$jtiVJGg7b1nOu}J*&Yrbg}}bD(wrHKndq diff --git a/billing/__pycache__/views.cpython-312.pyc b/billing/__pycache__/views.cpython-312.pyc index de825d6addc7d09726e515e30fdb75937e502233..f9e5bcdf5f067814fab8d02ae801867a851fd8d4 100644 GIT binary patch delta 8763 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 delta 3346 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 diff --git a/billing/flows.py b/billing/flows.py new file mode 100644 index 00000000..3088bc61 --- /dev/null +++ b/billing/flows.py @@ -0,0 +1,1022 @@ +# """ +# Viewflow workflows for billing app. +# Provides medical billing, insurance claims, and payment processing 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 MedicalBill, InsuranceClaim, Payment, ClaimStatusUpdate +# from .views import ( +# BillGenerationView, ChargeReviewView, InsuranceVerificationView, +# ClaimPreparationView, ClaimSubmissionView, ClaimTrackingView, +# PaymentProcessingView, PaymentReconciliationView, DenialManagementView, +# AppealPreparationView, CollectionsView +# ) +# +# +# class MedicalBillingProcess(Process): +# """ +# Viewflow process model for medical billing +# """ +# medical_bill = ModelField(MedicalBill, help_text='Associated medical bill') +# +# # Process status tracking +# charges_captured = models.BooleanField(default=False) +# charges_reviewed = models.BooleanField(default=False) +# insurance_verified = models.BooleanField(default=False) +# bill_generated = models.BooleanField(default=False) +# claims_submitted = models.BooleanField(default=False) +# payments_processed = models.BooleanField(default=False) +# account_reconciled = models.BooleanField(default=False) +# billing_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Medical Billing Process' +# verbose_name_plural = 'Medical Billing Processes' +# +# +# class MedicalBillingFlow(Flow): +# """ +# Medical Billing Workflow +# +# This flow manages the complete revenue cycle from charge capture +# through payment processing and account reconciliation. +# """ +# +# process_class = MedicalBillingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_billing) +# .Next(this.capture_charges) +# ) +# +# capture_charges = ( +# flow_func(this.collect_service_charges) +# .Next(this.review_charges) +# ) +# +# review_charges = ( +# flow_view(ChargeReviewView) +# .Permission('billing.can_review_charges') +# .Next(this.verify_insurance) +# ) +# +# verify_insurance = ( +# flow_view(InsuranceVerificationView) +# .Permission('billing.can_verify_insurance') +# .Next(this.generate_bill) +# ) +# +# generate_bill = ( +# flow_view(BillGenerationView) +# .Permission('billing.can_generate_bills') +# .Next(this.parallel_claim_processing) +# ) +# +# parallel_claim_processing = ( +# flow_func(this.start_parallel_processing) +# .Next(this.submit_primary_claim) +# .Next(this.submit_secondary_claim) +# .Next(this.patient_billing) +# ) +# +# submit_primary_claim = ( +# flow_view(PrimaryClaimSubmissionView) +# .Permission('billing.can_submit_claims') +# .Next(this.join_claim_processing) +# ) +# +# submit_secondary_claim = ( +# flow_view(SecondaryClaimSubmissionView) +# .Permission('billing.can_submit_claims') +# .Next(this.join_claim_processing) +# ) +# +# patient_billing = ( +# flow_view(PatientBillingView) +# .Permission('billing.can_bill_patients') +# .Next(this.join_claim_processing) +# ) +# +# join_claim_processing = ( +# flow_func(this.join_parallel_processing) +# .Next(this.process_payments) +# ) +# +# process_payments = ( +# flow_view(PaymentProcessingView) +# .Permission('billing.can_process_payments') +# .Next(this.reconcile_account) +# ) +# +# reconcile_account = ( +# flow_view(PaymentReconciliationView) +# .Permission('billing.can_reconcile_accounts') +# .Next(this.finalize_billing) +# ) +# +# finalize_billing = ( +# flow_func(this.complete_billing) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_billing) +# +# # Flow functions +# def start_billing(self, activation): +# """Initialize the billing process""" +# process = activation.process +# bill = process.medical_bill +# +# # Update bill status +# bill.status = 'PROCESSING' +# bill.save() +# +# # Send notification to billing staff +# self.notify_billing_staff(bill) +# +# # Check for priority billing +# if bill.bill_type in ['EMERGENCY', 'SURGERY']: +# self.notify_priority_billing(bill) +# +# def collect_service_charges(self, activation): +# """Collect charges from various service departments""" +# process = activation.process +# bill = process.medical_bill +# +# # Collect charges from different departments +# charges = self.gather_service_charges(bill) +# +# if charges: +# # Update bill with collected charges +# self.update_bill_charges(bill, charges) +# +# process.charges_captured = True +# process.save() +# +# def start_parallel_processing(self, activation): +# """Start parallel claim and billing processing""" +# process = activation.process +# +# # Create parallel processing tasks +# self.create_claim_tasks(process.medical_bill) +# +# def join_parallel_processing(self, activation): +# """Wait for all claim processing to complete""" +# process = activation.process +# +# # Check if all processing is completed +# if self.all_claims_processed(process.medical_bill): +# # Proceed to payment processing +# self.notify_claims_completed(process.medical_bill) +# +# def complete_billing(self, activation): +# """Finalize the billing process""" +# process = activation.process +# bill = process.medical_bill +# +# # Update bill status based on payment status +# if bill.balance_due <= 0: +# bill.status = 'PAID' +# elif bill.total_payments > 0: +# bill.status = 'PARTIALLY_PAID' +# else: +# bill.status = 'OUTSTANDING' +# +# bill.save() +# +# # Mark process as completed +# process.billing_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_billing_completion(bill) +# +# # Update revenue metrics +# self.update_revenue_metrics(bill) +# +# def end_billing(self, activation): +# """End the billing workflow""" +# process = activation.process +# +# # Generate billing summary report +# self.generate_billing_summary(process.medical_bill) +# +# # Helper methods +# def notify_billing_staff(self, bill): +# """Notify billing staff of new bill""" +# from django.contrib.auth.models import Group +# +# billing_staff = User.objects.filter( +# groups__name='Billing Staff' +# ) +# +# for staff in billing_staff: +# send_mail( +# subject=f'New Medical Bill: {bill.bill_number}', +# message=f'New medical bill for {bill.patient.get_full_name()} requires processing.', +# from_email='billing@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_priority_billing(self, bill): +# """Notify of priority billing""" +# billing_managers = User.objects.filter( +# groups__name='Billing Managers' +# ) +# +# for manager in billing_managers: +# send_mail( +# subject=f'PRIORITY Billing: {bill.bill_number}', +# message=f'{bill.get_bill_type_display()} bill requires priority processing.', +# from_email='billing@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def gather_service_charges(self, bill): +# """Gather charges from service departments""" +# # This would collect charges from various departments +# return [] +# +# def update_bill_charges(self, bill, charges): +# """Update bill with collected charges""" +# # This would update the bill with charges +# pass +# +# def create_claim_tasks(self, bill): +# """Create claim processing tasks""" +# # This would create tasks for claim processing +# pass +# +# def all_claims_processed(self, bill): +# """Check if all claims are processed""" +# # This would check claim processing status +# return True +# +# def notify_claims_completed(self, bill): +# """Notify that claims processing is completed""" +# billing_staff = User.objects.filter( +# groups__name='Billing Staff' +# ) +# +# for staff in billing_staff: +# send_mail( +# subject=f'Claims Processed: {bill.bill_number}', +# message=f'All claims have been processed for {bill.patient.get_full_name()}.', +# from_email='billing@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_billing_completion(self, bill): +# """Notify billing completion""" +# # Notify patient if email available +# if bill.patient.email: +# send_mail( +# subject='Medical Bill Processed', +# message=f'Your medical bill {bill.bill_number} has been processed.', +# from_email='billing@hospital.com', +# recipient_list=[bill.patient.email], +# fail_silently=True +# ) +# +# def update_revenue_metrics(self, bill): +# """Update revenue cycle metrics""" +# # This would update revenue metrics +# pass +# +# def generate_billing_summary(self, bill): +# """Generate billing summary report""" +# # This would generate a comprehensive billing report +# pass +# +# +# class InsuranceClaimProcess(Process): +# """ +# Viewflow process model for insurance claims +# """ +# insurance_claim = ModelField(InsuranceClaim, help_text='Associated insurance claim') +# +# # Process status tracking +# claim_prepared = models.BooleanField(default=False) +# eligibility_verified = models.BooleanField(default=False) +# claim_submitted = models.BooleanField(default=False) +# claim_tracked = models.BooleanField(default=False) +# response_received = models.BooleanField(default=False) +# payment_posted = models.BooleanField(default=False) +# denials_managed = models.BooleanField(default=False) +# claim_finalized = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Insurance Claim Process' +# verbose_name_plural = 'Insurance Claim Processes' +# +# +# class InsuranceClaimFlow(Flow): +# """ +# Insurance Claim Processing Workflow +# +# This flow manages insurance claim processing from preparation +# through payment posting and denial management. +# """ +# +# process_class = InsuranceClaimProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_claim) +# .Next(this.prepare_claim) +# ) +# +# prepare_claim = ( +# flow_view(ClaimPreparationView) +# .Permission('billing.can_prepare_claims') +# .Next(this.verify_eligibility) +# ) +# +# verify_eligibility = ( +# flow_view(EligibilityVerificationView) +# .Permission('billing.can_verify_eligibility') +# .Next(this.submit_claim) +# ) +# +# submit_claim = ( +# flow_view(ClaimSubmissionView) +# .Permission('billing.can_submit_claims') +# .Next(this.track_claim) +# ) +# +# track_claim = ( +# flow_view(ClaimTrackingView) +# .Permission('billing.can_track_claims') +# .Next(this.receive_response) +# ) +# +# receive_response = ( +# flow_func(this.process_claim_response) +# .Next(this.post_payment) +# ) +# +# post_payment = ( +# flow_view(PaymentPostingView) +# .Permission('billing.can_post_payments') +# .Next(this.manage_denials) +# ) +# +# manage_denials = ( +# flow_view(DenialManagementView) +# .Permission('billing.can_manage_denials') +# .Next(this.finalize_claim) +# ) +# +# finalize_claim = ( +# flow_func(this.complete_claim) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_claim) +# +# # Flow functions +# def start_claim(self, activation): +# """Initialize the claim process""" +# process = activation.process +# claim = process.insurance_claim +# +# # Update claim status +# claim.status = 'PREPARING' +# claim.save() +# +# # Send notification to claims staff +# self.notify_claims_staff(claim) +# +# def process_claim_response(self, activation): +# """Process insurance claim response""" +# process = activation.process +# claim = process.insurance_claim +# +# # Check for claim response +# response = self.check_claim_response(claim) +# +# if response: +# # Update claim with response +# self.update_claim_response(claim, response) +# +# process.response_received = True +# process.save() +# +# # Handle different response types +# if response.get('status') == 'DENIED': +# self.handle_claim_denial(claim, response) +# elif response.get('status') == 'PAID': +# self.handle_claim_payment(claim, response) +# +# def complete_claim(self, activation): +# """Finalize the claim process""" +# process = activation.process +# claim = process.insurance_claim +# +# # Update claim status based on final outcome +# if claim.paid_amount >= claim.billed_amount: +# claim.status = 'PAID' +# elif claim.paid_amount > 0: +# claim.status = 'PARTIALLY_PAID' +# elif claim.denial_reason: +# claim.status = 'DENIED' +# else: +# claim.status = 'PENDING' +# +# claim.save() +# +# # Mark process as completed +# process.claim_finalized = True +# process.save() +# +# # Send completion notifications +# self.notify_claim_completion(claim) +# +# def end_claim(self, activation): +# """End the claim workflow""" +# process = activation.process +# +# # Generate claim summary report +# self.generate_claim_summary(process.insurance_claim) +# +# # Helper methods +# def notify_claims_staff(self, claim): +# """Notify claims staff""" +# claims_staff = User.objects.filter( +# groups__name='Claims Staff' +# ) +# +# for staff in claims_staff: +# send_mail( +# subject=f'New Insurance Claim: {claim.claim_number}', +# message=f'New insurance claim for {claim.patient.get_full_name()} requires processing.', +# from_email='claims@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def check_claim_response(self, claim): +# """Check for claim response from insurance""" +# # This would check for insurance responses +# return None +# +# def update_claim_response(self, claim, response): +# """Update claim with insurance response""" +# # This would update the claim with response data +# pass +# +# def handle_claim_denial(self, claim, response): +# """Handle claim denial""" +# # Notify claims staff of denial +# claims_staff = User.objects.filter( +# groups__name='Claims Staff' +# ) +# +# for staff in claims_staff: +# send_mail( +# subject=f'Claim Denied: {claim.claim_number}', +# message=f'Insurance claim has been denied. Reason: {response.get("denial_reason", "Unknown")}', +# from_email='claims@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def handle_claim_payment(self, claim, response): +# """Handle claim payment""" +# # This would process claim payment +# pass +# +# def notify_claim_completion(self, claim): +# """Notify claim completion""" +# # This would notify relevant parties +# pass +# +# def generate_claim_summary(self, claim): +# """Generate claim summary report""" +# # This would generate claim summary +# pass +# +# +# class PaymentProcessingProcess(Process): +# """ +# Viewflow process model for payment processing +# """ +# payment = ModelField(Payment, help_text='Associated payment') +# +# # Process status tracking +# payment_received = models.BooleanField(default=False) +# payment_verified = models.BooleanField(default=False) +# payment_processed = models.BooleanField(default=False) +# payment_deposited = models.BooleanField(default=False) +# account_updated = models.BooleanField(default=False) +# receipt_generated = models.BooleanField(default=False) +# payment_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Payment Processing Process' +# verbose_name_plural = 'Payment Processing Processes' +# +# +# class PaymentProcessingFlow(Flow): +# """ +# Payment Processing Workflow +# +# This flow manages payment processing from receipt through +# deposit and account reconciliation. +# """ +# +# process_class = PaymentProcessingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_payment) +# .Next(this.receive_payment) +# ) +# +# receive_payment = ( +# flow_view(PaymentReceiptView) +# .Permission('billing.can_receive_payments') +# .Next(this.verify_payment) +# ) +# +# verify_payment = ( +# flow_view(PaymentVerificationView) +# .Permission('billing.can_verify_payments') +# .Next(this.process_payment) +# ) +# +# process_payment = ( +# flow_view(PaymentProcessingView) +# .Permission('billing.can_process_payments') +# .Next(this.deposit_payment) +# ) +# +# deposit_payment = ( +# flow_view(PaymentDepositView) +# .Permission('billing.can_deposit_payments') +# .Next(this.update_account) +# ) +# +# update_account = ( +# flow_func(this.update_patient_account) +# .Next(this.generate_receipt) +# ) +# +# generate_receipt = ( +# flow_view(ReceiptGenerationView) +# .Permission('billing.can_generate_receipts') +# .Next(this.finalize_payment) +# ) +# +# finalize_payment = ( +# flow_func(this.complete_payment) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_payment) +# +# # Flow functions +# def start_payment(self, activation): +# """Initialize the payment process""" +# process = activation.process +# payment = process.payment +# +# # Update payment status +# payment.status = 'PENDING' +# payment.save() +# +# # Send notification to billing staff +# self.notify_payment_received(payment) +# +# def update_patient_account(self, activation): +# """Update patient account with payment""" +# process = activation.process +# payment = process.payment +# +# # Update medical bill balance +# bill = payment.medical_bill +# bill.total_payments += payment.payment_amount +# bill.balance_due = bill.total_amount - bill.total_payments +# bill.save() +# +# process.account_updated = True +# process.save() +# +# # Check if bill is fully paid +# if bill.balance_due <= 0: +# self.notify_account_paid_in_full(bill) +# +# def complete_payment(self, activation): +# """Finalize the payment process""" +# process = activation.process +# payment = process.payment +# +# # Update payment status +# payment.status = 'PROCESSED' +# payment.save() +# +# # Mark process as completed +# process.payment_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_payment_completion(payment) +# +# def end_payment(self, activation): +# """End the payment workflow""" +# process = activation.process +# +# # Generate payment summary report +# self.generate_payment_summary(process.payment) +# +# # Helper methods +# def notify_payment_received(self, payment): +# """Notify billing staff of payment received""" +# billing_staff = User.objects.filter( +# groups__name='Billing Staff' +# ) +# +# for staff in billing_staff: +# send_mail( +# subject=f'Payment Received: {payment.payment_number}', +# message=f'Payment of ${payment.payment_amount} received for {payment.patient.get_full_name()}.', +# from_email='billing@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_account_paid_in_full(self, bill): +# """Notify that account is paid in full""" +# # Notify patient +# if bill.patient.email: +# send_mail( +# subject='Account Paid in Full', +# message=f'Your account for bill {bill.bill_number} has been paid in full.', +# from_email='billing@hospital.com', +# recipient_list=[bill.patient.email], +# fail_silently=True +# ) +# +# def notify_payment_completion(self, payment): +# """Notify payment completion""" +# # This would notify relevant parties +# pass +# +# def generate_payment_summary(self, payment): +# """Generate payment summary report""" +# # This would generate payment summary +# pass +# +# +# class DenialManagementProcess(Process): +# """ +# Viewflow process model for denial management +# """ +# insurance_claim = ModelField(InsuranceClaim, help_text='Associated denied claim') +# +# # Process status tracking +# denial_analyzed = models.BooleanField(default=False) +# appeal_prepared = models.BooleanField(default=False) +# appeal_submitted = models.BooleanField(default=False) +# appeal_tracked = models.BooleanField(default=False) +# appeal_resolved = models.BooleanField(default=False) +# account_adjusted = models.BooleanField(default=False) +# denial_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Denial Management Process' +# verbose_name_plural = 'Denial Management Processes' +# +# +# class DenialManagementFlow(Flow): +# """ +# Denial Management Workflow +# +# This flow manages insurance claim denials including analysis, +# appeal preparation, submission, and resolution. +# """ +# +# process_class = DenialManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_denial_management) +# .Next(this.analyze_denial) +# ) +# +# analyze_denial = ( +# flow_view(DenialAnalysisView) +# .Permission('billing.can_analyze_denials') +# .Next(this.prepare_appeal) +# ) +# +# prepare_appeal = ( +# flow_view(AppealPreparationView) +# .Permission('billing.can_prepare_appeals') +# .Next(this.submit_appeal) +# ) +# +# submit_appeal = ( +# flow_view(AppealSubmissionView) +# .Permission('billing.can_submit_appeals') +# .Next(this.track_appeal) +# ) +# +# track_appeal = ( +# flow_view(AppealTrackingView) +# .Permission('billing.can_track_appeals') +# .Next(this.resolve_appeal) +# ) +# +# resolve_appeal = ( +# flow_func(this.process_appeal_resolution) +# .Next(this.adjust_account) +# ) +# +# adjust_account = ( +# flow_view(AccountAdjustmentView) +# .Permission('billing.can_adjust_accounts') +# .Next(this.finalize_denial) +# ) +# +# finalize_denial = ( +# flow_func(this.complete_denial_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_denial_management) +# +# # Flow functions +# def start_denial_management(self, activation): +# """Initialize the denial management process""" +# process = activation.process +# claim = process.insurance_claim +# +# # Send notification to denial management staff +# self.notify_denial_staff(claim) +# +# def process_appeal_resolution(self, activation): +# """Process appeal resolution""" +# process = activation.process +# claim = process.insurance_claim +# +# # Check appeal status +# appeal_result = self.check_appeal_status(claim) +# +# if appeal_result: +# # Update claim with appeal result +# self.update_appeal_result(claim, appeal_result) +# +# process.appeal_resolved = True +# process.save() +# +# def complete_denial_management(self, activation): +# """Finalize the denial management process""" +# process = activation.process +# claim = process.insurance_claim +# +# # Mark process as completed +# process.denial_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_denial_completion(claim) +# +# def end_denial_management(self, activation): +# """End the denial management workflow""" +# process = activation.process +# +# # Generate denial management summary +# self.generate_denial_summary(process.insurance_claim) +# +# # Helper methods +# def notify_denial_staff(self, claim): +# """Notify denial management staff""" +# denial_staff = User.objects.filter( +# groups__name='Denial Management' +# ) +# +# for staff in denial_staff: +# send_mail( +# subject=f'Claim Denial: {claim.claim_number}', +# message=f'Insurance claim has been denied and requires review.', +# from_email='denials@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def check_appeal_status(self, claim): +# """Check appeal status""" +# # This would check appeal status +# return None +# +# def update_appeal_result(self, claim, result): +# """Update claim with appeal result""" +# # This would update the claim with appeal result +# pass +# +# def notify_denial_completion(self, claim): +# """Notify denial management completion""" +# # This would notify relevant parties +# pass +# +# def generate_denial_summary(self, claim): +# """Generate denial management summary""" +# # This would generate denial summary +# pass +# +# +# class CollectionsProcess(Process): +# """ +# Viewflow process model for collections +# """ +# medical_bill = ModelField(MedicalBill, help_text='Associated medical bill') +# +# # Process status tracking +# account_reviewed = models.BooleanField(default=False) +# patient_contacted = models.BooleanField(default=False) +# payment_plan_offered = models.BooleanField(default=False) +# collection_actions_taken = models.BooleanField(default=False) +# external_agency_assigned = models.BooleanField(default=False) +# collections_resolved = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Collections Process' +# verbose_name_plural = 'Collections Processes' +# +# +# class CollectionsFlow(Flow): +# """ +# Collections Workflow +# +# This flow manages collections activities for overdue accounts +# including patient contact, payment plans, and external collections. +# """ +# +# process_class = CollectionsProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_collections) +# .Next(this.review_account) +# ) +# +# review_account = ( +# flow_view(AccountReviewView) +# .Permission('billing.can_review_collections') +# .Next(this.contact_patient) +# ) +# +# contact_patient = ( +# flow_view(PatientContactView) +# .Permission('billing.can_contact_patients') +# .Next(this.offer_payment_plan) +# ) +# +# offer_payment_plan = ( +# flow_view(PaymentPlanView) +# .Permission('billing.can_offer_payment_plans') +# .Next(this.collection_actions) +# ) +# +# collection_actions = ( +# flow_view(CollectionActionsView) +# .Permission('billing.can_take_collection_actions') +# .Next(this.external_collections) +# ) +# +# external_collections = ( +# flow_view(ExternalCollectionsView) +# .Permission('billing.can_assign_external_collections') +# .Next(this.resolve_collections) +# ) +# +# resolve_collections = ( +# flow_func(this.complete_collections) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_collections) +# +# # Flow functions +# def start_collections(self, activation): +# """Initialize the collections process""" +# process = activation.process +# bill = process.medical_bill +# +# # Send notification to collections staff +# self.notify_collections_staff(bill) +# +# def complete_collections(self, activation): +# """Finalize the collections process""" +# process = activation.process +# bill = process.medical_bill +# +# # Mark process as completed +# process.collections_resolved = True +# process.save() +# +# # Send completion notifications +# self.notify_collections_completion(bill) +# +# def end_collections(self, activation): +# """End the collections workflow""" +# process = activation.process +# +# # Generate collections summary +# self.generate_collections_summary(process.medical_bill) +# +# # Helper methods +# def notify_collections_staff(self, bill): +# """Notify collections staff""" +# collections_staff = User.objects.filter( +# groups__name='Collections Staff' +# ) +# +# for staff in collections_staff: +# send_mail( +# subject=f'Collections Account: {bill.bill_number}', +# message=f'Account for {bill.patient.get_full_name()} requires collections action.', +# from_email='collections@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_collections_completion(self, bill): +# """Notify collections completion""" +# # This would notify relevant parties +# pass +# +# def generate_collections_summary(self, bill): +# """Generate collections summary""" +# # This would generate collections summary +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_generate_bills(): +# """Background task to automatically generate bills""" +# try: +# # This would generate bills for completed services +# return True +# except Exception: +# return False +# +# +# @celery.job +# def monitor_claim_status(): +# """Background task to monitor insurance claim status""" +# try: +# # This would check claim status with insurance companies +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_billing_reports(): +# """Background task to generate billing reports""" +# try: +# # This would generate daily billing reports +# return True +# except Exception: +# return False +# +# +# @celery.job +# def auto_post_insurance_payments(): +# """Background task to automatically post insurance payments""" +# try: +# # This would post insurance payments from EDI files +# return True +# except Exception: +# return False +# +# +# @celery.job +# def identify_collection_accounts(): +# """Background task to identify accounts for collections""" +# try: +# # This would identify overdue accounts +# return True +# except Exception: +# return False +# diff --git a/billing/forms.py b/billing/forms.py index 30aa60b9..44b2bd66 100644 --- a/billing/forms.py +++ b/billing/forms.py @@ -786,3 +786,790 @@ class PaymentSearchForm(forms.Form): }) ) + +# from django import forms +# from django.core.exceptions import ValidationError +# from django.utils import timezone +# from django.contrib.auth.models import User +# from crispy_forms.helper import FormHelper +# from crispy_forms.layout import Layout, Fieldset, Submit, Row, Column, HTML, Div +# from crispy_forms.bootstrap import FormActions +# from decimal import Decimal +# import json +# +# from .models import ( +# Bill, BillItem, InsuranceClaim, Payment, PaymentMethod, +# InsuranceProvider, ClaimDenial, PaymentPlan +# ) +# from patients.models import Patient +# +# +# class MedicalBillingForm(forms.ModelForm): +# """ +# Form for medical billing creation +# """ +# patient_search = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={ +# 'class': 'form-control', +# 'placeholder': 'Search patient by name, ID, or insurance...', +# 'data-toggle': 'patient-search' +# }) +# ) +# insurance_verification = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# auto_submit_primary = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# auto_submit_secondary = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# generate_patient_statement = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = Bill +# fields = [ +# 'patient', 'encounter', 'bill_type', 'service_date', +# 'diagnosis_codes', 'procedure_codes', 'provider', +# 'facility', 'insurance_verification', 'auto_submit_primary', +# 'auto_submit_secondary', 'generate_patient_statement' +# ] +# widgets = { +# 'patient': forms.Select(attrs={'class': 'form-control'}), +# 'encounter': forms.Select(attrs={'class': 'form-control'}), +# 'bill_type': forms.Select(attrs={'class': 'form-control'}), +# 'service_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), +# 'diagnosis_codes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), +# 'procedure_codes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), +# 'provider': forms.Select(attrs={'class': 'form-control'}), +# 'facility': forms.Select(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['patient'].queryset = Patient.objects.filter(tenant=tenant) +# self.fields['provider'].queryset = User.objects.filter( +# tenant=tenant, +# groups__name__in=['Doctors', 'Nurses', 'Specialists'] +# ) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Patient Information', +# 'patient_search', +# 'patient', +# 'encounter' +# ), +# Fieldset( +# 'Service Details', +# Row( +# Column('bill_type', css_class='form-group col-md-6 mb-0'), +# Column('service_date', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('provider', css_class='form-group col-md-6 mb-0'), +# Column('facility', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'diagnosis_codes', +# 'procedure_codes' +# ), +# Fieldset( +# 'Billing Options', +# HTML('
'), +# 'insurance_verification', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'auto_submit_primary', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'auto_submit_secondary', +# HTML( +# ''), +# HTML('
'), +# HTML('
'), +# 'generate_patient_statement', +# HTML( +# ''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Create Bill', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean_diagnosis_codes(self): +# codes = self.cleaned_data.get('diagnosis_codes') +# if codes: +# # Validate ICD-10 codes format +# code_list = [code.strip() for code in codes.split(',')] +# for code in code_list: +# if not self.validate_icd10_code(code): +# raise ValidationError(f'Invalid ICD-10 code format: {code}') +# return codes +# +# def clean_procedure_codes(self): +# codes = self.cleaned_data.get('procedure_codes') +# if codes: +# # Validate CPT codes format +# code_list = [code.strip() for code in codes.split(',')] +# for code in code_list: +# if not self.validate_cpt_code(code): +# raise ValidationError(f'Invalid CPT code format: {code}') +# return codes +# +# def validate_icd10_code(self, code): +# """Validate ICD-10 code format""" +# # Basic ICD-10 validation (simplified) +# return len(code) >= 3 and code[0].isalpha() +# +# def validate_cpt_code(self, code): +# """Validate CPT code format""" +# # Basic CPT validation (simplified) +# return len(code) == 5 and code.isdigit() +# +# +# class BillItemForm(forms.ModelForm): +# """ +# Form for bill item creation/editing +# """ +# quantity = forms.DecimalField( +# max_digits=10, +# decimal_places=2, +# initial=1.00, +# widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# ) +# unit_price = forms.DecimalField( +# max_digits=10, +# decimal_places=2, +# widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# ) +# discount_amount = forms.DecimalField( +# max_digits=10, +# decimal_places=2, +# initial=0.00, +# required=False, +# widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# ) +# +# class Meta: +# model = BillItem +# fields = [ +# 'service_code', 'description', 'quantity', 'unit_price', +# 'discount_amount', 'modifier_codes', 'revenue_code' +# ] +# widgets = { +# 'service_code': forms.TextInput(attrs={'class': 'form-control'}), +# 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 2}), +# 'modifier_codes': forms.TextInput(attrs={'class': 'form-control'}), +# 'revenue_code': forms.TextInput(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Service Information', +# Row( +# Column('service_code', css_class='form-group col-md-6 mb-0'), +# Column('revenue_code', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'description', +# 'modifier_codes' +# ), +# Fieldset( +# 'Pricing', +# Row( +# Column('quantity', css_class='form-group col-md-4 mb-0'), +# Column('unit_price', css_class='form-group col-md-4 mb-0'), +# Column('discount_amount', css_class='form-group col-md-4 mb-0'), +# css_class='form-row' +# ) +# ), +# FormActions( +# Submit('submit', 'Save Item', css_class='btn btn-primary'), +# HTML('') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# quantity = cleaned_data.get('quantity') +# unit_price = cleaned_data.get('unit_price') +# discount_amount = cleaned_data.get('discount_amount', Decimal('0.00')) +# +# if quantity and unit_price: +# total_amount = quantity * unit_price +# if discount_amount > total_amount: +# raise ValidationError('Discount amount cannot exceed total amount.') +# +# return cleaned_data +# +# +# class InsuranceClaimForm(forms.ModelForm): +# """ +# Form for insurance claim submission +# """ +# claim_type = forms.ChoiceField( +# choices=[ +# ('primary', 'Primary Insurance'), +# ('secondary', 'Secondary Insurance'), +# ('tertiary', 'Tertiary Insurance') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# submit_electronically = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# prior_authorization = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# referral_number = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# +# class Meta: +# model = InsuranceClaim +# fields = [ +# 'bill', 'insurance_provider', 'claim_type', 'policy_number', +# 'group_number', 'subscriber_id', 'prior_authorization', +# 'referral_number', 'submit_electronically' +# ] +# widgets = { +# 'bill': forms.Select(attrs={'class': 'form-control'}), +# 'insurance_provider': forms.Select(attrs={'class': 'form-control'}), +# 'policy_number': forms.TextInput(attrs={'class': 'form-control'}), +# 'group_number': forms.TextInput(attrs={'class': 'form-control'}), +# 'subscriber_id': forms.TextInput(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['bill'].queryset = Bill.objects.filter(tenant=tenant) +# self.fields['insurance_provider'].queryset = InsuranceProvider.objects.filter(tenant=tenant) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Claim Information', +# Row( +# Column('bill', css_class='form-group col-md-6 mb-0'), +# Column('claim_type', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'insurance_provider' +# ), +# Fieldset( +# 'Insurance Details', +# Row( +# Column('policy_number', css_class='form-group col-md-6 mb-0'), +# Column('group_number', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'subscriber_id' +# ), +# Fieldset( +# 'Authorization', +# Row( +# Column('prior_authorization', css_class='form-group col-md-6 mb-0'), +# Column('referral_number', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ) +# ), +# Fieldset( +# 'Submission Options', +# HTML('
'), +# 'submit_electronically', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Submit Claim', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class PaymentProcessingForm(forms.ModelForm): +# """ +# Form for payment processing +# """ +# payment_amount = forms.DecimalField( +# max_digits=10, +# decimal_places=2, +# widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# ) +# payment_date = forms.DateField( +# initial=timezone.now().date(), +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# reference_number = forms.CharField( +# required=False, +# widget=forms.TextInput(attrs={'class': 'form-control'}) +# ) +# notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# send_receipt = forms.BooleanField( +# required=False, +# initial=True, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = Payment +# fields = [ +# 'bill', 'payment_method', 'payment_source', 'payment_amount', +# 'payment_date', 'reference_number', 'notes', 'send_receipt' +# ] +# widgets = { +# 'bill': forms.Select(attrs={'class': 'form-control'}), +# 'payment_method': forms.Select(attrs={'class': 'form-control'}), +# 'payment_source': forms.Select(attrs={'class': 'form-control'}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# bill = kwargs.pop('bill', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['bill'].queryset = Bill.objects.filter(tenant=tenant) +# self.fields['payment_method'].queryset = PaymentMethod.objects.filter(tenant=tenant) +# +# if bill: +# self.fields['bill'].initial = bill +# self.fields['payment_amount'].initial = bill.balance_due +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Payment Information', +# Row( +# Column('bill', css_class='form-group col-md-6 mb-0'), +# Column('payment_source', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('payment_method', css_class='form-group col-md-6 mb-0'), +# Column('payment_amount', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('payment_date', css_class='form-group col-md-6 mb-0'), +# Column('reference_number', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'notes' +# ), +# Fieldset( +# 'Options', +# HTML('
'), +# 'send_receipt', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Process Payment', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean_payment_amount(self): +# payment_amount = self.cleaned_data.get('payment_amount') +# bill = self.cleaned_data.get('bill') +# +# if payment_amount and bill: +# if payment_amount > bill.balance_due: +# raise ValidationError('Payment amount cannot exceed balance due.') +# if payment_amount <= 0: +# raise ValidationError('Payment amount must be greater than zero.') +# +# return payment_amount +# +# +# class DenialManagementForm(forms.ModelForm): +# """ +# Form for denial management +# """ +# denial_reason = forms.ChoiceField( +# choices=[ +# ('invalid_code', 'Invalid Procedure/Diagnosis Code'), +# ('not_covered', 'Service Not Covered'), +# ('prior_auth', 'Prior Authorization Required'), +# ('duplicate', 'Duplicate Claim'), +# ('incomplete', 'Incomplete Information'), +# ('timely_filing', 'Timely Filing Limit Exceeded'), +# ('other', 'Other') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# appeal_deadline = forms.DateField( +# required=False, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# corrective_action = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) +# ) +# resubmit_claim = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# file_appeal = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = ClaimDenial +# fields = [ +# 'claim', 'denial_reason', 'denial_description', 'denied_amount', +# 'appeal_deadline', 'corrective_action', 'resubmit_claim', 'file_appeal' +# ] +# widgets = { +# 'claim': forms.Select(attrs={'class': 'form-control'}), +# 'denial_description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), +# 'denied_amount': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['claim'].queryset = InsuranceClaim.objects.filter(tenant=tenant) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Denial Information', +# 'claim', +# Row( +# Column('denial_reason', css_class='form-group col-md-6 mb-0'), +# Column('denied_amount', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'denial_description', +# 'appeal_deadline' +# ), +# Fieldset( +# 'Corrective Actions', +# 'corrective_action', +# HTML('
'), +# 'resubmit_claim', +# HTML(''), +# HTML('
'), +# HTML('
'), +# 'file_appeal', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Process Denial', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class PaymentPlanForm(forms.ModelForm): +# """ +# Form for payment plan setup +# """ +# plan_type = forms.ChoiceField( +# choices=[ +# ('monthly', 'Monthly Payments'), +# ('weekly', 'Weekly Payments'), +# ('biweekly', 'Bi-weekly Payments'), +# ('custom', 'Custom Schedule') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# number_of_payments = forms.IntegerField( +# min_value=2, +# max_value=60, +# widget=forms.NumberInput(attrs={'class': 'form-control'}) +# ) +# payment_amount = forms.DecimalField( +# max_digits=10, +# decimal_places=2, +# widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# ) +# first_payment_date = forms.DateField( +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# auto_payment = forms.BooleanField( +# required=False, +# widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}) +# ) +# +# class Meta: +# model = PaymentPlan +# fields = [ +# 'bill', 'plan_type', 'total_amount', 'number_of_payments', +# 'payment_amount', 'first_payment_date', 'auto_payment' +# ] +# widgets = { +# 'bill': forms.Select(attrs={'class': 'form-control'}), +# 'total_amount': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# } +# +# def __init__(self, *args, **kwargs): +# tenant = kwargs.pop('tenant', None) +# super().__init__(*args, **kwargs) +# +# if tenant: +# self.fields['bill'].queryset = Bill.objects.filter(tenant=tenant, balance_due__gt=0) +# +# # Set minimum date to tomorrow +# tomorrow = timezone.now().date() + timezone.timedelta(days=1) +# self.fields['first_payment_date'].widget.attrs['min'] = tomorrow.isoformat() +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Payment Plan Details', +# 'bill', +# Row( +# Column('plan_type', css_class='form-group col-md-6 mb-0'), +# Column('total_amount', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# Row( +# Column('number_of_payments', css_class='form-group col-md-6 mb-0'), +# Column('payment_amount', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'first_payment_date' +# ), +# Fieldset( +# 'Options', +# HTML('
'), +# 'auto_payment', +# HTML(''), +# HTML('
') +# ), +# FormActions( +# Submit('submit', 'Create Payment Plan', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# def clean(self): +# cleaned_data = super().clean() +# total_amount = cleaned_data.get('total_amount') +# number_of_payments = cleaned_data.get('number_of_payments') +# payment_amount = cleaned_data.get('payment_amount') +# +# if total_amount and number_of_payments and payment_amount: +# calculated_total = payment_amount * number_of_payments +# if abs(calculated_total - total_amount) > Decimal('0.01'): +# raise ValidationError('Payment amount × number of payments must equal total amount.') +# +# return cleaned_data +# +# +# class CollectionsForm(forms.Form): +# """ +# Form for collections management +# """ +# collection_action = forms.ChoiceField( +# choices=[ +# ('letter_1', 'Send First Collection Letter'), +# ('letter_2', 'Send Second Collection Letter'), +# ('letter_3', 'Send Final Collection Letter'), +# ('phone_call', 'Schedule Phone Call'), +# ('external_agency', 'Send to External Agency'), +# ('write_off', 'Write Off Balance') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# collection_notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) +# ) +# follow_up_date = forms.DateField( +# required=False, +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# write_off_reason = forms.ChoiceField( +# choices=[ +# ('uncollectible', 'Uncollectible'), +# ('patient_deceased', 'Patient Deceased'), +# ('bankruptcy', 'Bankruptcy'), +# ('small_balance', 'Small Balance'), +# ('other', 'Other') +# ], +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Collection Action', +# 'collection_action', +# 'collection_notes', +# 'follow_up_date' +# ), +# Fieldset( +# 'Write-off Details', +# 'write_off_reason', +# HTML('Required only for write-off actions') +# ), +# FormActions( +# Submit('submit', 'Execute Collection Action', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class InsuranceVerificationForm(forms.Form): +# """ +# Form for insurance verification +# """ +# verification_type = forms.ChoiceField( +# choices=[ +# ('eligibility', 'Eligibility Verification'), +# ('benefits', 'Benefits Verification'), +# ('authorization', 'Prior Authorization'), +# ('referral', 'Referral Verification') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# service_date = forms.DateField( +# widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}) +# ) +# procedure_codes = forms.CharField( +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# verification_notes = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# Fieldset( +# 'Verification Details', +# Row( +# Column('verification_type', css_class='form-group col-md-6 mb-0'), +# Column('service_date', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'procedure_codes', +# 'verification_notes' +# ), +# FormActions( +# Submit('submit', 'Verify Insurance', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# class BulkBillingForm(forms.Form): +# """ +# Form for bulk billing operations +# """ +# action = forms.ChoiceField( +# choices=[ +# ('submit_claims', 'Submit Claims'), +# ('generate_statements', 'Generate Patient Statements'), +# ('send_reminders', 'Send Payment Reminders'), +# ('update_status', 'Update Status'), +# ('apply_adjustments', 'Apply Adjustments') +# ], +# required=True, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# bill_ids = forms.CharField( +# widget=forms.HiddenInput() +# ) +# new_status = forms.ChoiceField( +# choices=[ +# ('pending', 'Pending'), +# ('submitted', 'Submitted'), +# ('paid', 'Paid'), +# ('denied', 'Denied'), +# ('cancelled', 'Cancelled') +# ], +# required=False, +# widget=forms.Select(attrs={'class': 'form-control'}) +# ) +# adjustment_amount = forms.DecimalField( +# max_digits=10, +# decimal_places=2, +# required=False, +# widget=forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}) +# ) +# adjustment_reason = forms.CharField( +# required=False, +# widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}) +# ) +# +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.helper = FormHelper() +# self.helper.layout = Layout( +# 'bill_ids', +# Fieldset( +# 'Bulk Operation', +# 'action', +# 'new_status', +# Row( +# Column('adjustment_amount', css_class='form-group col-md-6 mb-0'), +# css_class='form-row' +# ), +# 'adjustment_reason' +# ), +# FormActions( +# Submit('submit', 'Execute Bulk Operation', css_class='btn btn-primary'), +# HTML('Cancel') +# ) +# ) +# +# +# diff --git a/billing/urls.py b/billing/urls.py index a60e0c98..1e5d7bd9 100644 --- a/billing/urls.py +++ b/billing/urls.py @@ -14,6 +14,8 @@ urlpatterns = [ # Medical Bills path('bills/', views.MedicalBillListView.as_view(), name='bill_list'), path('bills//', views.MedicalBillDetailView.as_view(), name='bill_detail'), + path('bills//', views.bill_details_api, name='bill_details_api'), + path('bills//line-items', views.bill_line_items_api, name='bill_line_items_api'), path('bills/create/', views.MedicalBillCreateView.as_view(), name='bill_create'), path('bills//edit/', views.MedicalBillUpdateView.as_view(), name='bill_update'), path('bills//delete/', views.MedicalBillDeleteView.as_view(), name='bill_delete'), @@ -40,14 +42,15 @@ urlpatterns = [ path('bills//payments/create/', views.PaymentCreateView.as_view(), name='bill_payment_create'), # HTMX endpoints - path('htmx/stats/', views.htmx_billing_stats, name='billing_stats'), - path('htmx/bill-search/', views.htmx_bill_search, name='bill_search'), + path('stats/bills/', views.billing_stats, name='billing_stats'), + path('bill-search/', views.bill_search, name='bill_search'), # Action endpoints path('bills//submit/', views.submit_bill, name='submit_bill'), # Export endpoints path('export/bills/', views.export_bills, name='export_bills'), + path('export/claims/', views.export_claims, name='export_claims'), # API endpoints # path('api/', include('billing.api.urls')), diff --git a/billing/views.py b/billing/views.py index 59282afe..f8edfbb2 100644 --- a/billing/views.py +++ b/billing/views.py @@ -393,7 +393,7 @@ class InsuranceClaimDetailView(LoginRequiredMixin, DetailView): claim = self.get_object() # Get related data - context['status_updates'] = claim.claimstatusupdate_set.all().order_by('-update_date') + # context['status_updates'] = claim.claimstatusupdate_set.all().order_by('-update_date') return context @@ -426,8 +426,8 @@ class InsuranceClaimCreateView(LoginRequiredMixin, PermissionRequiredMixin, Crea return kwargs def form_valid(self, form): - # Set medical bill and created_by - bill_id = self.kwargs.get('bill_id') + # Prefer URL bill_id; otherwise read from POST("medical_bill") + bill_id = self.kwargs.get('bill_id') or self.request.POST.get('medical_bill') if bill_id: try: medical_bill = MedicalBill.objects.get( @@ -438,22 +438,25 @@ class InsuranceClaimCreateView(LoginRequiredMixin, PermissionRequiredMixin, Crea except MedicalBill.DoesNotExist: messages.error(self.request, 'Medical bill not found.') return redirect('billing:bill_list') - + else: + messages.error(self.request, 'Please select a medical bill.') + return redirect('billing:claim_create') + form.instance.created_by = self.request.user - - # Generate claim number + if not form.instance.claim_number: form.instance.claim_number = form.instance.generate_claim_number() - + response = super().form_valid(form) - - messages.success( - self.request, - f'Insurance claim {self.object.claim_number} created successfully.' - ) - + messages.success(self.request, f'Insurance claim {self.object.claim_number} created successfully.') return response - + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + tenant = getattr(self.request, 'tenant', None) + ctx['available_bills'] = MedicalBill.objects.filter(tenant=tenant).select_related('patient') + return ctx + def get_success_url(self): return reverse('billing:claim_detail', kwargs={'claim_id': self.object.claim_id}) @@ -631,7 +634,7 @@ class PaymentCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView) # return JsonResponse(stats) @login_required -def htmx_billing_stats(request): +def billing_stats(request): """ HTMX view for billing statistics. """ @@ -690,7 +693,30 @@ def htmx_billing_stats(request): @login_required -def htmx_bill_search(request): +def bill_details_api(request, bill_id): + tenant = getattr(request, 'tenant', None) + if not tenant: + return JsonResponse({'error': 'No tenant found'}, status=400) + + bill = get_object_or_404( + MedicalBill.objects.select_related('patient', 'billing_provider'), + bill_id=bill_id, + tenant=tenant, + ) + + data = { + 'patient_name': bill.patient.get_full_name() if bill.patient else '', + 'bill_number': bill.bill_number or '', + 'bill_date': bill.bill_date.isoformat() if bill.bill_date else '', + 'total_amount': str(bill.total_amount or 0), + 'service_date_from': bill.service_date_from.isoformat() if bill.service_date_from else '', + 'service_date_to': bill.service_date_to.isoformat() if bill.service_date_to else '', + 'billing_provider': bill.billing_provider.get_full_name() if bill.billing_provider else '', + } + return JsonResponse(data) + +@login_required +def bill_search(request): """ HTMX endpoint for bill search. """ @@ -1391,6 +1417,145 @@ def payment_download(request, payment_id): messages.error(request, f'Error generating PDF: {str(e)}') return redirect('billing:payment_receipt', payment_id=payment_id) + +@login_required +def export_claims(request): + """ + Export insurance claims to CSV. + Supports optional filtering by 'claims' GET param: ?claims=ID1,ID2,ID3 + """ + tenant = getattr(request, 'tenant', None) + if not tenant: + return HttpResponse('No tenant found', status=400) + + # Base queryset + qs = InsuranceClaim.objects.filter(tenant=tenant).select_related( + 'medical_bill__patient', + 'insurance_info', + ) + + # Optional selection filter (comma-separated claim_ids) + selected = request.GET.get('claims') + if selected: + claim_ids = [c.strip() for c in selected.split(',') if c.strip()] + if claim_ids: + qs = qs.filter(claim_id__in=claim_ids) + + # Prepare CSV response + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="insurance_claims.csv"' + + writer = csv.writer(response) + writer.writerow([ + 'Claim Number', + 'Bill Number', + 'Patient Name', + 'Insurance Company', + 'Claim Type', + 'Service From', + 'Service To', + 'Billed Amount', + 'Status', + ]) + + for claim in qs: + bill = getattr(claim, 'medical_bill', None) + patient = getattr(bill, 'patient', None) + + # Safely get nice display values + insurance_company = getattr(getattr(claim, 'insurance_info', None), 'company', None) + if not insurance_company: + # Fallback to __str__ of insurance_info or empty + insurance_company = str(getattr(claim, 'insurance_info', '')) or '' + + claim_type = getattr(claim, 'get_claim_type_display', None) + if callable(claim_type): + claim_type = claim.get_claim_type_display() + else: + claim_type = getattr(claim, 'claim_type', '') or '' + + status_val = '' + get_status_display = getattr(claim, 'get_status_display', None) + if callable(get_status_display): + status_val = claim.get_status_display() + else: + # Fallback if no choices helper exists + status_val = getattr(claim, 'status', '') or '' + + writer.writerow([ + getattr(claim, 'claim_number', '') or '', + getattr(bill, 'bill_number', '') if bill else '', + patient.get_full_name() if patient else '', + insurance_company, + claim_type, + claim.service_date_from.strftime('%Y-%m-%d') if getattr(claim, 'service_date_from', None) else '', + claim.service_date_to.strftime('%Y-%m-%d') if getattr(claim, 'service_date_to', None) else '', + str(getattr(claim, 'billed_amount', '')) or '0', + status_val, + ]) + + return response + + +@login_required +def bill_line_items_api(request, bill_id=None): + """ + Return line items for a medical bill as JSON. + Supports: + - /api/bills//line-items/ + - /api/bills/line-items/?bill_id= + """ + tenant = getattr(request, 'tenant', None) + if not tenant: + return JsonResponse({'success': False, 'error': 'No tenant found'}, status=400) + + bill_id = bill_id or request.GET.get('bill_id') + if not bill_id: + return JsonResponse({'success': False, 'error': 'bill_id is required'}, status=400) + + bill = get_object_or_404( + MedicalBill.objects.select_related('patient').prefetch_related('billlineitem_set'), + bill_id=bill_id, + tenant=tenant, + ) + + # Prefer per-item service date if your model has it; otherwise fall back + bill_service_date = ( + bill.service_date_from.isoformat() if getattr(bill, 'service_date_from', None) + else bill.bill_date.isoformat() if getattr(bill, 'bill_date', None) + else '' + ) + + items = [] + for li in bill.billlineitem_set.all(): + qty = getattr(li, 'quantity', 0) or 0 + price = getattr(li, 'unit_price', Decimal('0')) or Decimal('0') + # If your BillLineItem has service_date, use it; otherwise default + li_service_date = getattr(li, 'service_date', None) + if li_service_date: + li_service_date = li_service_date.isoformat() + else: + li_service_date = bill_service_date + + items.append({ + 'id': getattr(li, 'id', None), + 'service_code': getattr(li, 'service_code', '') or '', + 'description': getattr(li, 'description', '') or '', + 'quantity': qty, + 'unit_price': str(price), + 'service_date': li_service_date, + 'total': str(price * Decimal(qty)), + }) + + return JsonResponse({ + 'success': True, + 'bill_id': str(bill.bill_id), + 'patient_name': bill.patient.get_full_name() if bill.patient else '', + 'line_items': items, + }) + + + # # # """ @@ -2159,3 +2324,503 @@ payment_list = PaymentListView.as_view() # # # +# from django.shortcuts import render, redirect, get_object_or_404 +# from django.contrib.auth.decorators import login_required, permission_required +# from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin +# from django.contrib import messages +# from django.views.generic import ( +# CreateView, UpdateView, DeleteView, DetailView, ListView, FormView +# ) +# from django.urls import reverse_lazy, reverse +# from django.http import JsonResponse, HttpResponse +# from django.utils import timezone +# from django.db import transaction +# from django.core.mail import send_mail +# from django.conf import settings +# from django.db.models import Q, Sum, Count +# from viewflow.views import CreateProcessView, UpdateProcessView +# from decimal import Decimal +# import json +# +# from .models import ( +# Bill, BillItem, InsuranceClaim, Payment, PaymentMethod, +# InsuranceProvider, ClaimDenial, PaymentPlan +# ) +# from .forms import ( +# MedicalBillingForm, BillItemForm, InsuranceClaimForm, PaymentProcessingForm, +# DenialManagementForm, PaymentPlanForm, CollectionsForm, +# InsuranceVerificationForm, BulkBillingForm +# ) +# from .flows import MedicalBillingFlow, InsuranceClaimFlow, PaymentProcessingFlow, DenialManagementFlow, CollectionsFlow +# from patients.models import Patient +# +# +# class MedicalBillingView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for medical billing workflow +# """ +# model = Bill +# form_class = MedicalBillingForm +# template_name = 'billing/medical_billing.html' +# permission_required = 'billing.can_create_bills' +# flow_class = MedicalBillingFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create bill +# bill = form.save(commit=False) +# bill.tenant = self.request.user.tenant +# bill.created_by = self.request.user +# bill.status = 'draft' +# bill.save() +# +# # Start medical billing workflow +# process = self.flow_class.start.run( +# bill=bill, +# insurance_verification=form.cleaned_data.get('insurance_verification', True), +# auto_submit_primary=form.cleaned_data.get('auto_submit_primary', True), +# auto_submit_secondary=form.cleaned_data.get('auto_submit_secondary', False), +# generate_patient_statement=form.cleaned_data.get('generate_patient_statement', True), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Medical bill created successfully for {bill.patient.get_full_name()}. ' +# f'Billing workflow initiated.' +# ) +# +# return redirect('billing:bill_detail', pk=bill.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Create Medical Bill' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Billing', 'url': reverse('billing:dashboard')}, +# {'name': 'Bills', 'url': reverse('billing:bill_list')}, +# {'name': 'Create Bill', 'url': ''} +# ] +# return context +# +# +# class BillItemView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): +# """ +# View for bill item creation/editing +# """ +# model = BillItem +# form_class = BillItemForm +# template_name = 'billing/bill_item_form.html' +# permission_required = 'billing.can_edit_bill_items' +# +# def get_success_url(self): +# return reverse('billing:bill_detail', kwargs={'pk': self.kwargs['bill_id']}) +# +# def form_valid(self, form): +# bill = get_object_or_404(Bill, pk=self.kwargs['bill_id']) +# +# with transaction.atomic(): +# # Create bill item +# item = form.save(commit=False) +# item.bill = bill +# item.tenant = bill.tenant +# item.save() +# +# # Recalculate bill totals +# self.recalculate_bill_totals(bill) +# +# messages.success( +# self.request, +# f'Bill item "{item.description}" added successfully.' +# ) +# +# return super().form_valid(form) +# +# def recalculate_bill_totals(self, bill): +# """Recalculate bill totals""" +# items = bill.items.all() +# subtotal = sum(item.total_amount for item in items) +# +# bill.subtotal = subtotal +# bill.total_amount = subtotal + bill.tax_amount +# bill.balance_due = bill.total_amount - bill.paid_amount +# bill.save() +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['bill'] = get_object_or_404(Bill, pk=self.kwargs['bill_id']) +# context['title'] = 'Add Bill Item' +# return context +# +# +# class InsuranceClaimView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for insurance claim submission workflow +# """ +# model = InsuranceClaim +# form_class = InsuranceClaimForm +# template_name = 'billing/insurance_claim.html' +# permission_required = 'billing.can_submit_claims' +# flow_class = InsuranceClaimFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create insurance claim +# claim = form.save(commit=False) +# claim.tenant = self.request.user.tenant +# claim.submitted_by = self.request.user +# claim.status = 'pending' +# claim.save() +# +# # Start insurance claim workflow +# process = self.flow_class.start.run( +# claim=claim, +# submit_electronically=form.cleaned_data.get('submit_electronically', True), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Insurance claim submitted successfully. Claim ID: {claim.claim_number}' +# ) +# +# return redirect('billing:claim_detail', pk=claim.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Submit Insurance Claim' +# context['breadcrumbs'] = [ +# {'name': 'Home', 'url': reverse('core:dashboard')}, +# {'name': 'Billing', 'url': reverse('billing:dashboard')}, +# {'name': 'Claims', 'url': reverse('billing:claim_list')}, +# {'name': 'Submit Claim', 'url': ''} +# ] +# return context +# +# +# class PaymentProcessingView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for payment processing workflow +# """ +# model = Payment +# form_class = PaymentProcessingForm +# template_name = 'billing/payment_processing.html' +# permission_required = 'billing.can_process_payments' +# flow_class = PaymentProcessingFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# +# # Pre-populate bill if provided +# bill_id = self.kwargs.get('bill_id') +# if bill_id: +# kwargs['bill'] = get_object_or_404(Bill, pk=bill_id) +# +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create payment +# payment = form.save(commit=False) +# payment.tenant = self.request.user.tenant +# payment.processed_by = self.request.user +# payment.status = 'pending' +# payment.save() +# +# # Update bill balance +# bill = payment.bill +# bill.paid_amount += payment.payment_amount +# bill.balance_due = bill.total_amount - bill.paid_amount +# +# if bill.balance_due <= 0: +# bill.status = 'paid' +# else: +# bill.status = 'partial_payment' +# +# bill.save() +# +# # Start payment processing workflow +# process = self.flow_class.start.run( +# payment=payment, +# send_receipt=form.cleaned_data.get('send_receipt', True), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Payment of ${payment.payment_amount} processed successfully. ' +# f'Remaining balance: ${bill.balance_due}' +# ) +# +# return redirect('billing:payment_detail', pk=payment.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Process Payment' +# +# bill_id = self.kwargs.get('bill_id') +# if bill_id: +# context['bill'] = get_object_or_404(Bill, pk=bill_id) +# +# return context +# +# +# class DenialManagementView(LoginRequiredMixin, PermissionRequiredMixin, CreateProcessView): +# """ +# View for denial management workflow +# """ +# model = ClaimDenial +# form_class = DenialManagementForm +# template_name = 'billing/denial_management.html' +# permission_required = 'billing.can_manage_denials' +# flow_class = DenialManagementFlow +# +# def get_form_kwargs(self): +# kwargs = super().get_form_kwargs() +# kwargs['tenant'] = self.request.user.tenant +# return kwargs +# +# def form_valid(self, form): +# with transaction.atomic(): +# # Create denial record +# denial = form.save(commit=False) +# denial.tenant = self.request.user.tenant +# denial.processed_by = self.request.user +# denial.save() +# +# # Update claim status +# claim = denial.claim +# claim.status = 'denied' +# claim.save() +# +# # Start denial management workflow +# process = self.flow_class.start.run( +# denial=denial, +# resubmit_claim=form.cleaned_data.get('resubmit_claim', False), +# file_appeal=form.cleaned_data.get('file_appeal', False), +# created_by=self.request.user +# ) +# +# messages.success( +# self.request, +# f'Denial processed for claim {claim.claim_number}. ' +# f'Workflow initiated for corrective actions.' +# ) +# +# return redirect('billing:denial_detail', pk=denial.pk) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Manage Claim Denial' +# return context +# +# +# class BillListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# """ +# View for listing bills +# """ +# model = Bill +# template_name = 'billing/bill_list.html' +# context_object_name = 'bills' +# permission_required = 'billing.view_bill' +# paginate_by = 25 +# +# def get_queryset(self): +# queryset = Bill.objects.filter(tenant=self.request.user.tenant) +# +# # Apply filters +# search = self.request.GET.get('search') +# if search: +# queryset = queryset.filter( +# Q(patient__first_name__icontains=search) | +# Q(patient__last_name__icontains=search) | +# Q(bill_number__icontains=search) +# ) +# +# status = self.request.GET.get('status') +# if status: +# queryset = queryset.filter(status=status) +# +# date_from = self.request.GET.get('date_from') +# if date_from: +# queryset = queryset.filter(service_date__gte=date_from) +# +# date_to = self.request.GET.get('date_to') +# if date_to: +# queryset = queryset.filter(service_date__lte=date_to) +# +# return queryset.order_by('-created_at') +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# context['title'] = 'Bills' +# context['search'] = self.request.GET.get('search', '') +# context['selected_status'] = self.request.GET.get('status', '') +# context['date_from'] = self.request.GET.get('date_from', '') +# context['date_to'] = self.request.GET.get('date_to', '') +# context['billing_stats'] = self.get_billing_stats() +# return context +# +# def get_billing_stats(self): +# """Get billing statistics""" +# bills = Bill.objects.filter(tenant=self.request.user.tenant) +# return { +# 'total_bills': bills.count(), +# 'total_amount': bills.aggregate(Sum('total_amount'))['total_amount__sum'] or 0, +# 'total_paid': bills.aggregate(Sum('paid_amount'))['paid_amount__sum'] or 0, +# 'total_outstanding': bills.aggregate(Sum('balance_due'))['balance_due__sum'] or 0 +# } +# +# +# class BillDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# """ +# View for bill details +# """ +# model = Bill +# template_name = 'billing/bill_detail.html' +# context_object_name = 'bill' +# permission_required = 'billing.view_bill' +# +# def get_queryset(self): +# return Bill.objects.filter(tenant=self.request.user.tenant) +# +# def get_context_data(self, **kwargs): +# context = super().get_context_data(**kwargs) +# bill = self.object +# context['title'] = f'Bill {bill.bill_number}' +# context['items'] = bill.items.all() +# context['claims'] = bill.claims.all() +# context['payments'] = bill.payments.all() +# context['payment_plan'] = getattr(bill, 'payment_plan', None) +# context['can_edit'] = self.request.user.has_perm('billing.change_bill') +# context['can_process_payment'] = self.request.user.has_perm('billing.can_process_payments') +# return context +# +# +# # AJAX Views +# @login_required +# @permission_required('billing.view_patient') +# def patient_billing_search_ajax(request): +# """AJAX view for patient billing search""" +# query = request.GET.get('q', '') +# if len(query) < 2: +# return JsonResponse({'patients': []}) +# +# patients = Patient.objects.filter( +# tenant=request.user.tenant +# ).filter( +# Q(first_name__icontains=query) | +# Q(last_name__icontains=query) | +# Q(patient_id__icontains=query) | +# Q(insurance_id__icontains=query) +# )[:10] +# +# patient_data = [ +# { +# 'id': patient.id, +# 'name': patient.get_full_name(), +# 'patient_id': patient.patient_id, +# 'insurance': patient.primary_insurance.name if patient.primary_insurance else 'No Insurance', +# 'outstanding_balance': str(patient.get_outstanding_balance()) +# } +# for patient in patients +# ] +# +# return JsonResponse({'patients': patient_data}) +# +# +# @login_required +# @permission_required('billing.can_calculate_totals') +# def calculate_bill_totals_ajax(request): +# """AJAX view to calculate bill totals""" +# if request.method == 'POST': +# try: +# data = json.loads(request.body) +# items = data.get('items', []) +# +# subtotal = Decimal('0.00') +# for item in items: +# quantity = Decimal(str(item.get('quantity', 1))) +# unit_price = Decimal(str(item.get('unit_price', 0))) +# discount = Decimal(str(item.get('discount', 0))) +# +# item_total = (quantity * unit_price) - discount +# subtotal += item_total +# +# tax_rate = Decimal('0.08') # 8% tax rate (configurable) +# tax_amount = subtotal * tax_rate +# total_amount = subtotal + tax_amount +# +# return JsonResponse({ +# 'success': True, +# 'subtotal': str(subtotal), +# 'tax_amount': str(tax_amount), +# 'total_amount': str(total_amount) +# }) +# except Exception as e: +# return JsonResponse({ +# 'success': False, +# 'error': str(e) +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# @login_required +# @permission_required('billing.can_verify_insurance') +# def verify_insurance_ajax(request, patient_id): +# """AJAX view to verify insurance""" +# if request.method == 'POST': +# try: +# patient = Patient.objects.get( +# id=patient_id, +# tenant=request.user.tenant +# ) +# +# # Perform insurance verification +# verification_result = verify_patient_insurance(patient) +# +# return JsonResponse({ +# 'success': verification_result['success'], +# 'data': verification_result +# }) +# except Patient.DoesNotExist: +# return JsonResponse({ +# 'success': False, +# 'message': 'Patient not found.' +# }) +# +# return JsonResponse({'success': False, 'message': 'Invalid request.'}) +# +# +# def verify_patient_insurance(patient): +# """Verify patient insurance""" +# try: +# # This would implement actual insurance verification +# return { +# 'success': True, +# 'status': 'active', +# 'coverage': 'full', +# 'copay': 25.00, +# 'deductible': 500.00, +# 'deductible_met': 150.00, +# 'out_of_pocket_max': 2000.00, +# 'out_of_pocket_met': 300.00 +# } +# except Exception as e: +# return { +# 'success': False, +# 'error': str(e) +# } +# diff --git a/blood_bank/__pycache__/forms.cpython-312.pyc b/blood_bank/__pycache__/forms.cpython-312.pyc index 9283a135e2659bef4fc589aad3fa6e2c71790320..7690112b2f93311e4720ffd3983a24530c09868c 100644 GIT binary patch delta 22 ccmeymp7HB?M()$Ryj%=GaCraTjoh!o0b?BqfdBvi delta 22 ccmeymp7HB?M()$Ryj%=GaBA<)joh!o0b?!*f&c&j diff --git a/blood_bank/__pycache__/models.cpython-312.pyc b/blood_bank/__pycache__/models.cpython-312.pyc index 1adafb18c97c7c849ea1317e98fab5b9972b5168..6daed658862a6b6d158f082734891bfacb96080c 100644 GIT binary patch delta 38 tcmZ4Uk#W^WM&8rByj%=Gz_)L2hUrG$|7Faa8AX!?%eOKrOg>)z6aWM>4jljh delta 40 vcmZ4Wk#WsOM&8rByj%=Gux0no4D*e=|I1jplkuM diff --git a/blood_bank/__pycache__/urls.cpython-312.pyc b/blood_bank/__pycache__/urls.cpython-312.pyc index 0d2a88b58e5848511a883db97bd86d47b2e38243..78ba56aaf8faf6855b07982c78089752c27a058d 100644 GIT binary patch delta 649 zcmYk2!E4h{9LJXskrmQbvPGJhjZkWq$TX}9S&MW{3uSEw!`Uf_)8YbF$GWv09z=Te zB3R?0#~}#wBFJtc=ur?fKVIMmy?OEEA^rga)7P=~!TbIAec$K%<-LcOiNXKi`N&kb z{yzHh_-Bt#uy4=z7C!b~D?QZ1>M{&%SD20A)E!M9MvaWx3G-rj_MD~Ud)khFvA-kf zL9E!^ZMKR|r{37vY&g$Og+j}zcbo~KwzqvMxL^51cW}YpX*RcOyNyn@(e6-CIFlyg z#^N}#C4|pu&4gtzLp`^g{R5{xP7){8iLf(0I>g6;Z=!!9`7n+Ncl)y&M7Qo)khCzl z0?8GUw7<{!+}(gLF){XEbn4u+H=XF;K-mP@MA-t_B68+i$gBr3%ET$NaFjwL2SyH! z5*Q_7ta|HPKKHt43%b8A6@nk8zUKb%E118N3U8&sR9MXxe6 z2Qq~&h0x3SehQ^DNNJR^AZ3Yk(<|N?-c+H?91YTrW>L36w^1*HUM70g+t~A2Zr{Ba zU%hXFXrgF=Xb~~viGWi{lHeu45Tm{4j znCd1+F>6g;z^t|T8S^79{vvLm-Xb0l!3!iN|K^j_DB=fk1we!#h!6%5A|OH(M2LY1 zaUd~yA^$Tj3m}6Lh>PPVPZWr=H@&EAy2I}Zi}wd!cSe4uk9-WQoEJDHXP91>*1agL zy8$TW{DB`VB>lbBEJ2gK1a)IIE(&X0(091P;`l)ltWpZBQhtHx zbw!JdiWV2_gRZaye~<>t$pGa#vw>URQU#sP1^dBkl@I{0DuooB>!) ddPeAVS@Vms<`?WjuCRn|o+q@CiNy@)aRBZ8bQ}Nx diff --git a/blood_bank/__pycache__/views.cpython-312.pyc b/blood_bank/__pycache__/views.cpython-312.pyc index 6ce82638a3bd4009e6a0f974d02120c1f1ec46f6..c8323144f5b02c50c1d2918788a24807e3c21a0c 100644 GIT binary patch delta 17637 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 Np~26G%akmD`2Y5kQKkR@ delta 15209 zcmb7r33!v&m8gF0wtiW%CGVSzH-v4xuoEDF*=&OW+k_w>LiR6=K#OxFvp5DhOTTgE zr3vJwg)}5MZPJp!G$d-XwjD^b@LrZDVP|Ci&o93H0tx3{1{nBaYopb+R3y#y7 z(f4tDmvhg(_uRAHbAR4@L-p_lRrnpFF;fA*hhBeW->PR6ijT39_-WG$2m9-%Sx}(r*f!#YKPjVacEeZ%B%J196F!gp=WiqH^Z0d$Yf=W*WlwFywB(` zvbxrrj#5~h(Oc##ca%e0mSFPQd=-ug-z>*0U!|kcSLLYkRXeJEHIAAS ze=R6xIA(8yZ?0pmuhG%yYjQOCnjOu)76)zSO2eGOtrN2EQ=F5z;aI9vtXBv*_bCL6 zn{$_+Q%fC=TL90RhPTYEQ!3ngA@>|7VF-Dt-XyiT_nV>OH`OB>e;_42g(ny^gBmLyb>>Q0hbD`U+{ zVpYz7wGN0^rP>|qpBiR^QYslbM?&)0pZ`PS(k=3WTP9E{WGX1K#Et@LH%%mD{fq=B4l*TV=fY zY4jGP`jhi^%|LJA40zoMdh}UUdAMhWQHy67wQUBxB{SgNmY|-t+NCq#ZI|$r!hD*k zu4qK{C=k-OxNL?&I}*gHW5zKnW*D;+0x=G5Xk-lIZ zUf+WAHsf5JnAPhI1O#V42@DQ6J%T-h;3mj+1iKLIMsNoJQMG<;kErT*hsf>NW~76; zTe&^-?c4^gjs7wB_grt}lf1_`!#?a~b8Mu4Ur=Qj#QH%5hv+K>_5=A?#0f-|%j;$H ziCNt}t9rI|J6ktwZfjlJ%_bywA|e4`SCb&(YY!Z9k^UfYVkN`r?DM*UL8mi_e6!hX zBV-R0$T0vzWorWd0HN8d3$?va4<4sYs|)CTg~MDg<%;HT1+>0s*@D9fe9vMa( zPN$tC_u?pY5-TOD0-_>lrH>aiF``7E7q=C1O8QYvEu|~VX!&h6x;@{j6;y)yoRZ!s zE~ZcHH>!tK!z%jx3M;+dsaHaA>mwy$L3>(#R2{MaLG}Y-(+#WBgiSwG%eG(>+##38 zYdh$1AF>_tg!b8lfZrAJ1pKyrAoc-rKiG&{35+EQq($o(k zB|MxU(u5PS*%L>W-k+o2>l*Dr?V>y-a zoH?Mh52gUDObMSe=7(3qz(6*>8n`LiaAYvRTAvEusi z;<=NBRq?_(vBEjyh4nWwG$!rH`Y*E-e9rOOXz|L6wd0wF_Ncm@poq|l@_de?cRyg| zhUl+JG5v*CXP_Zj{h|NK;ygO`Tn7Dv*Tx;DX5XlCSV^xhww64m5Hydg66S+C`I+&0P%^MkSFAI+l`{u=ML=)2&57QknaEx^`4;fpv&tKM0L=0&@HM5 zgKi>b_OZzXXYUb`foQtmU|*j*7$i6q!Jv}KkaV~zN&TL{(_sf2#KliPOo=4#cSLjWDckJ$Cr}D1o%CDIUPUW8|d9-BQR5PlcG?*S*e*f|ZZk@CioNPPM zHn#0}+qkuEbnRq$&6(jxhey{=@FkOc_CxLWw?DA)8gJbc=SyOI$*JvUwPy#PJNC@6 z=-d_26+O|KZ4>-$*DS@+k_8tvZ|g7VCoFAIzU>oJ!T-2xRQ-t|8;^IzWoz{I{@BWW z;|5Pu?IFGN+m$7BQMr+JyqE!Y>!X@A9HFsYHtn$TJe(d~a(gYeow{z%Lp`M-U)6u( zeDnK|h8$BKRfP(H8SDpotq1*A3K>G?X;qqj8-@zD4G1U!?DTCOKOQYpZ1Qaw%8nBZ zwBF+nhFtzWH#tR*Rh5L1&EzozrvVJ{G7(8YROAWlVRqmQlM*JXWOJ}zh`ObgQ` zgf~Cbc7NLg9Uuia3BktyiWH1hPnc$>1Yy!_JvDgt*bS9(6{r0|q2zT_3Z+H|5^=j1juxvZY6ZC)0-a0R3CdZ(UG$25glNdQ859w|8vaWwXoHU~; zF_|3^JFJ=PWj>P$r`zl4_w;(ap3o6z-#&NW0rDIWJ4fHLpJfiHkE74Ktjf=o^nZV= z3T+eEFYdM$Y7VN^0tg%3nqNfgN(?IHFh^Zh=77}XDpXeOwq^<{lu}X-R&47dRz!hT ztJHd4lN4sTgZlqTtDc68ZCU5F(@`@8-Heo3>v{cjbiI(l&{xveddoofGU)k7GUQnc zq`vc+i9tiK!x-=y<4^?7pX@fY$#vG`PIZ(+DOW~cz-!JLgG{4I+9}G^JwYMOr z=Qjfs4erAO9&*GfxQ+zLLTCa1y#%}WVy}9@)$g_|i5pu`KB#X&S=bAUn7c3J^V-d1 zF7}}NlwwNeu2Y^GwOZu+yl$7@Ex;ThmlUmKb^hX1>xcOShk4BjPf zD2W+LPVK&8sGBURju+L(it1ms#+S6mmb7199$T^_T2wz?B)TEHt#OJS#&0l+QUu^znhP)-6FfQU+(X2D|kJdjn z_xzHVtKv&LVoN(NZ;CB-Ow{d+7401DNYZ-w03*;o+VP3G@KoIx88^=vX`9R`JXv?5 z?qnlf>@BRE(kgOG!Ia(5s8|@2DTgtuFRmXqY>cWmf<41tO`sYI> zi5N8ux1nUna#TGGap|yH(41Bs)r3rNHtYw^OA9(9hc0jf(hbdCjrRqn249a%LvU%a z5qEIV8wxUu3jQlIb^2lkB7j)-9ua3}5O<$vz~lCZ>?-maOb1a7^aeqANgx;mPY4z- zI8;jm3m{r%F|ecodda1+ShX0&Nq3c0z*>TB%-(9HAXSGti!mzBLVkhZ9}zHd#n2~R zShG{hb;{xDC3Jef1-#(B0GPbyR6e!jLjFYdl96@{Ui0F7X^bz8^Hnjv>Oy9euNvoX ziSz9-zWwqoKQPxN09Wy3aIbwzy7EP9 z*7x9k3mHQ0DA-bxO;7B~hpWmTwpZv>2WG?ezkt}Mjr$w|o_v-1yoR3MxRKtyJ5Nn| zhSl`Ml{|XyZfl0q09(c%9oe0)Jj~JT4c2TyJ7iQS`jk$zBKX5jYTHysEBeax(oJT6 z8C|uZa#e+dpil@I!|MIB61CJ{uV`B6c#bjd!bOI8o;TR(o7tFwnEREnV(@Fl}yPlSXcXKJpA8+O5+guqq^! z3LIDj_5)}G!4G)7kU3xqLfYwDOYGr?5IGrJhz2Igvdu-&m7;cb+e;Jq=^+MFFJ4|R za|*$~CHHb<|DHlIOYs#<5}eKKG=%oX?2)xsb*5|Pil?g2ZkRAH7}d}p?x_kFmYykm zwD4^8slxHXrqTAvnuZ^FpY)ElPwB6d*dBF$frnKhjn7MkwT>D8{NNBjw9-rSHj?Hh6 z&g+PFxS}<^6MP@L8Z5oo{`RIznQNHVXe&Hy8)nJ~ivX5>&l^^3PCg(K9=iCyT za|_f#d26qkO2&3gm|Buy<7yT*MjO{a+_?7UxDj~L2P{ec9`4SdM`MdI?xMe3-b(+q z#X=ia7&S_g15s7;m0XqbypA?lD_D=pYN0Jxa%r8FFG#bsoRCxn2wp1S8uEWztTg)L zOyyAx-TX+N`R3>)q@ce(T%v?OKkqGF3FceiPir8U$xo~b^w4-yFq1WuKP{M%^Grd~ zO|PwJ?(c!2L&gTV73IV&<#8}>Azc6r&zt4O|q?P{o2mf9m!M? zlY1#_5%tL(v3%1N9Q6`{mk~@0Qo@qmmv1mR%qTb$n`eQ_2QaD(4m$W7C@{lsE{U5e zW2VZusU>ED&?Gx*nG>yF9bK~n?6+A;NsNZawdI(RFoH49Ejih7qT}S|6Pw32j9VK< zHeJd1B{D=LzT7j`7^ak%eCW%uBf_8 z3J;XeD(Ll^n)GxP-M!ZohL9RWNDJ|>It0dD`bnld&Hw9%3MKm{vnf3UNH~1sO^lRW zdxj?%9F!b?q8JK5lpBY6L@jixAm2%U+}aqn>m+;0Ql(|kJ>9*tU^ zh=BQZ4V2jVN-?PQrbQ(@`!zsXf#-V%6xjLRkz4bW_rlPGb@j+5@a$OyabtPRSROal z#Edl;c1MjhCsvHWr)stqUs(g$MovD zGAYNTv?}SZ4;HZ`)AesiGQ9~&rgcg|O`qIbL;v_>F7>a<;2xu&zB!K$JeFb7;$2A4 zJ*Ivf4$o<%oj$t(*~Wh0e=l`gG?;x*(uxPIHb_!s+?1rMNT3Rt!^-`$Xxkm-VL8%+ zJEq)ulnYfS@IV@PxHB2?)|4g_rlEqbxmNjHn46RQs;FGu^_8}IN42k7U_Mq zvThP5l?|Nj>lR(Tp}NSBl&CyxWF-9pCT55YKKCf7=$*pZC@ zuRx+6E+KnE9-lkS{;(8hRzjd;7n{NI9Z%!Hl(%IPn9Pwu7mD7^DY9weCOcHLB3n@0 zK7+#7Q)T62x*zdR^5dq4v_wdFvcz_#?a{Wg+fKEOm&_a8G}*lPrIP1MMmJ6HbFViv z{zU&0|2!YbiZ`u~HLbs_A8*{KQl~ZmLMS%njf&qvZ?0VRqc?FzE@GHS&JPPgRBAMqXm{BZ~zpKUfCxOL}^9 z@rGYx@BcwC4**;YSY(sDL4SsDJ)9~QChnzl#0>FJ2*TgE$p7M9opKM zI}6n55~X8#$_kw3{br@z%;5X5}y-PI@uA zWov=vb7<+0__p4|!E?-1*S%cEUL1(NnjYeF$Z9&daC0> zC*84qHSq8B_8m$-U1BNc=qdVlz=f4g!5=Xbar9>(zgEw7sA@dKKgnVF=vt=-jFlN|sxFjlM z4;00l*dZGzC9vW}8rbaz{V49ErsT#Y=qM~T{V!lj$Wfv5WFvXdMj@Cl8AyanM@pOxe3ANyLQ zGfwTS2A4A9&afkSt4lK$(@s`a{foGf%!J)YBr@3c;9)0`EFsPYzzg1F5^!L43dJdJ zGZ$9=?{r*vBauahN3Y29?!Rzb(Co6OVX_8GYmtDdFW?&p_|axL{Vs5t>#%D*f&~Z` z0swtr2gMSZ%w99g{UZHq|3H{=B&EU*9JCWb7J}UfQX98obr*sP1Zn_q$+!c{g~)LD zzDPmf1EFtFa*zKYEEHZvoq>aHf{&&|1D_!&is|S3{sk=0R99i--#m*s-Cm>^QP7kA zMo6&B=~Z?`0P~26ivO;8)Zf|XL|OVJrPuSPu*W*+Vx4N;FkK zWgYbgo;LL2M0Wy^UKb)Q1Ff8von{BU>&_}$GxnpLfNBrGAIw`Msf z<(Ek&mZnJn##->W!VVQlkU6-AIsj?UO0q8~uuL(qf( zSJX*50fMA3;d~g%qM8XSTlsnH%SwGvAga7>zqGUh=t}c1My#f2Wb7S;?*WjIr~*4e zmN0TZMsl)O)WD}2XSH|HuqTQnY(JWOR?h?`tDt4a#Os_#>GiVd^$2*HeIn&{t_8Xrs)}z1lgiU)L{zI zASa!ePyaU@_GbjlXMEk15cfcUgo0r2gZp{|87?A_O+e-TNX^k#xeO*bD55m{KwjiO zjy0>=(RqpnZ=jDoY@&0j0sJBBM!Ch-wgwW$cMf_8#DJJ)Vuv|oZu7H8Y+GU^nMa52 zsfJH&#_n0bJx%}Vo)u}EC%9s!8cf(Ka87kc&u1jTtx51h4eY#9D9{JshR?HWltc6r*dvG)G~p`reFTz>lzqv z`vqwZ&eIAtTI){{V&&1a)r)!_vB`}LE8YIzS z$w%VAK>`4g8=S#mAwT6uGHDbU0Njrw*Z-cX%TS{1N-+bCj@J#zQYhl{IHXQNxaf(8 zDlADk61DKzLonbcjr7fj))X)gg_f%`;jRwiLV~p7c!Tz7+)X#_Io=T7hOM^&faEP+ zs3r5jq>PbZ+hy{`Sj>bg40xhNUWp{^^4u8JfsIV85kJ959tAjOsa+buGH&1Bj8ifV z-i`~|fdCJ~F1=@v53xUv;4rj`aA$>2JPyM31jR2%?tsRd(z|r?i2}_qw5lTB6Yr|G zCWS}T-#O^=!?z?y*o~a2CaDF)lqO0tYsWSwD+_R1bok^21WE+U>HXhb!mXme{O;T| z>D!NE7^kMmA@lcadr3A(Z<0*lP#;9C8?`n_P9S+UFUlHxsx-}G9K$)#Z4me(SV2}P z+5p~zMJ8cxC7rSW zH*hU<+2dq!O1d0~kqU~K8)8(aF^N&{qQ8B-q4WTd2d^~fBdB_e*P4_!U zhp@ei2A-%b+XM8)9Nc#z9V@HWV}R2g`Nd;L}J)>bgneE}lO zY_Q3<=`Byya39g$ry9bjN#Iw&&L&=myOD+^MZ+Hm+4cqo!O|pEt<#<>nQ*3NOm1c& zOSU7iEJjRvzW|Mw_@817Gel3p9HJ2rd6#p5cmiNYkB}eGqNi7enUSBSOR^(;9Jlxc zf-xMQ0l|^9PlEI$UHZBkL^dW?9 zeV@7kXA^ni#<0{0On?-5lE>spoG@v+fTNE*+s$}M;FEb^s633>2xKUE8bKNZv%isn zi~{)q@-xM?=W+OR2#`Ob5$$_2+L4U=_N~~RGC*=1&X~qVp2vP>a5O-J=@{9A)R?5n zD^5HJM*#Vm$V=x`S}k6o!B}5>zSNMuEB&;=&759jW0C(7MPYn`V*@+0wFQeubod4$BbD2R$K| z*BSKm`-4(afO39ySJkQCKEu#t{=*hlkD<1 zQMX0PT@oZfK0_+{t#Sw<>b6O*e?Sd{mv04m2U~4hgRh9)xT*`#Zm$wmeZhmGLD=u| z_Xi-c9~vOIAGn)A2qj$^lhVqpkf=Qbwj4fU)k}Zj!+GXTnTqeip(6{{Fp& zoQH8YMkylsJ)#5ef2DRKbNOhz>rX4D7F@5m~4a5c|R{ z%L#lUe}bX6M^3;0wh}JDLTt6t!7?;kkm6PZN}%(ZfV1QQfYb%MOtwImXiQ#Mn5f*2 z=)17PBnLfSw=)QrA-7~{3m%>*Y{JBf-9##oAYds=9)V$Noq@4BGjAPj3 zOxs~oIwlT~jX86*Py_!9NAW`B=T|pzYOd4nq=pYGX!C~_1K=s7_faj~{9)A`3{42y zRWVCeDEuEI#M3J!g#LiDu=N<|;~y3;;LIK8 z8gD2~oDO@NWE7}QRVl(q+{$f95Xa(F6PvP(+mvX<;?(NIN;W5&&D`d+l{AiXO`j{v zq*b{|7jyG1UM7 diff --git a/blood_bank/models.py b/blood_bank/models.py index bc0abfc0..9081ba94 100644 --- a/blood_bank/models.py +++ b/blood_bank/models.py @@ -3,7 +3,7 @@ from django.db import models from django.core.validators import MinValueValidator, MaxValueValidator from django.utils import timezone from datetime import timedelta -from core.models import Department +from hr.models import Department from patients.models import PatientProfile from accounts.models import User diff --git a/blood_bank/urls.py b/blood_bank/urls.py index 98fa7f5f..fa45fd9e 100644 --- a/blood_bank/urls.py +++ b/blood_bank/urls.py @@ -9,25 +9,25 @@ urlpatterns = [ # Donor Management path('donors/', views.DonorListView.as_view(), name='donor_list'), - path('donors//', views.donor_detail, name='donor_detail'), - path('donors/create/', views.donor_create, name='donor_create'), - path('donors//update/', views.donor_update, name='donor_update'), + path('donors//', views.DonorDetailView.as_view(), name='donor_detail'), + path('donors/create/', views.DonorCreateView.as_view(), name='donor_create'), + path('donors//update/', views.DonorUpdateView.as_view(), name='donor_update'), path('donors//eligibility/', views.donor_eligibility_check, name='donor_eligibility'), # Blood Unit Management - path('units/', views.blood_unit_list, name='blood_unit_list'), - path('units//', views.blood_unit_detail, name='blood_unit_detail'), - path('units/create/', views.blood_unit_create, name='blood_unit_create'), - path('units/create//', views.blood_unit_create, name='blood_unit_create_for_donor'), + path('units/', views.BloodUnitListView.as_view(), name='blood_unit_list'), + path('units//', views.BloodUnitDetailView.as_view(), name='blood_unit_detail'), + path('units/create/', views.BloodUnitCreateView.as_view(), name='blood_unit_create'), + path('units/create//', views.BloodUnitCreateView.as_view(), name='blood_unit_create_for_donor'), # Blood Testing path('units//test/', views.blood_test_create, name='blood_test_create'), path('units//crossmatch//', views.crossmatch_create, name='crossmatch_create'), # Blood Requests - path('requests/', views.blood_request_list, name='blood_request_list'), - path('requests//', views.blood_request_detail, name='blood_request_detail'), - path('requests/create/', views.blood_request_create, name='blood_request_create'), + path('requests/', views.BloodRequestListView.as_view(), name='blood_request_list'), + path('requests//', views.BloodRequestDetailView.as_view(), name='blood_request_detail'), + path('requests/create/', views.BloodRequestCreateView.as_view(), name='blood_request_create'), # Blood Issue and Transfusion path('requests//issue/', views.blood_issue_create, name='blood_issue_create'), diff --git a/blood_bank/views.py b/blood_bank/views.py index d40f1ba9..3303210e 100644 --- a/blood_bank/views.py +++ b/blood_bank/views.py @@ -1,4 +1,4 @@ -from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import login_required, permission_required from django.contrib import messages @@ -11,7 +11,7 @@ from django.contrib.auth.models import User from datetime import timedelta import json -from django.views.generic import ListView +from django.views.generic import ListView, CreateView, DetailView, DeleteView, UpdateView from .models import ( BloodGroup, Donor, BloodComponent, BloodUnit, BloodTest, CrossMatch, @@ -52,9 +52,7 @@ def dashboard(request): context['blood_group_stats'] = blood_group_stats # Recent activities - context['recent_units'] = BloodUnit.objects.select_related( - 'donor', 'component', 'blood_group' - ).order_by('-collection_date')[:10] + context['recent_units'] = BloodUnit.objects.select_related('donor', 'component', 'blood_group').order_by('-collection_date') context['urgent_requests'] = BloodRequest.objects.filter( urgency='emergency', status__in=['pending', 'processing'] @@ -110,62 +108,65 @@ class DonorListView(LoginRequiredMixin, ListView): -@login_required -def donor_detail(request, donor_id): - """Donor detail view with donation history""" - donor = get_object_or_404(Donor, id=donor_id) +class DonorDetailView(LoginRequiredMixin, DetailView): + model = Donor + template_name = 'blood_bank/donors/donor_detail.html' + context_object_name = 'donor' + pk_url_kwarg = 'donor_id' - # Get donation history - blood_units = BloodUnit.objects.filter(donor=donor).select_related( - 'component', 'blood_group' - ).order_by('-collection_date') - - context = { - 'donor': donor, - 'blood_units': blood_units, - 'total_donations': blood_units.count(), - 'last_donation': blood_units.first(), - } - - return render(request, 'blood_bank/donors/donor_detail.html', context) + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + donor = self.object + blood_units = ( + BloodUnit.objects + .filter(donor=donor) + .select_related('component', 'blood_group') + .order_by('-collection_date') + ) + ctx.update({ + 'blood_units': blood_units, + 'total_donations': blood_units.count(), + 'last_donation': blood_units.first(), + }) + return ctx -@login_required -@permission_required('blood_bank.add_donor') -def donor_create(request): - """Create new donor""" - if request.method == 'POST': - form = DonorForm(request.POST) - if form.is_valid(): - donor = form.save(commit=False) - donor.created_by = request.user - donor.save() - messages.success(request, f'Donor {donor.donor_id} created successfully.') - return redirect('blood_bank:donor_detail', donor_id=donor.id) - else: - form = DonorForm() +class DonorCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): + model = Donor + form_class = DonorForm + template_name = 'blood_bank/donors/donor_form.html' + permission_required = 'blood_bank.add_donor' - return render(request, 'blood_bank/donors/donor_form.html', {'form': form, 'title': 'Add New Donor'}) + def form_valid(self, form): + donor = form.save(commit=False) + donor.created_by = self.request.user + donor.save() + messages.success(self.request, f'Donor {donor.donor_id} created successfully.') + return redirect('blood_bank:donor_detail', donor_id=donor.id) + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + ctx['title'] = 'Add New Donor' + return ctx -@login_required -@permission_required('blood_bank.change_donor') -def donor_update(request, donor_id): - """Update donor information""" - donor = get_object_or_404(Donor, id=donor_id) +class DonorUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView): + model = Donor + form_class = DonorForm + template_name = 'blood_bank/donors/donor_form.html' + permission_required = 'blood_bank.change_donor' + pk_url_kwarg = 'donor_id' + context_object_name = 'donor' - if request.method == 'POST': - form = DonorForm(request.POST, instance=donor) - if form.is_valid(): - form.save() - messages.success(request, f'Donor {donor.donor_id} updated successfully.') - return redirect('blood_bank:donor_detail', donor_id=donor.id) - else: - form = DonorForm(instance=donor) + def form_valid(self, form): + donor = form.save() + messages.success(self.request, f'Donor {donor.donor_id} updated successfully.') + return redirect('blood_bank:donor_detail', donor_id=donor.id) - return render(request, 'blood_bank/donors/donor_form.html', { - 'form': form, 'donor': donor, 'title': 'Update Donor' - }) + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + ctx['title'] = 'Update Donor' + return ctx @login_required @@ -192,167 +193,163 @@ def donor_eligibility_check(request, donor_id): return render(request, 'blood_bank/donors/donor_eligibility.html', context) -# Blood Unit Management Views -@login_required -def blood_unit_list(request): - """List all blood units with filtering""" - form = BloodInventorySearchForm(request.GET) - blood_units = BloodUnit.objects.select_related( - 'donor', 'component', 'blood_group' - ).order_by('-collection_date') +class BloodUnitListView(LoginRequiredMixin, ListView): + model = BloodUnit + template_name = 'blood_bank/units/blood_unit_list.html' + context_object_name = 'blood_units' # you'll still get page_obj automatically + paginate_by = 25 - if form.is_valid(): - if form.cleaned_data['blood_group']: - blood_units = blood_units.filter(blood_group=form.cleaned_data['blood_group']) + def get_queryset(self): + # base queryset + qs = BloodUnit.objects.select_related('donor', 'component', 'blood_group') \ + .order_by('-collection_date') - if form.cleaned_data['component']: - blood_units = blood_units.filter(component=form.cleaned_data['component']) + # bind/validate the filter form + self.form = BloodInventorySearchForm(self.request.GET) + if self.form.is_valid(): + cd = self.form.cleaned_data - if form.cleaned_data['status']: - blood_units = blood_units.filter(status=form.cleaned_data['status']) + if cd.get('blood_group'): + qs = qs.filter(blood_group=cd['blood_group']) - if form.cleaned_data['expiry_days']: - expiry_date = timezone.now() + timedelta(days=form.cleaned_data['expiry_days']) - blood_units = blood_units.filter(expiry_date__lte=expiry_date) + if cd.get('component'): + qs = qs.filter(component=cd['component']) - paginator = Paginator(blood_units, 25) - page_number = request.GET.get('page') - page_obj = paginator.get_page(page_number) + if cd.get('status'): + qs = qs.filter(status=cd['status']) - context = { - 'page_obj': page_obj, - 'form': form, - } + if cd.get('expiry_days') is not None: + expiry_date = timezone.now() + timedelta(days=cd['expiry_days']) + qs = qs.filter(expiry_date__lte=expiry_date) - return render(request, 'blood_bank/units/blood_unit_list.html', context) + return qs + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + # expose the (bound) form to the template + ctx['form'] = getattr(self, 'form', BloodInventorySearchForm(self.request.GET)) + return ctx -@login_required -def blood_unit_detail(request, unit_id): - """Blood unit detail view with test results""" - blood_unit = get_object_or_404(BloodUnit, id=unit_id) +class BloodUnitDetailView(LoginRequiredMixin, DetailView): + model = BloodUnit + template_name = 'blood_bank/units/blood_unit_detail.html' + context_object_name = 'blood_unit' + pk_url_kwarg = 'unit_id' - # Get test results - tests = BloodTest.objects.filter(blood_unit=blood_unit).select_related('tested_by') - crossmatches = CrossMatch.objects.filter(blood_unit=blood_unit).select_related( - 'recipient', 'tested_by' - ) + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + blood_unit = self.object - context = { - 'blood_unit': blood_unit, - 'tests': tests, - 'crossmatches': crossmatches, - } - - return render(request, 'blood_bank/units/blood_unit_detail.html', context) + # related objects + ctx['tests'] = BloodTest.objects.filter(blood_unit=blood_unit) \ + .select_related('tested_by') + ctx['crossmatches'] = CrossMatch.objects.filter(blood_unit=blood_unit) \ + .select_related('recipient', 'tested_by') + return ctx -@login_required -@permission_required('blood_bank.add_bloodunit') -def blood_unit_create(request, donor_id=None): - """Create new blood unit""" - donor = None - if donor_id: - donor = get_object_or_404(Donor, id=donor_id) +class BloodUnitCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): + model = BloodUnit + form_class = BloodUnitForm + template_name = 'blood_bank/units/blood_unit_form.html' + permission_required = 'blood_bank.add_bloodunit' - if request.method == 'POST': - form = BloodUnitForm(request.POST) - if form.is_valid(): - blood_unit = form.save(commit=False) - blood_unit.collected_by = request.user - blood_unit.save() + def get_initial(self): + initial = super().get_initial() + donor_id = self.kwargs.get('donor_id') + if donor_id: + donor = get_object_or_404(Donor, id=donor_id) + initial['donor'] = donor + initial['blood_group'] = donor.blood_group + self.donor = donor # store for use in context + return initial - # Update donor's last donation date and total donations - if blood_unit.donor: - blood_unit.donor.last_donation_date = blood_unit.collection_date - blood_unit.donor.total_donations += 1 - blood_unit.donor.save() + def form_valid(self, form): + blood_unit = form.save(commit=False) + blood_unit.collected_by = self.request.user + blood_unit.save() - messages.success(request, f'Blood unit {blood_unit.unit_number} created successfully.') - return redirect('blood_bank:blood_unit_detail', unit_id=blood_unit.id) - else: - initial_data = {} - if donor: - initial_data['donor'] = donor - initial_data['blood_group'] = donor.blood_group - form = BloodUnitForm(initial=initial_data) + # Update donor’s donation stats + if blood_unit.donor: + blood_unit.donor.last_donation_date = blood_unit.collection_date + blood_unit.donor.total_donations += 1 + blood_unit.donor.save() - return render(request, 'blood_bank/units/blood_unit_form.html', { - 'form': form, 'donor': donor, 'title': 'Register Blood Unit' - }) + messages.success(self.request, f'Blood unit {blood_unit.unit_number} created successfully.') + return redirect('blood_bank:blood_unit_detail', unit_id=blood_unit.id) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['donor'] = getattr(self, 'donor', None) + context['title'] = 'Register Blood Unit' + return context -# Blood Request Management Views -@login_required -def blood_request_list(request): - """List all blood requests""" - requests = BloodRequest.objects.select_related( - 'patient', 'requesting_department', 'requesting_physician', 'component_requested' - ).order_by('-request_date') +class BloodRequestListView(LoginRequiredMixin, ListView): + model = BloodRequest + template_name = 'blood_bank/requests/blood_request_list.html' + context_object_name = 'page_obj' + paginate_by = 25 - # Filter by status - status_filter = request.GET.get('status') - if status_filter: - requests = requests.filter(status=status_filter) + def get_queryset(self): + qs = BloodRequest.objects.select_related( + 'patient', 'requesting_department', 'requesting_physician', 'component_requested' + ).order_by('-request_date') - # Filter by urgency - urgency_filter = request.GET.get('urgency') - if urgency_filter: - requests = requests.filter(urgency=urgency_filter) + status_filter = self.request.GET.get('status') + urgency_filter = self.request.GET.get('urgency') - paginator = Paginator(requests, 25) - page_number = request.GET.get('page') - page_obj = paginator.get_page(page_number) + if status_filter: + qs = qs.filter(status=status_filter) + if urgency_filter: + qs = qs.filter(urgency=urgency_filter) - context = { - 'page_obj': page_obj, - 'status_choices': BloodRequest.STATUS_CHOICES, - 'urgency_choices': BloodRequest.URGENCY_CHOICES, - 'status_filter': status_filter, - 'urgency_filter': urgency_filter, - } + return qs - return render(request, 'blood_bank/requests/blood_request_list.html', context) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['status_choices'] = BloodRequest.STATUS_CHOICES + context['urgency_choices'] = BloodRequest.URGENCY_CHOICES + context['status_filter'] = self.request.GET.get('status') + context['urgency_filter'] = self.request.GET.get('urgency') + return context -@login_required -def blood_request_detail(request, request_id): - """Blood request detail view""" - blood_request = get_object_or_404(BloodRequest, id=request_id) +class BloodRequestDetailView(LoginRequiredMixin, DetailView): + model = BloodRequest + pk_url_kwarg = 'request_id' + template_name = 'blood_bank/requests/blood_request_detail.html' + context_object_name = 'blood_request' - # Get issued units for this request - issues = BloodIssue.objects.filter(blood_request=blood_request).select_related( - 'blood_unit', 'issued_by', 'issued_to' - ) - - context = { - 'blood_request': blood_request, - 'issues': issues, - } - - return render(request, 'blood_bank/requests/blood_request_detail.html', context) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['issues'] = BloodIssue.objects.filter( + blood_request=self.object + ).select_related('blood_unit', 'issued_by', 'issued_to') + return context -@login_required -@permission_required('blood_bank.add_bloodrequest') -def blood_request_create(request): - """Create new blood request""" - if request.method == 'POST': - form = BloodRequestForm(request.POST) - if form.is_valid(): - blood_request = form.save(commit=False) - blood_request.requesting_physician = request.user - # Generate request number - blood_request.request_number = f"BR{timezone.now().strftime('%Y%m%d')}{BloodRequest.objects.count() + 1:04d}" - blood_request.save() - messages.success(request, f'Blood request {blood_request.request_number} created successfully.') - return redirect('blood_bank:blood_request_detail', request_id=blood_request.id) - else: - form = BloodRequestForm() +class BloodRequestCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView): + model = BloodRequest + form_class = BloodRequestForm + template_name = 'blood_bank/requests/blood_request_form.html' + permission_required = 'blood_bank.add_bloodrequest' - return render(request, 'blood_bank/requests/blood_request_form.html', { - 'form': form, 'title': 'Create Blood Request' - }) + def form_valid(self, form): + blood_request = form.save(commit=False) + blood_request.requesting_physician = self.request.user + # Generate request number + blood_request.request_number = f"BR{timezone.now().strftime('%Y%m%d')}{BloodRequest.objects.count() + 1:04d}" + blood_request.save() + + messages.success(self.request, f'Blood request {blood_request.request_number} created successfully.') + return redirect('blood_bank:blood_request_detail', request_id=blood_request.id) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['title'] = 'Create Blood Request' + return context # Blood Issue and Transfusion Views diff --git a/communications/__pycache__/flows.cpython-312.pyc b/communications/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..620ed170ab3acd075620411edd16018f3997b3c1 GIT binary patch literal 184 zcmX@j%ge<81bQ<2GCDgM7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@Ts{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqMw|fn_HTfnVeXXnV(mzpO%wfUaVJ8d5gm)H$SB`C)KWq6=)A55Ep|OADI~$8H<>K FEC41HGcf=F literal 0 HcmV?d00001 diff --git a/communications/flows.py b/communications/flows.py new file mode 100644 index 00000000..fc077c27 --- /dev/null +++ b/communications/flows.py @@ -0,0 +1,1046 @@ +# """ +# Viewflow workflows for communications app. +# Provides message routing, notification delivery, and alert management 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 Message, MessageRecipient, NotificationTemplate, AlertRule, AlertInstance +# from .views import ( +# MessageCompositionView, RecipientSelectionView, MessageDeliveryView, +# NotificationCreationView, TemplateSelectionView, AlertConfigurationView, +# AlertEvaluationView, EscalationView, AcknowledgmentView, ResolutionView +# ) +# +# +# class MessageDeliveryProcess(Process): +# """ +# Viewflow process model for message delivery +# """ +# message = ModelField(Message, help_text='Associated message') +# +# # Process status tracking +# message_composed = models.BooleanField(default=False) +# recipients_selected = models.BooleanField(default=False) +# content_validated = models.BooleanField(default=False) +# delivery_scheduled = models.BooleanField(default=False) +# message_sent = models.BooleanField(default=False) +# delivery_confirmed = models.BooleanField(default=False) +# acknowledgments_received = models.BooleanField(default=False) +# delivery_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Message Delivery Process' +# verbose_name_plural = 'Message Delivery Processes' +# +# +# class MessageDeliveryFlow(Flow): +# """ +# Message Delivery Workflow +# +# This flow manages message composition, recipient selection, +# delivery, and acknowledgment tracking. +# """ +# +# process_class = MessageDeliveryProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_message_delivery) +# .Next(this.compose_message) +# ) +# +# compose_message = ( +# flow_view(MessageCompositionView) +# .Permission('communications.can_compose_messages') +# .Next(this.select_recipients) +# ) +# +# select_recipients = ( +# flow_view(RecipientSelectionView) +# .Permission('communications.can_select_recipients') +# .Next(this.validate_content) +# ) +# +# validate_content = ( +# flow_func(this.perform_content_validation) +# .Next(this.schedule_delivery) +# ) +# +# schedule_delivery = ( +# flow_func(this.setup_delivery_schedule) +# .Next(this.send_message) +# ) +# +# send_message = ( +# flow_view(MessageDeliveryView) +# .Permission('communications.can_send_messages') +# .Next(this.confirm_delivery) +# ) +# +# confirm_delivery = ( +# flow_func(this.track_delivery_status) +# .Next(this.collect_acknowledgments) +# ) +# +# collect_acknowledgments = ( +# flow_func(this.monitor_acknowledgments) +# .Next(this.complete_delivery) +# ) +# +# complete_delivery = ( +# flow_func(this.finalize_message_delivery) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_message_delivery) +# +# # Flow functions +# def start_message_delivery(self, activation): +# """Initialize the message delivery process""" +# process = activation.process +# message = process.message +# +# # Update message status +# message.status = 'DRAFT' +# message.save() +# +# # Send notification to communications staff +# self.notify_message_creation(message) +# +# # Check for urgent messages +# if message.priority in ['URGENT', 'CRITICAL'] or message.is_urgent: +# self.notify_urgent_message(message) +# +# def perform_content_validation(self, activation): +# """Validate message content and compliance""" +# process = activation.process +# message = process.message +# +# # Perform content validation +# validation_results = self.validate_message_content(message) +# +# if validation_results['is_valid']: +# process.content_validated = True +# process.save() +# else: +# # Handle validation failures +# self.handle_validation_failure(message, validation_results) +# +# def setup_delivery_schedule(self, activation): +# """Setup message delivery schedule""" +# process = activation.process +# message = process.message +# +# # Set delivery schedule +# if message.scheduled_at: +# # Message is scheduled for future delivery +# self.schedule_future_delivery(message) +# else: +# # Immediate delivery +# message.scheduled_at = timezone.now() +# message.save() +# +# # Mark delivery scheduled +# process.delivery_scheduled = True +# process.save() +# +# def track_delivery_status(self, activation): +# """Track message delivery status""" +# process = activation.process +# message = process.message +# +# # Update message status +# message.status = 'SENT' +# message.sent_at = timezone.now() +# message.save() +# +# # Mark message sent +# process.message_sent = True +# process.save() +# +# # Start delivery tracking +# self.start_delivery_tracking(message) +# +# def monitor_acknowledgments(self, activation): +# """Monitor message acknowledgments""" +# process = activation.process +# message = process.message +# +# if message.requires_acknowledgment: +# # Check acknowledgment status +# acknowledgment_status = self.check_acknowledgment_status(message) +# +# if acknowledgment_status['all_acknowledged']: +# process.acknowledgments_received = True +# process.save() +# else: +# # Send reminders for unacknowledged messages +# self.send_acknowledgment_reminders(message) +# else: +# # No acknowledgment required +# process.acknowledgments_received = True +# process.save() +# +# def finalize_message_delivery(self, activation): +# """Finalize the message delivery process""" +# process = activation.process +# message = process.message +# +# # Update message status +# message.status = 'DELIVERED' +# message.save() +# +# # Mark process as completed +# process.delivery_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_delivery_completion(message) +# +# # Update delivery metrics +# self.update_delivery_metrics(message) +# +# def end_message_delivery(self, activation): +# """End the message delivery workflow""" +# process = activation.process +# +# # Generate delivery summary report +# self.generate_delivery_summary(process.message) +# +# # Helper methods +# def notify_message_creation(self, message): +# """Notify communications staff of new message""" +# from django.contrib.auth.models import Group +# +# communications_staff = User.objects.filter( +# groups__name='Communications Staff' +# ) +# +# for staff in communications_staff: +# send_mail( +# subject=f'New Message Created: {message.subject}', +# message=f'New {message.get_message_type_display()} message created by {message.sender.get_full_name()}.', +# from_email='communications@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_urgent_message(self, message): +# """Notify of urgent message""" +# communications_managers = User.objects.filter( +# groups__name='Communications Managers' +# ) +# +# for manager in communications_managers: +# send_mail( +# subject=f'URGENT Message: {message.subject}', +# message=f'{message.get_priority_display()} message requires immediate attention.', +# from_email='communications@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def validate_message_content(self, message): +# """Validate message content for compliance and quality""" +# validation_results = { +# 'is_valid': True, +# 'errors': [], +# 'warnings': [] +# } +# +# # Content validation logic would go here +# # Check for compliance, appropriate language, etc. +# +# return validation_results +# +# def handle_validation_failure(self, message, validation_results): +# """Handle message validation failures""" +# # This would handle validation failures +# pass +# +# def schedule_future_delivery(self, message): +# """Schedule message for future delivery""" +# # Schedule delivery task +# send_scheduled_message.apply_async( +# args=[message.message_id], +# eta=message.scheduled_at +# ) +# +# def start_delivery_tracking(self, message): +# """Start tracking message delivery""" +# # This would start delivery tracking for all recipients +# pass +# +# def check_acknowledgment_status(self, message): +# """Check acknowledgment status for all recipients""" +# recipients = message.recipients.all() +# total_recipients = recipients.count() +# acknowledged_recipients = recipients.filter(status='ACKNOWLEDGED').count() +# +# return { +# 'all_acknowledged': acknowledged_recipients == total_recipients, +# 'acknowledgment_rate': acknowledged_recipients / total_recipients if total_recipients > 0 else 0 +# } +# +# def send_acknowledgment_reminders(self, message): +# """Send reminders for unacknowledged messages""" +# unacknowledged_recipients = message.recipients.filter( +# status__in=['DELIVERED', 'READ'] +# ) +# +# for recipient in unacknowledged_recipients: +# self.send_acknowledgment_reminder(recipient) +# +# def send_acknowledgment_reminder(self, recipient): +# """Send acknowledgment reminder to specific recipient""" +# # This would send reminder to recipient +# pass +# +# def notify_delivery_completion(self, message): +# """Notify delivery completion""" +# # Notify sender +# if message.sender and message.sender.email: +# send_mail( +# subject=f'Message Delivered: {message.subject}', +# message=f'Your message has been successfully delivered to all recipients.', +# from_email='communications@hospital.com', +# recipient_list=[message.sender.email], +# fail_silently=True +# ) +# +# def update_delivery_metrics(self, message): +# """Update message delivery metrics""" +# # This would update delivery performance metrics +# pass +# +# def generate_delivery_summary(self, message): +# """Generate message delivery summary""" +# # This would generate comprehensive delivery report +# pass +# +# +# class NotificationManagementProcess(Process): +# """ +# Viewflow process model for notification management +# """ +# notification_template = ModelField(NotificationTemplate, help_text='Associated notification template') +# +# # Process status tracking +# template_selected = models.BooleanField(default=False) +# content_generated = models.BooleanField(default=False) +# recipients_determined = models.BooleanField(default=False) +# notifications_created = models.BooleanField(default=False) +# delivery_initiated = models.BooleanField(default=False) +# delivery_monitored = models.BooleanField(default=False) +# notifications_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Notification Management Process' +# verbose_name_plural = 'Notification Management Processes' +# +# +# class NotificationManagementFlow(Flow): +# """ +# Notification Management Workflow +# +# This flow manages automated notification generation, +# delivery, and tracking using templates. +# """ +# +# process_class = NotificationManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_notification_management) +# .Next(this.select_template) +# ) +# +# select_template = ( +# flow_view(TemplateSelectionView) +# .Permission('communications.can_select_templates') +# .Next(this.generate_content) +# ) +# +# generate_content = ( +# flow_func(this.create_notification_content) +# .Next(this.determine_recipients) +# ) +# +# determine_recipients = ( +# flow_func(this.identify_notification_recipients) +# .Next(this.create_notifications) +# ) +# +# create_notifications = ( +# flow_view(NotificationCreationView) +# .Permission('communications.can_create_notifications') +# .Next(this.initiate_delivery) +# ) +# +# initiate_delivery = ( +# flow_func(this.start_notification_delivery) +# .Next(this.monitor_delivery) +# ) +# +# monitor_delivery = ( +# flow_func(this.track_notification_delivery) +# .Next(this.complete_notifications) +# ) +# +# complete_notifications = ( +# flow_func(this.finalize_notification_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_notification_management) +# +# # Flow functions +# def start_notification_management(self, activation): +# """Initialize the notification management process""" +# process = activation.process +# template = process.notification_template +# +# # Send notification to communications staff +# self.notify_notification_triggered(template) +# +# def create_notification_content(self, activation): +# """Generate notification content from template""" +# process = activation.process +# template = process.notification_template +# +# # Generate content using template +# content = self.generate_template_content(template) +# +# # Mark content generated +# process.content_generated = True +# process.save() +# +# # Store generated content +# self.store_generated_content(template, content) +# +# def identify_notification_recipients(self, activation): +# """Identify notification recipients""" +# process = activation.process +# template = process.notification_template +# +# # Determine recipients based on template configuration +# recipients = self.determine_template_recipients(template) +# +# # Mark recipients determined +# process.recipients_determined = True +# process.save() +# +# # Store recipient list +# self.store_recipient_list(template, recipients) +# +# def start_notification_delivery(self, activation): +# """Start notification delivery""" +# process = activation.process +# template = process.notification_template +# +# # Initiate delivery for all notifications +# self.initiate_template_delivery(template) +# +# # Mark delivery initiated +# process.delivery_initiated = True +# process.save() +# +# def track_notification_delivery(self, activation): +# """Track notification delivery progress""" +# process = activation.process +# template = process.notification_template +# +# # Monitor delivery status +# delivery_status = self.monitor_template_delivery(template) +# +# if delivery_status['all_delivered']: +# process.delivery_monitored = True +# process.save() +# else: +# # Continue monitoring +# self.schedule_delivery_monitoring(template) +# +# def finalize_notification_management(self, activation): +# """Finalize the notification management process""" +# process = activation.process +# template = process.notification_template +# +# # Mark process as completed +# process.notifications_completed = True +# process.save() +# +# # Update template usage statistics +# self.update_template_usage(template) +# +# # Send completion notifications +# self.notify_notification_completion(template) +# +# def end_notification_management(self, activation): +# """End the notification management workflow""" +# process = activation.process +# +# # Generate notification summary +# self.generate_notification_summary(process.notification_template) +# +# # Helper methods +# def notify_notification_triggered(self, template): +# """Notify communications staff of triggered notification""" +# communications_staff = User.objects.filter( +# groups__name='Communications Staff' +# ) +# +# for staff in communications_staff: +# send_mail( +# subject=f'Notification Triggered: {template.name}', +# message=f'Automated notification "{template.name}" has been triggered.', +# from_email='notifications@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_template_content(self, template): +# """Generate content from notification template""" +# # This would implement template rendering logic +# return { +# 'subject': template.subject_template, +# 'content': template.content_template +# } +# +# def store_generated_content(self, template, content): +# """Store generated notification content""" +# # This would store the generated content +# pass +# +# def determine_template_recipients(self, template): +# """Determine recipients for template notifications""" +# # This would implement recipient determination logic +# return [] +# +# def store_recipient_list(self, template, recipients): +# """Store recipient list for template""" +# # This would store the recipient list +# pass +# +# def initiate_template_delivery(self, template): +# """Initiate delivery for template notifications""" +# # This would start delivery for all notifications +# pass +# +# def monitor_template_delivery(self, template): +# """Monitor template notification delivery""" +# # This would monitor delivery progress +# return {'all_delivered': True} +# +# def schedule_delivery_monitoring(self, template): +# """Schedule continued delivery monitoring""" +# # This would schedule monitoring tasks +# pass +# +# def update_template_usage(self, template): +# """Update template usage statistics""" +# template.usage_count += 1 +# template.last_used_at = timezone.now() +# template.save() +# +# def notify_notification_completion(self, template): +# """Notify notification completion""" +# # This would notify relevant parties +# pass +# +# def generate_notification_summary(self, template): +# """Generate notification summary""" +# # This would generate notification summary +# pass +# +# +# class AlertManagementProcess(Process): +# """ +# Viewflow process model for alert management +# """ +# alert_instance = ModelField(AlertInstance, help_text='Associated alert instance') +# +# # Process status tracking +# alert_triggered = models.BooleanField(default=False) +# alert_evaluated = models.BooleanField(default=False) +# notifications_sent = models.BooleanField(default=False) +# acknowledgment_received = models.BooleanField(default=False) +# escalation_processed = models.BooleanField(default=False) +# resolution_completed = models.BooleanField(default=False) +# alert_closed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Alert Management Process' +# verbose_name_plural = 'Alert Management Processes' +# +# +# class AlertManagementFlow(Flow): +# """ +# Alert Management Workflow +# +# This flow manages alert lifecycle from trigger through +# acknowledgment, escalation, and resolution. +# """ +# +# process_class = AlertManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_alert_management) +# .Next(this.trigger_alert) +# ) +# +# trigger_alert = ( +# flow_func(this.process_alert_trigger) +# .Next(this.evaluate_alert) +# ) +# +# evaluate_alert = ( +# flow_view(AlertEvaluationView) +# .Permission('communications.can_evaluate_alerts') +# .Next(this.send_notifications) +# ) +# +# send_notifications = ( +# flow_func(this.dispatch_alert_notifications) +# .Next(this.await_acknowledgment) +# ) +# +# await_acknowledgment = ( +# flow_view(AcknowledgmentView) +# .Permission('communications.can_acknowledge_alerts') +# .Next(this.process_escalation) +# ) +# +# process_escalation = ( +# flow_view(EscalationView) +# .Permission('communications.can_escalate_alerts') +# .Next(this.resolve_alert) +# ) +# +# resolve_alert = ( +# flow_view(ResolutionView) +# .Permission('communications.can_resolve_alerts') +# .Next(this.close_alert) +# ) +# +# close_alert = ( +# flow_func(this.finalize_alert_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_alert_management) +# +# # Flow functions +# def start_alert_management(self, activation): +# """Initialize the alert management process""" +# process = activation.process +# alert = process.alert_instance +# +# # Update alert status +# alert.status = 'ACTIVE' +# alert.save() +# +# # Send immediate notifications for critical alerts +# if alert.severity in ['CRITICAL', 'EMERGENCY']: +# self.send_immediate_notifications(alert) +# +# def process_alert_trigger(self, activation): +# """Process alert trigger conditions""" +# process = activation.process +# alert = process.alert_instance +# +# # Mark alert as triggered +# process.alert_triggered = True +# process.save() +# +# # Log alert trigger +# self.log_alert_trigger(alert) +# +# # Check for duplicate alerts +# self.check_duplicate_alerts(alert) +# +# def dispatch_alert_notifications(self, activation): +# """Dispatch alert notifications""" +# process = activation.process +# alert = process.alert_instance +# +# # Send notifications to configured recipients +# self.send_alert_notifications(alert) +# +# # Mark notifications sent +# process.notifications_sent = True +# process.save() +# +# # Schedule escalation if no acknowledgment +# self.schedule_escalation(alert) +# +# def finalize_alert_management(self, activation): +# """Finalize the alert management process""" +# process = activation.process +# alert = process.alert_instance +# +# # Update alert status +# alert.status = 'RESOLVED' +# alert.resolved_at = timezone.now() +# alert.save() +# +# # Mark process as completed +# process.alert_closed = True +# process.save() +# +# # Send resolution notifications +# self.notify_alert_resolution(alert) +# +# # Update alert metrics +# self.update_alert_metrics(alert) +# +# def end_alert_management(self, activation): +# """End the alert management workflow""" +# process = activation.process +# +# # Generate alert summary +# self.generate_alert_summary(process.alert_instance) +# +# # Helper methods +# def send_immediate_notifications(self, alert): +# """Send immediate notifications for critical alerts""" +# # This would send immediate notifications +# pass +# +# def log_alert_trigger(self, alert): +# """Log alert trigger event""" +# # This would log the alert trigger +# pass +# +# def check_duplicate_alerts(self, alert): +# """Check for duplicate alerts""" +# # This would check for and handle duplicate alerts +# pass +# +# def send_alert_notifications(self, alert): +# """Send alert notifications to recipients""" +# rule = alert.alert_rule +# +# # Send to default recipients +# for recipient in rule.default_recipients.all(): +# self.send_alert_to_recipient(alert, recipient) +# +# # Send to role-based recipients +# for role in rule.recipient_roles: +# role_recipients = User.objects.filter(groups__name=role) +# for recipient in role_recipients: +# self.send_alert_to_recipient(alert, recipient) +# +# def send_alert_to_recipient(self, alert, recipient): +# """Send alert to specific recipient""" +# if recipient.email: +# send_mail( +# subject=f'ALERT: {alert.title}', +# message=f'Alert: {alert.description}\nSeverity: {alert.severity}', +# from_email='alerts@hospital.com', +# recipient_list=[recipient.email], +# fail_silently=True +# ) +# +# def schedule_escalation(self, alert): +# """Schedule alert escalation""" +# rule = alert.alert_rule +# escalation_rules = rule.escalation_rules +# +# if escalation_rules: +# # Schedule escalation task +# escalate_alert.apply_async( +# args=[alert.alert_id], +# countdown=escalation_rules.get('escalation_delay', 3600) # 1 hour default +# ) +# +# def notify_alert_resolution(self, alert): +# """Notify alert resolution""" +# # Notify all recipients of resolution +# rule = alert.alert_rule +# +# for recipient in rule.default_recipients.all(): +# if recipient.email: +# send_mail( +# subject=f'RESOLVED: {alert.title}', +# message=f'Alert has been resolved: {alert.description}', +# from_email='alerts@hospital.com', +# recipient_list=[recipient.email], +# fail_silently=True +# ) +# +# def update_alert_metrics(self, alert): +# """Update alert performance metrics""" +# # This would update alert metrics +# pass +# +# def generate_alert_summary(self, alert): +# """Generate alert summary""" +# # This would generate alert summary +# pass +# +# +# class CommunicationAuditProcess(Process): +# """ +# Viewflow process model for communication audit +# """ +# audit_period_start = models.DateTimeField(help_text='Audit period start') +# audit_period_end = models.DateTimeField(help_text='Audit period end') +# +# # Process status tracking +# audit_initiated = models.BooleanField(default=False) +# data_collected = models.BooleanField(default=False) +# analysis_completed = models.BooleanField(default=False) +# report_generated = models.BooleanField(default=False) +# audit_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Communication Audit Process' +# verbose_name_plural = 'Communication Audit Processes' +# +# +# class CommunicationAuditFlow(Flow): +# """ +# Communication Audit Workflow +# +# This flow manages communication auditing including +# data collection, analysis, and reporting. +# """ +# +# process_class = CommunicationAuditProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_communication_audit) +# .Next(this.initiate_audit) +# ) +# +# initiate_audit = ( +# flow_func(this.setup_audit_parameters) +# .Next(this.collect_data) +# ) +# +# collect_data = ( +# flow_func(this.gather_communication_data) +# .Next(this.analyze_data) +# ) +# +# analyze_data = ( +# flow_func(this.perform_communication_analysis) +# .Next(this.generate_report) +# ) +# +# generate_report = ( +# flow_func(this.create_audit_report) +# .Next(this.complete_audit) +# ) +# +# complete_audit = ( +# flow_func(this.finalize_communication_audit) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_communication_audit) +# +# # Flow functions +# def start_communication_audit(self, activation): +# """Initialize the communication audit process""" +# process = activation.process +# +# # Send audit notification +# self.notify_audit_start(process.audit_period_start, process.audit_period_end) +# +# def setup_audit_parameters(self, activation): +# """Setup audit parameters and scope""" +# process = activation.process +# +# # Mark audit initiated +# process.audit_initiated = True +# process.save() +# +# # Configure audit parameters +# self.configure_audit_scope(process.audit_period_start, process.audit_period_end) +# +# def gather_communication_data(self, activation): +# """Gather communication data for audit""" +# process = activation.process +# +# # Collect communication data +# self.collect_audit_data(process.audit_period_start, process.audit_period_end) +# +# # Mark data collected +# process.data_collected = True +# process.save() +# +# def perform_communication_analysis(self, activation): +# """Perform communication analysis""" +# process = activation.process +# +# # Analyze communication patterns and compliance +# self.analyze_communication_patterns(process.audit_period_start, process.audit_period_end) +# +# # Mark analysis completed +# process.analysis_completed = True +# process.save() +# +# def create_audit_report(self, activation): +# """Create audit report""" +# process = activation.process +# +# # Generate comprehensive audit report +# self.generate_audit_report(process.audit_period_start, process.audit_period_end) +# +# # Mark report generated +# process.report_generated = True +# process.save() +# +# def finalize_communication_audit(self, activation): +# """Finalize the communication audit process""" +# process = activation.process +# +# # Mark audit completed +# process.audit_completed = True +# process.save() +# +# # Send audit completion notification +# self.notify_audit_completion(process.audit_period_start, process.audit_period_end) +# +# def end_communication_audit(self, activation): +# """End the communication audit workflow""" +# process = activation.process +# +# # Archive audit results +# self.archive_audit_results(process.audit_period_start, process.audit_period_end) +# +# # Helper methods +# def notify_audit_start(self, start_date, end_date): +# """Notify audit start""" +# # This would notify relevant parties of audit start +# pass +# +# def configure_audit_scope(self, start_date, end_date): +# """Configure audit scope and parameters""" +# # This would configure audit parameters +# pass +# +# def collect_audit_data(self, start_date, end_date): +# """Collect communication data for audit""" +# # This would collect all relevant communication data +# pass +# +# def analyze_communication_patterns(self, start_date, end_date): +# """Analyze communication patterns""" +# # This would analyze communication effectiveness and compliance +# pass +# +# def generate_audit_report(self, start_date, end_date): +# """Generate comprehensive audit report""" +# # This would generate detailed audit report +# pass +# +# def notify_audit_completion(self, start_date, end_date): +# """Notify audit completion""" +# # This would notify audit completion +# pass +# +# def archive_audit_results(self, start_date, end_date): +# """Archive audit results""" +# # This would archive audit results for future reference +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def send_scheduled_message(message_id): +# """Background task to send scheduled messages""" +# try: +# message = Message.objects.get(message_id=message_id) +# +# # Send message to all recipients +# for recipient in message.recipients.all(): +# send_message_to_recipient(message, recipient) +# +# # Update message status +# message.status = 'SENT' +# message.sent_at = timezone.now() +# message.save() +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def escalate_alert(alert_id): +# """Background task to escalate alerts""" +# try: +# alert = AlertInstance.objects.get(alert_id=alert_id) +# +# if alert.status == 'ACTIVE': +# # Escalate alert +# alert.escalation_level += 1 +# alert.escalated_at = timezone.now() +# alert.save() +# +# # Send escalation notifications +# send_escalation_notifications(alert) +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def process_notification_queue(): +# """Background task to process notification queue""" +# try: +# # This would process pending notifications +# return True +# except Exception: +# return False +# +# +# @celery.job +# def cleanup_expired_messages(): +# """Background task to cleanup expired messages""" +# try: +# # This would cleanup expired messages +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_communication_reports(): +# """Background task to generate communication reports""" +# try: +# # This would generate periodic communication reports +# return True +# except Exception: +# return False +# +# +# def send_message_to_recipient(message, recipient): +# """Helper function to send message to specific recipient""" +# # This would implement actual message sending logic +# pass +# +# +# def send_escalation_notifications(alert): +# """Helper function to send escalation notifications""" +# # This would send escalation notifications +# pass +# diff --git a/core/__pycache__/admin.cpython-312.pyc b/core/__pycache__/admin.cpython-312.pyc index cf8a7ffc4b1a97ef6322766fbe1f8307a9e0703b..00b2aa2873b35c5c4a09d3eb59079a9cd8a747d8 100644 GIT binary patch delta 20 acmdmMve$(BG%qg~0}yoX-@B39ND2T!D+THR delta 20 acmdmMve$(BG%qg~0}$BlYv0IiBn1FI3I%8Y diff --git a/core/__pycache__/flows.cpython-312.pyc b/core/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aadce5c4c6c155a5513a63cf45da952d5e1875f8 GIT binary patch literal 174 zcmX@j%ge<81bQ<2GPtuC7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX;)_{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc vqMw{!l&YVWlV4t}S5SG2!zMRBr8Fniu80+AIwKGlgBTx~85tRin1L(+d!;T) literal 0 HcmV?d00001 diff --git a/core/__pycache__/forms.cpython-312.pyc b/core/__pycache__/forms.cpython-312.pyc index 13ebdd6d1ea266b49a77cc4beab1a78222fc4ef4..2b335ed8d0cad3eef3386fe63202d286c8fc9bde 100644 GIT binary patch delta 20 acmZq6Z_DRC&CAQh00jH?@7>5cu9IoL`h0zj=3JD=VYgX2*1KMn>b!kr~#EjAomsX2vrz+HU@uwStk+ tW%IloTPDWH$#?P$7}YoP=KHdW$FUSLGs;g8n=Ug^<|_k;UE~9_9{|<;D}w+4 delta 121 zcmV-<0EYkd=mGKQ0S(Iy4GI7N003T4lW0b<4Fn4g4OMPwbY)~9Q*>c;WplG03$OtL zRZ~Q>(F}450UxtO7j;Sj3$wprg#`g8vqfhY0Rc3#U1&Q20XMUmXWKC}61r~v^* bv!ZN00s&f+;BGJhBC`>1O$7m9lV5ZeFuf*m diff --git a/core/__pycache__/views.cpython-312.pyc b/core/__pycache__/views.cpython-312.pyc index aff523a84a4ea6b3bc9c453e583b884086316187..c4cf615beb19a53235e10016c06fcb17504754e2 100644 GIT binary patch delta 25 fcmdnHlx6Qy7Vgu$yj%=G(6WDTBllKr#!W&1Y>@}p delta 25 fcmdnHlx6Qy7Vgu$yj%=G5X3RNk$WpQ<0c^hV;%<0 diff --git a/core/flows.py b/core/flows.py new file mode 100644 index 00000000..4e05b8d3 --- /dev/null +++ b/core/flows.py @@ -0,0 +1,849 @@ +# """ +# Viewflow workflows for core app. +# Provides system administration, tenant management, and configuration 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 Tenant, Department, AuditLogEntry, SystemConfiguration, SystemNotification, IntegrationLog +# from .views import ( +# TenantSetupView, DepartmentManagementView, ConfigurationView, +# AuditReviewView, NotificationManagementView, IntegrationMonitoringView, +# SystemMaintenanceView, BackupView, SecurityAuditView, ComplianceCheckView +# ) +# +# +# class TenantOnboardingProcess(Process): +# """ +# Viewflow process model for tenant onboarding +# """ +# tenant = ModelField(Tenant, help_text='Associated tenant') +# +# # Process status tracking +# tenant_created = models.BooleanField(default=False) +# configuration_setup = models.BooleanField(default=False) +# departments_created = models.BooleanField(default=False) +# users_configured = models.BooleanField(default=False) +# integrations_setup = models.BooleanField(default=False) +# testing_completed = models.BooleanField(default=False) +# training_provided = models.BooleanField(default=False) +# onboarding_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Tenant Onboarding Process' +# verbose_name_plural = 'Tenant Onboarding Processes' +# +# +# class TenantOnboardingFlow(Flow): +# """ +# Tenant Onboarding Workflow +# +# This flow manages complete tenant onboarding from initial +# setup through configuration, testing, and go-live. +# """ +# +# process_class = TenantOnboardingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_tenant_onboarding) +# .Next(this.setup_tenant) +# ) +# +# setup_tenant = ( +# flow_view(TenantSetupView) +# .Permission('core.can_setup_tenants') +# .Next(this.configure_system) +# ) +# +# configure_system = ( +# flow_view(ConfigurationView) +# .Permission('core.can_configure_system') +# .Next(this.create_departments) +# ) +# +# create_departments = ( +# flow_view(DepartmentManagementView) +# .Permission('core.can_manage_departments') +# .Next(this.configure_users) +# ) +# +# configure_users = ( +# flow_func(this.setup_initial_users) +# .Next(this.setup_integrations) +# ) +# +# setup_integrations = ( +# flow_func(this.configure_integrations) +# .Next(this.complete_testing) +# ) +# +# complete_testing = ( +# flow_func(this.perform_system_testing) +# .Next(this.provide_training) +# ) +# +# provide_training = ( +# flow_func(this.deliver_user_training) +# .Next(this.finalize_onboarding) +# ) +# +# finalize_onboarding = ( +# flow_func(this.complete_tenant_onboarding) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_tenant_onboarding) +# +# # Flow functions +# def start_tenant_onboarding(self, activation): +# """Initialize the tenant onboarding process""" +# process = activation.process +# tenant = process.tenant +# +# # Send onboarding notification +# self.notify_onboarding_start(tenant) +# +# # Create onboarding checklist +# self.create_onboarding_checklist(tenant) +# +# # Set up audit logging +# self.setup_audit_logging(tenant) +# +# def setup_initial_users(self, activation): +# """Setup initial users for tenant""" +# process = activation.process +# tenant = process.tenant +# +# # Create initial admin users +# self.create_admin_users(tenant) +# +# # Mark users configured +# process.users_configured = True +# process.save() +# +# # Send user credentials +# self.send_user_credentials(tenant) +# +# def configure_integrations(self, activation): +# """Configure system integrations""" +# process = activation.process +# tenant = process.tenant +# +# # Setup default integrations +# self.setup_default_integrations(tenant) +# +# # Mark integrations setup +# process.integrations_setup = True +# process.save() +# +# # Test integration connectivity +# self.test_integration_connectivity(tenant) +# +# def perform_system_testing(self, activation): +# """Perform comprehensive system testing""" +# process = activation.process +# tenant = process.tenant +# +# # Execute system tests +# test_results = self.execute_system_tests(tenant) +# +# # Mark testing completed +# process.testing_completed = True +# process.save() +# +# # Store test results +# self.store_test_results(tenant, test_results) +# +# def deliver_user_training(self, activation): +# """Deliver user training""" +# process = activation.process +# tenant = process.tenant +# +# # Schedule training sessions +# self.schedule_training_sessions(tenant) +# +# # Mark training provided +# process.training_provided = True +# process.save() +# +# # Send training materials +# self.send_training_materials(tenant) +# +# def complete_tenant_onboarding(self, activation): +# """Complete the tenant onboarding process""" +# process = activation.process +# tenant = process.tenant +# +# # Activate tenant +# tenant.is_active = True +# tenant.save() +# +# # Mark onboarding completed +# process.onboarding_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_onboarding_completion(tenant) +# +# # Schedule post-onboarding follow-up +# self.schedule_followup(tenant) +# +# def end_tenant_onboarding(self, activation): +# """End the tenant onboarding workflow""" +# process = activation.process +# +# # Generate onboarding summary +# self.generate_onboarding_summary(process.tenant) +# +# # Helper methods +# def notify_onboarding_start(self, tenant): +# """Notify onboarding start""" +# admin_team = User.objects.filter(groups__name='System Administrators') +# for admin in admin_team: +# send_mail( +# subject=f'Tenant Onboarding Started: {tenant.name}', +# message=f'Onboarding process started for tenant "{tenant.name}".', +# from_email='admin@hospital.com', +# recipient_list=[admin.email], +# fail_silently=True +# ) +# +# def create_onboarding_checklist(self, tenant): +# """Create onboarding checklist""" +# # This would create a comprehensive onboarding checklist +# pass +# +# def setup_audit_logging(self, tenant): +# """Setup audit logging for tenant""" +# # This would configure audit logging +# pass +# +# def create_admin_users(self, tenant): +# """Create initial admin users""" +# # This would create initial admin users +# pass +# +# def send_user_credentials(self, tenant): +# """Send user credentials""" +# # This would send initial user credentials +# pass +# +# def setup_default_integrations(self, tenant): +# """Setup default integrations""" +# # This would configure default integrations +# pass +# +# def test_integration_connectivity(self, tenant): +# """Test integration connectivity""" +# # This would test all integrations +# pass +# +# def execute_system_tests(self, tenant): +# """Execute comprehensive system tests""" +# # This would run system tests +# return {'status': 'passed', 'issues': []} +# +# def store_test_results(self, tenant, results): +# """Store test results""" +# # This would store test results +# pass +# +# def schedule_training_sessions(self, tenant): +# """Schedule training sessions""" +# # This would schedule training +# pass +# +# def send_training_materials(self, tenant): +# """Send training materials""" +# # This would send training materials +# pass +# +# def notify_onboarding_completion(self, tenant): +# """Notify onboarding completion""" +# send_mail( +# subject=f'Tenant Onboarding Complete: {tenant.name}', +# message=f'Onboarding completed successfully for "{tenant.name}".', +# from_email='admin@hospital.com', +# recipient_list=[tenant.email], +# fail_silently=True +# ) +# +# def schedule_followup(self, tenant): +# """Schedule post-onboarding follow-up""" +# # Schedule follow-up task +# tenant_followup.apply_async( +# args=[tenant.tenant_id], +# countdown=86400 * 7 # 7 days +# ) +# +# def generate_onboarding_summary(self, tenant): +# """Generate onboarding summary""" +# # This would generate onboarding summary +# pass +# +# +# class SystemMaintenanceProcess(Process): +# """ +# Viewflow process model for system maintenance +# """ +# maintenance_type = models.CharField(max_length=50, help_text='Type of maintenance') +# +# # Process status tracking +# maintenance_scheduled = models.BooleanField(default=False) +# notifications_sent = models.BooleanField(default=False) +# backup_completed = models.BooleanField(default=False) +# maintenance_executed = models.BooleanField(default=False) +# testing_completed = models.BooleanField(default=False) +# system_restored = models.BooleanField(default=False) +# maintenance_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'System Maintenance Process' +# verbose_name_plural = 'System Maintenance Processes' +# +# +# class SystemMaintenanceFlow(Flow): +# """ +# System Maintenance Workflow +# +# This flow manages scheduled system maintenance including +# notifications, backups, execution, and restoration. +# """ +# +# process_class = SystemMaintenanceProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_system_maintenance) +# .Next(this.schedule_maintenance) +# ) +# +# schedule_maintenance = ( +# flow_view(SystemMaintenanceView) +# .Permission('core.can_schedule_maintenance') +# .Next(this.send_notifications) +# ) +# +# send_notifications = ( +# flow_func(this.notify_maintenance_window) +# .Next(this.create_backup) +# ) +# +# create_backup = ( +# flow_view(BackupView) +# .Permission('core.can_create_backups') +# .Next(this.execute_maintenance) +# ) +# +# execute_maintenance = ( +# flow_func(this.perform_maintenance_tasks) +# .Next(this.test_system) +# ) +# +# test_system = ( +# flow_func(this.perform_post_maintenance_testing) +# .Next(this.restore_system) +# ) +# +# restore_system = ( +# flow_func(this.restore_system_services) +# .Next(this.complete_maintenance) +# ) +# +# complete_maintenance = ( +# flow_func(this.finalize_system_maintenance) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_system_maintenance) +# +# # Flow functions +# def start_system_maintenance(self, activation): +# """Initialize the system maintenance process""" +# process = activation.process +# +# # Send maintenance start notification +# self.notify_maintenance_start(process.maintenance_type) +# +# # Create maintenance checklist +# self.create_maintenance_checklist(process.maintenance_type) +# +# def notify_maintenance_window(self, activation): +# """Send maintenance window notifications""" +# process = activation.process +# +# # Send notifications to all users +# self.send_maintenance_notifications(process.maintenance_type) +# +# # Mark notifications sent +# process.notifications_sent = True +# process.save() +# +# # Create system notification +# self.create_system_notification(process.maintenance_type) +# +# def perform_maintenance_tasks(self, activation): +# """Perform maintenance tasks""" +# process = activation.process +# +# # Execute maintenance tasks +# self.execute_maintenance_procedures(process.maintenance_type) +# +# # Mark maintenance executed +# process.maintenance_executed = True +# process.save() +# +# # Log maintenance activities +# self.log_maintenance_activities(process.maintenance_type) +# +# def perform_post_maintenance_testing(self, activation): +# """Perform post-maintenance testing""" +# process = activation.process +# +# # Execute post-maintenance tests +# test_results = self.execute_post_maintenance_tests() +# +# # Mark testing completed +# process.testing_completed = True +# process.save() +# +# # Store test results +# self.store_maintenance_test_results(test_results) +# +# def restore_system_services(self, activation): +# """Restore system services""" +# process = activation.process +# +# # Restore all system services +# self.restore_services() +# +# # Mark system restored +# process.system_restored = True +# process.save() +# +# # Verify service restoration +# self.verify_service_restoration() +# +# def finalize_system_maintenance(self, activation): +# """Finalize the system maintenance process""" +# process = activation.process +# +# # Mark maintenance completed +# process.maintenance_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_maintenance_completion(process.maintenance_type) +# +# # Generate maintenance report +# self.generate_maintenance_report(process.maintenance_type) +# +# def end_system_maintenance(self, activation): +# """End the system maintenance workflow""" +# process = activation.process +# +# # Archive maintenance records +# self.archive_maintenance_records(process.maintenance_type) +# +# # Helper methods +# def notify_maintenance_start(self, maintenance_type): +# """Notify maintenance start""" +# admin_team = User.objects.filter(groups__name='System Administrators') +# for admin in admin_team: +# send_mail( +# subject=f'System Maintenance Started: {maintenance_type}', +# message=f'System maintenance process started for {maintenance_type}.', +# from_email='admin@hospital.com', +# recipient_list=[admin.email], +# fail_silently=True +# ) +# +# def create_maintenance_checklist(self, maintenance_type): +# """Create maintenance checklist""" +# # This would create maintenance checklist +# pass +# +# def send_maintenance_notifications(self, maintenance_type): +# """Send maintenance notifications to all users""" +# # This would send notifications to all users +# pass +# +# def create_system_notification(self, maintenance_type): +# """Create system-wide notification""" +# SystemNotification.objects.create( +# title='Scheduled System Maintenance', +# message=f'System maintenance is scheduled for {maintenance_type}.', +# notification_type='MAINTENANCE', +# priority='HIGH', +# target_audience='ALL_USERS', +# is_active=True +# ) +# +# def execute_maintenance_procedures(self, maintenance_type): +# """Execute maintenance procedures""" +# # This would execute maintenance procedures +# pass +# +# def log_maintenance_activities(self, maintenance_type): +# """Log maintenance activities""" +# # This would log all maintenance activities +# pass +# +# def execute_post_maintenance_tests(self): +# """Execute post-maintenance tests""" +# # This would run post-maintenance tests +# return {'status': 'passed', 'issues': []} +# +# def store_maintenance_test_results(self, results): +# """Store maintenance test results""" +# # This would store test results +# pass +# +# def restore_services(self): +# """Restore all system services""" +# # This would restore system services +# pass +# +# def verify_service_restoration(self): +# """Verify service restoration""" +# # This would verify all services are restored +# pass +# +# def notify_maintenance_completion(self, maintenance_type): +# """Notify maintenance completion""" +# all_users = User.objects.filter(is_active=True) +# for user in all_users: +# if user.email: +# send_mail( +# subject='System Maintenance Complete', +# message=f'System maintenance for {maintenance_type} has been completed.', +# from_email='admin@hospital.com', +# recipient_list=[user.email], +# fail_silently=True +# ) +# +# def generate_maintenance_report(self, maintenance_type): +# """Generate maintenance report""" +# # This would generate comprehensive maintenance report +# pass +# +# def archive_maintenance_records(self, maintenance_type): +# """Archive maintenance records""" +# # This would archive maintenance records +# pass +# +# +# class AuditManagementProcess(Process): +# """ +# Viewflow process model for audit management +# """ +# audit_type = models.CharField(max_length=50, help_text='Type of audit') +# +# # Process status tracking +# audit_initiated = models.BooleanField(default=False) +# scope_defined = models.BooleanField(default=False) +# data_collected = models.BooleanField(default=False) +# analysis_completed = models.BooleanField(default=False) +# findings_documented = models.BooleanField(default=False) +# report_generated = models.BooleanField(default=False) +# audit_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Audit Management Process' +# verbose_name_plural = 'Audit Management Processes' +# +# +# class AuditManagementFlow(Flow): +# """ +# Audit Management Workflow +# +# This flow manages system audits including security, +# compliance, and operational audits. +# """ +# +# process_class = AuditManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_audit_management) +# .Next(this.initiate_audit) +# ) +# +# initiate_audit = ( +# flow_func(this.setup_audit_scope) +# .Next(this.define_scope) +# ) +# +# define_scope = ( +# flow_func(this.define_audit_scope) +# .Next(this.collect_data) +# ) +# +# collect_data = ( +# flow_func(this.gather_audit_data) +# .Next(this.analyze_data) +# ) +# +# analyze_data = ( +# flow_view(AuditReviewView) +# .Permission('core.can_review_audits') +# .Next(this.document_findings) +# ) +# +# document_findings = ( +# flow_func(this.document_audit_findings) +# .Next(this.generate_report) +# ) +# +# generate_report = ( +# flow_func(this.create_audit_report) +# .Next(this.complete_audit) +# ) +# +# complete_audit = ( +# flow_func(this.finalize_audit_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_audit_management) +# +# # Flow functions +# def start_audit_management(self, activation): +# """Initialize the audit management process""" +# process = activation.process +# +# # Send audit start notification +# self.notify_audit_start(process.audit_type) +# +# # Create audit checklist +# self.create_audit_checklist(process.audit_type) +# +# def setup_audit_scope(self, activation): +# """Setup audit scope""" +# process = activation.process +# +# # Mark audit initiated +# process.audit_initiated = True +# process.save() +# +# # Configure audit parameters +# self.configure_audit_parameters(process.audit_type) +# +# def define_audit_scope(self, activation): +# """Define audit scope and criteria""" +# process = activation.process +# +# # Define audit scope +# self.establish_audit_scope(process.audit_type) +# +# # Mark scope defined +# process.scope_defined = True +# process.save() +# +# def gather_audit_data(self, activation): +# """Gather audit data""" +# process = activation.process +# +# # Collect audit data +# audit_data = self.collect_audit_data(process.audit_type) +# +# # Mark data collected +# process.data_collected = True +# process.save() +# +# # Store audit data +# self.store_audit_data(process.audit_type, audit_data) +# +# def document_audit_findings(self, activation): +# """Document audit findings""" +# process = activation.process +# +# # Document findings +# findings = self.create_audit_findings(process.audit_type) +# +# # Mark findings documented +# process.findings_documented = True +# process.save() +# +# # Store findings +# self.store_audit_findings(process.audit_type, findings) +# +# def create_audit_report(self, activation): +# """Create audit report""" +# process = activation.process +# +# # Generate audit report +# report = self.generate_audit_report(process.audit_type) +# +# # Mark report generated +# process.report_generated = True +# process.save() +# +# # Store report +# self.store_audit_report(process.audit_type, report) +# +# def finalize_audit_management(self, activation): +# """Finalize the audit management process""" +# process = activation.process +# +# # Mark audit completed +# process.audit_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_audit_completion(process.audit_type) +# +# # Schedule follow-up actions +# self.schedule_audit_followup(process.audit_type) +# +# def end_audit_management(self, activation): +# """End the audit management workflow""" +# process = activation.process +# +# # Archive audit records +# self.archive_audit_records(process.audit_type) +# +# # Helper methods +# def notify_audit_start(self, audit_type): +# """Notify audit start""" +# audit_team = User.objects.filter(groups__name='Audit Team') +# for auditor in audit_team: +# send_mail( +# subject=f'Audit Started: {audit_type}', +# message=f'Audit process started for {audit_type}.', +# from_email='audit@hospital.com', +# recipient_list=[auditor.email], +# fail_silently=True +# ) +# +# def create_audit_checklist(self, audit_type): +# """Create audit checklist""" +# # This would create audit checklist +# pass +# +# def configure_audit_parameters(self, audit_type): +# """Configure audit parameters""" +# # This would configure audit parameters +# pass +# +# def establish_audit_scope(self, audit_type): +# """Establish audit scope""" +# # This would define audit scope +# pass +# +# def collect_audit_data(self, audit_type): +# """Collect audit data""" +# # This would collect audit data +# return {'status': 'collected', 'records': 1000} +# +# def store_audit_data(self, audit_type, data): +# """Store audit data""" +# # This would store audit data +# pass +# +# def create_audit_findings(self, audit_type): +# """Create audit findings""" +# # This would create audit findings +# return {'findings': [], 'recommendations': []} +# +# def store_audit_findings(self, audit_type, findings): +# """Store audit findings""" +# # This would store findings +# pass +# +# def generate_audit_report(self, audit_type): +# """Generate audit report""" +# # This would generate comprehensive audit report +# return {'report_path': '/audits/report.pdf'} +# +# def store_audit_report(self, audit_type, report): +# """Store audit report""" +# # This would store audit report +# pass +# +# def notify_audit_completion(self, audit_type): +# """Notify audit completion""" +# # This would notify relevant parties +# pass +# +# def schedule_audit_followup(self, audit_type): +# """Schedule audit follow-up""" +# # Schedule follow-up task +# audit_followup.apply_async( +# args=[audit_type], +# countdown=86400 * 30 # 30 days +# ) +# +# def archive_audit_records(self, audit_type): +# """Archive audit records""" +# # This would archive audit records +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def tenant_followup(tenant_id): +# """Background task for tenant follow-up""" +# try: +# tenant = Tenant.objects.get(tenant_id=tenant_id) +# +# # Perform follow-up activities +# # This would perform post-onboarding follow-up +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def system_health_check(): +# """Background task for system health monitoring""" +# try: +# # This would perform system health checks +# return True +# except Exception: +# return False +# +# +# @celery.job +# def audit_followup(audit_type): +# """Background task for audit follow-up""" +# try: +# # This would perform audit follow-up activities +# return True +# except Exception: +# return False +# +# +# @celery.job +# def cleanup_audit_logs(): +# """Background task to cleanup old audit logs""" +# try: +# # This would cleanup old audit logs +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_system_reports(): +# """Background task to generate system reports""" +# try: +# # This would generate periodic system reports +# return True +# except Exception: +# return False +# diff --git a/core/models.py b/core/models.py index a0074036..459657b1 100644 --- a/core/models.py +++ b/core/models.py @@ -90,7 +90,7 @@ class Tenant(models.Model): ) country = models.CharField( max_length=100, - default='United States', + default='Saudi Arabia', help_text='Country' ) @@ -150,7 +150,7 @@ class Tenant(models.Model): ) currency = models.CharField( max_length=3, - default='USD', + default='SAR', help_text='Organization currency code' ) @@ -854,7 +854,6 @@ class IntegrationLog(models.Model): - class Department(models.Model): """ Hospital department model for organizational structure. @@ -890,10 +889,10 @@ class Department(models.Model): tenant = models.ForeignKey( Tenant, on_delete=models.CASCADE, - related_name='departments', + related_name='core_departments', help_text='Organization tenant' ) - + # Department Information department_id = models.UUIDField( default=uuid.uuid4, @@ -914,14 +913,14 @@ class Department(models.Model): null=True, help_text='Department description' ) - + # Department Classification department_type = models.CharField( max_length=30, choices=DEPARTMENT_TYPE_CHOICES, help_text='Type of department' ) - + # Organizational Structure parent_department = models.ForeignKey( 'self', @@ -931,7 +930,7 @@ class Department(models.Model): related_name='sub_departments', help_text='Parent department (for hierarchical structure)' ) - + # Management department_head = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -941,7 +940,7 @@ class Department(models.Model): related_name='headed_departments', help_text='Department head/manager' ) - + # Contact Information phone = models.CharField( max_length=20, @@ -960,7 +959,7 @@ class Department(models.Model): null=True, help_text='Department email' ) - + # Location building = models.CharField( max_length=50, @@ -986,7 +985,7 @@ class Department(models.Model): null=True, help_text='Room numbers (e.g., 101-110, 201A-205C)' ) - + # Operational Information is_active = models.BooleanField( default=True, @@ -1001,7 +1000,7 @@ class Department(models.Model): blank=True, help_text='Operating hours by day of week' ) - + # Budget and Cost Center cost_center_code = models.CharField( max_length=20, @@ -1015,7 +1014,7 @@ class Department(models.Model): null=True, help_text='Budget code' ) - + # Staffing authorized_positions = models.PositiveIntegerField( default=0, @@ -1025,7 +1024,7 @@ class Department(models.Model): default=0, help_text='Current number of staff members' ) - + # Quality and Compliance accreditation_required = models.BooleanField( default=False, @@ -1047,7 +1046,7 @@ class Department(models.Model): null=True, help_text='Next scheduled inspection date' ) - + # Metadata created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -1059,7 +1058,7 @@ class Department(models.Model): related_name='created_departments', help_text='User who created the department' ) - + class Meta: db_table = 'core_department' verbose_name = 'Department' @@ -1072,24 +1071,24 @@ class Department(models.Model): models.Index(fields=['parent_department']), ] unique_together = ['tenant', 'code'] - + def __str__(self): return f"{self.name} ({self.code})" - + @property def full_name(self): """Return full department name with parent if applicable""" if self.parent_department: return f"{self.parent_department.name} - {self.name}" return self.name - + @property def staffing_percentage(self): """Calculate current staffing percentage""" if self.authorized_positions > 0: return (self.current_staff_count / self.authorized_positions) * 100 return 0 - + def get_all_sub_departments(self): """Get all sub-departments recursively""" sub_departments = [] diff --git a/db.sqlite3 b/db.sqlite3 index e52372a39d810d13d3b489b879bc4eaff3fa3c7a..8027494908e37b64cc85eb2da116e640e5128856 100644 GIT binary patch delta 53909 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 delta 23135 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 diff --git a/emr/__pycache__/flows.cpython-312.pyc b/emr/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9dc1af66a89947716ae2e5f01395caf8e16128b GIT binary patch literal 173 zcmX@j%ge<81bQ<2GQO5GFgylv(7|UGpvZKFN(N0vzm*I{OhDdekeXjU`k}?CMaBBL ziACj!d5JmYi8+}-PF`tod_hruR%&vIenx(AL1sx}PCQUJF+DXmHLoPTxU#q;H8;M@ uL_amRNIxwnzr0wlpz;=nO>TZlX-=wL5i8JeMj$Q*F+MUgGBOr116csz@Gjc` literal 0 HcmV?d00001 diff --git a/emr/__pycache__/urls.cpython-312.pyc b/emr/__pycache__/urls.cpython-312.pyc index fe32c7af3431f26f1d2af7dde5a1029434eaf502..cf7bccd7f3db2c1b88ee7ab1fca39a179bfb2409 100644 GIT binary patch delta 75 zcmbOsIa8ANG%qg~0}yDG?#Y<3kvEZ5P&73!IlnZoB(w@i7gh=R1)|p# etu88BT~~CvsOWTA(dB}7>=l-{&9}MsF#-T`Y8l4> diff --git a/emr/flows.py b/emr/flows.py new file mode 100644 index 00000000..cef76b53 --- /dev/null +++ b/emr/flows.py @@ -0,0 +1,929 @@ +# """ +# Viewflow workflows for EMR app. +# Provides electronic medical record workflows for clinical documentation, care planning, and patient management. +# """ +# +# 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 Encounter, ClinicalNote, ProblemList, CarePlan, NoteTemplate +# from .views import ( +# EncounterInitiationView, PatientAssessmentView, ClinicalDocumentationView, +# ProblemIdentificationView, CarePlanDevelopmentView, TreatmentPlanningView, +# ProgressMonitoringView, DischargePreparationView, QualityReviewView, +# NoteCreationView, NoteReviewView, NoteSigningView +# ) +# +# +# class ClinicalEncounterProcess(Process): +# """ +# Viewflow process model for clinical encounters +# """ +# encounter = ModelField(Encounter, help_text='Associated clinical encounter') +# +# # Process status tracking +# encounter_initiated = models.BooleanField(default=False) +# patient_assessed = models.BooleanField(default=False) +# problems_identified = models.BooleanField(default=False) +# care_plan_developed = models.BooleanField(default=False) +# treatment_planned = models.BooleanField(default=False) +# documentation_completed = models.BooleanField(default=False) +# quality_reviewed = models.BooleanField(default=False) +# encounter_finalized = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Clinical Encounter Process' +# verbose_name_plural = 'Clinical Encounter Processes' +# +# +# class ClinicalEncounterFlow(Flow): +# """ +# Clinical Encounter Workflow +# +# This flow manages the complete clinical encounter process from +# patient assessment through documentation and quality review. +# """ +# +# process_class = ClinicalEncounterProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_encounter) +# .Next(this.initiate_encounter) +# ) +# +# initiate_encounter = ( +# flow_view(EncounterInitiationView) +# .Permission('emr.can_initiate_encounters') +# .Next(this.assess_patient) +# ) +# +# assess_patient = ( +# flow_view(PatientAssessmentView) +# .Permission('emr.can_assess_patients') +# .Next(this.parallel_clinical_work) +# ) +# +# parallel_clinical_work = ( +# flow_func(this.start_parallel_clinical_work) +# .Next(this.identify_problems) +# .Next(this.develop_care_plan) +# .Next(this.plan_treatment) +# ) +# +# identify_problems = ( +# flow_view(ProblemIdentificationView) +# .Permission('emr.can_identify_problems') +# .Next(this.join_clinical_work) +# ) +# +# develop_care_plan = ( +# flow_view(CarePlanDevelopmentView) +# .Permission('emr.can_develop_care_plans') +# .Next(this.join_clinical_work) +# ) +# +# plan_treatment = ( +# flow_view(TreatmentPlanningView) +# .Permission('emr.can_plan_treatment') +# .Next(this.join_clinical_work) +# ) +# +# join_clinical_work = ( +# flow_func(this.join_parallel_clinical_work) +# .Next(this.complete_documentation) +# ) +# +# complete_documentation = ( +# flow_view(ClinicalDocumentationView) +# .Permission('emr.can_complete_documentation') +# .Next(this.review_quality) +# ) +# +# review_quality = ( +# flow_view(QualityReviewView) +# .Permission('emr.can_review_quality') +# .Next(this.finalize_encounter) +# ) +# +# finalize_encounter = ( +# flow_func(this.complete_encounter) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_encounter) +# +# # Flow functions +# def start_encounter(self, activation): +# """Initialize the clinical encounter process""" +# process = activation.process +# encounter = process.encounter +# +# # Update encounter status +# encounter.status = 'IN_PROGRESS' +# encounter.save() +# +# # Send notification to clinical staff +# self.notify_clinical_staff(encounter) +# +# # Check for high-priority encounters +# if encounter.encounter_type in ['EMERGENCY', 'URGENT_CARE']: +# self.notify_priority_encounter(encounter) +# +# def start_parallel_clinical_work(self, activation): +# """Start parallel clinical work tasks""" +# process = activation.process +# +# # Create parallel clinical tasks +# self.create_clinical_tasks(process.encounter) +# +# def join_parallel_clinical_work(self, activation): +# """Wait for all clinical work to complete""" +# process = activation.process +# +# # Check if all clinical work is completed +# if (process.problems_identified and +# process.care_plan_developed and +# process.treatment_planned): +# +# # Proceed to documentation +# self.notify_documentation_ready(process.encounter) +# +# def complete_encounter(self, activation): +# """Finalize the clinical encounter process""" +# process = activation.process +# encounter = process.encounter +# +# # Update encounter status +# encounter.status = 'COMPLETED' +# encounter.end_datetime = timezone.now() +# encounter.save() +# +# # Mark process as completed +# process.encounter_finalized = True +# process.save() +# +# # Send completion notifications +# self.notify_encounter_completion(encounter) +# +# # Update clinical metrics +# self.update_clinical_metrics(encounter) +# +# # Schedule follow-up if needed +# self.schedule_follow_up(encounter) +# +# def end_encounter(self, activation): +# """End the clinical encounter workflow""" +# process = activation.process +# +# # Generate encounter summary report +# self.generate_encounter_summary(process.encounter) +# +# # Helper methods +# def notify_clinical_staff(self, encounter): +# """Notify clinical staff of new encounter""" +# from django.contrib.auth.models import Group +# +# clinical_staff = User.objects.filter( +# groups__name='Clinical Staff' +# ) +# +# for staff in clinical_staff: +# send_mail( +# subject=f'New Clinical Encounter: {encounter.patient.get_full_name()}', +# message=f'New {encounter.get_encounter_type_display()} encounter started.', +# from_email='clinical@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_priority_encounter(self, encounter): +# """Notify of priority encounter""" +# supervisors = User.objects.filter( +# groups__name='Clinical Supervisors' +# ) +# +# for supervisor in supervisors: +# send_mail( +# subject=f'PRIORITY Encounter: {encounter.patient.get_full_name()}', +# message=f'{encounter.get_encounter_type_display()} encounter requires immediate attention.', +# from_email='clinical@hospital.com', +# recipient_list=[supervisor.email], +# fail_silently=True +# ) +# +# def create_clinical_tasks(self, encounter): +# """Create clinical work tasks""" +# # This would create tasks in a task management system +# pass +# +# def notify_documentation_ready(self, encounter): +# """Notify that documentation is ready""" +# if encounter.provider and encounter.provider.email: +# send_mail( +# subject=f'Documentation Ready: {encounter.patient.get_full_name()}', +# message=f'Clinical work completed, ready for documentation.', +# from_email='clinical@hospital.com', +# recipient_list=[encounter.provider.email], +# fail_silently=True +# ) +# +# def notify_encounter_completion(self, encounter): +# """Notify encounter completion""" +# # Notify care team +# care_team = encounter.care_team.all() +# for member in care_team: +# if member.email: +# send_mail( +# subject=f'Encounter Completed: {encounter.patient.get_full_name()}', +# message=f'Clinical encounter has been completed and documented.', +# from_email='clinical@hospital.com', +# recipient_list=[member.email], +# fail_silently=True +# ) +# +# def update_clinical_metrics(self, encounter): +# """Update clinical quality metrics""" +# # This would update clinical performance metrics +# pass +# +# def schedule_follow_up(self, encounter): +# """Schedule follow-up appointments if needed""" +# # This would schedule follow-up appointments +# pass +# +# def generate_encounter_summary(self, encounter): +# """Generate encounter summary report""" +# # This would generate a comprehensive encounter report +# pass +# +# +# class ClinicalDocumentationProcess(Process): +# """ +# Viewflow process model for clinical documentation +# """ +# clinical_note = ModelField(ClinicalNote, help_text='Associated clinical note') +# +# # Process status tracking +# note_initiated = models.BooleanField(default=False) +# content_drafted = models.BooleanField(default=False) +# clinical_review_completed = models.BooleanField(default=False) +# quality_check_completed = models.BooleanField(default=False) +# note_signed = models.BooleanField(default=False) +# note_finalized = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Clinical Documentation Process' +# verbose_name_plural = 'Clinical Documentation Processes' +# +# +# class ClinicalDocumentationFlow(Flow): +# """ +# Clinical Documentation Workflow +# +# This flow manages clinical note creation, review, and finalization +# with quality checks and electronic signatures. +# """ +# +# process_class = ClinicalDocumentationProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_documentation) +# .Next(this.create_note) +# ) +# +# create_note = ( +# flow_view(NoteCreationView) +# .Permission('emr.can_create_notes') +# .Next(this.draft_content) +# ) +# +# draft_content = ( +# flow_view(NoteDraftingView) +# .Permission('emr.can_draft_notes') +# .Next(this.review_note) +# ) +# +# review_note = ( +# flow_view(NoteReviewView) +# .Permission('emr.can_review_notes') +# .Next(this.quality_check) +# ) +# +# quality_check = ( +# flow_view(NoteQualityCheckView) +# .Permission('emr.can_quality_check_notes') +# .Next(this.sign_note) +# ) +# +# sign_note = ( +# flow_view(NoteSigningView) +# .Permission('emr.can_sign_notes') +# .Next(this.finalize_note) +# ) +# +# finalize_note = ( +# flow_func(this.complete_documentation) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_documentation) +# +# # Flow functions +# def start_documentation(self, activation): +# """Initialize the documentation process""" +# process = activation.process +# note = process.clinical_note +# +# # Update note status +# note.status = 'DRAFT' +# note.save() +# +# # Send notification to documenting provider +# self.notify_documentation_required(note) +# +# def complete_documentation(self, activation): +# """Finalize the documentation process""" +# process = activation.process +# note = process.clinical_note +# +# # Update note status +# note.status = 'FINAL' +# note.finalized_datetime = timezone.now() +# note.save() +# +# # Mark process as completed +# process.note_finalized = True +# process.save() +# +# # Send completion notifications +# self.notify_documentation_completion(note) +# +# # Update documentation metrics +# self.update_documentation_metrics(note) +# +# def end_documentation(self, activation): +# """End the documentation workflow""" +# process = activation.process +# +# # Generate documentation summary +# self.generate_documentation_summary(process.clinical_note) +# +# # Helper methods +# def notify_documentation_required(self, note): +# """Notify provider that documentation is required""" +# if note.author and note.author.email: +# send_mail( +# subject=f'Documentation Required: {note.patient.get_full_name()}', +# message=f'{note.get_note_type_display()} requires completion.', +# from_email='documentation@hospital.com', +# recipient_list=[note.author.email], +# fail_silently=True +# ) +# +# def notify_documentation_completion(self, note): +# """Notify documentation completion""" +# # Notify care team +# if note.encounter: +# care_team = note.encounter.care_team.all() +# for member in care_team: +# if member.email: +# send_mail( +# subject=f'Documentation Complete: {note.patient.get_full_name()}', +# message=f'{note.get_note_type_display()} has been completed and signed.', +# from_email='documentation@hospital.com', +# recipient_list=[member.email], +# fail_silently=True +# ) +# +# def update_documentation_metrics(self, note): +# """Update documentation quality metrics""" +# # This would update documentation performance metrics +# pass +# +# def generate_documentation_summary(self, note): +# """Generate documentation summary""" +# # This would generate documentation summary +# pass +# +# +# class CarePlanManagementProcess(Process): +# """ +# Viewflow process model for care plan management +# """ +# care_plan = ModelField(CarePlan, help_text='Associated care plan') +# +# # Process status tracking +# plan_initiated = models.BooleanField(default=False) +# assessment_completed = models.BooleanField(default=False) +# goals_established = models.BooleanField(default=False) +# interventions_planned = models.BooleanField(default=False) +# team_assigned = models.BooleanField(default=False) +# plan_approved = models.BooleanField(default=False) +# implementation_started = models.BooleanField(default=False) +# progress_monitored = models.BooleanField(default=False) +# plan_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Care Plan Management Process' +# verbose_name_plural = 'Care Plan Management Processes' +# +# +# class CarePlanManagementFlow(Flow): +# """ +# Care Plan Management Workflow +# +# This flow manages care plan development, approval, implementation, +# and monitoring with multidisciplinary team coordination. +# """ +# +# process_class = CarePlanManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_care_planning) +# .Next(this.initiate_plan) +# ) +# +# initiate_plan = ( +# flow_view(CarePlanInitiationView) +# .Permission('emr.can_initiate_care_plans') +# .Next(this.complete_assessment) +# ) +# +# complete_assessment = ( +# flow_view(CarePlanAssessmentView) +# .Permission('emr.can_assess_care_plans') +# .Next(this.establish_goals) +# ) +# +# establish_goals = ( +# flow_view(GoalEstablishmentView) +# .Permission('emr.can_establish_goals') +# .Next(this.plan_interventions) +# ) +# +# plan_interventions = ( +# flow_view(InterventionPlanningView) +# .Permission('emr.can_plan_interventions') +# .Next(this.assign_care_team) +# ) +# +# assign_care_team = ( +# flow_view(CareTeamAssignmentView) +# .Permission('emr.can_assign_care_team') +# .Next(this.approve_plan) +# ) +# +# approve_plan = ( +# flow_view(CarePlanApprovalView) +# .Permission('emr.can_approve_care_plans') +# .Next(this.implement_plan) +# ) +# +# implement_plan = ( +# flow_func(this.start_implementation) +# .Next(this.monitor_progress) +# ) +# +# monitor_progress = ( +# flow_view(ProgressMonitoringView) +# .Permission('emr.can_monitor_progress') +# .Next(this.complete_plan) +# ) +# +# complete_plan = ( +# flow_func(this.finalize_care_plan) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_care_planning) +# +# # Flow functions +# def start_care_planning(self, activation): +# """Initialize the care planning process""" +# process = activation.process +# plan = process.care_plan +# +# # Update plan status +# plan.status = 'DRAFT' +# plan.save() +# +# # Send notification to care team +# self.notify_care_planning_start(plan) +# +# def start_implementation(self, activation): +# """Start care plan implementation""" +# process = activation.process +# plan = process.care_plan +# +# # Update plan status +# plan.status = 'ACTIVE' +# plan.save() +# +# # Mark implementation started +# process.implementation_started = True +# process.save() +# +# # Notify care team of implementation +# self.notify_implementation_start(plan) +# +# # Schedule monitoring activities +# self.schedule_monitoring(plan) +# +# def finalize_care_plan(self, activation): +# """Finalize the care plan process""" +# process = activation.process +# plan = process.care_plan +# +# # Update plan status based on completion +# if plan.completion_percentage >= 100: +# plan.status = 'COMPLETED' +# else: +# plan.status = 'ON_HOLD' +# +# plan.save() +# +# # Mark process as completed +# process.plan_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_care_plan_completion(plan) +# +# # Generate outcomes report +# self.generate_outcomes_report(plan) +# +# def end_care_planning(self, activation): +# """End the care planning workflow""" +# process = activation.process +# +# # Generate care plan summary +# self.generate_care_plan_summary(process.care_plan) +# +# # Helper methods +# def notify_care_planning_start(self, plan): +# """Notify care team of care planning start""" +# care_team = plan.care_team.all() +# for member in care_team: +# if member.email: +# send_mail( +# subject=f'Care Plan Development: {plan.patient.get_full_name()}', +# message=f'Care plan development has started for {plan.title}.', +# from_email='careplanning@hospital.com', +# recipient_list=[member.email], +# fail_silently=True +# ) +# +# def notify_implementation_start(self, plan): +# """Notify care team of implementation start""" +# care_team = plan.care_team.all() +# for member in care_team: +# if member.email: +# send_mail( +# subject=f'Care Plan Implementation: {plan.patient.get_full_name()}', +# message=f'Care plan implementation has started for {plan.title}.', +# from_email='careplanning@hospital.com', +# recipient_list=[member.email], +# fail_silently=True +# ) +# +# def schedule_monitoring(self, plan): +# """Schedule monitoring activities""" +# # This would schedule monitoring tasks +# pass +# +# def notify_care_plan_completion(self, plan): +# """Notify care plan completion""" +# # Notify patient if email available +# if plan.patient.email: +# send_mail( +# subject='Care Plan Completed', +# message=f'Your care plan "{plan.title}" has been completed.', +# from_email='careplanning@hospital.com', +# recipient_list=[plan.patient.email], +# fail_silently=True +# ) +# +# def generate_outcomes_report(self, plan): +# """Generate care plan outcomes report""" +# # This would generate outcomes report +# pass +# +# def generate_care_plan_summary(self, plan): +# """Generate care plan summary""" +# # This would generate care plan summary +# pass +# +# +# class ProblemManagementProcess(Process): +# """ +# Viewflow process model for problem management +# """ +# problem = ModelField(ProblemList, help_text='Associated problem') +# +# # Process status tracking +# problem_identified = models.BooleanField(default=False) +# problem_assessed = models.BooleanField(default=False) +# treatment_planned = models.BooleanField(default=False) +# interventions_implemented = models.BooleanField(default=False) +# progress_monitored = models.BooleanField(default=False) +# problem_resolved = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Problem Management Process' +# verbose_name_plural = 'Problem Management Processes' +# +# +# class ProblemManagementFlow(Flow): +# """ +# Problem Management Workflow +# +# This flow manages clinical problem identification, assessment, +# treatment planning, and resolution tracking. +# """ +# +# process_class = ProblemManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_problem_management) +# .Next(this.identify_problem) +# ) +# +# identify_problem = ( +# flow_view(ProblemIdentificationView) +# .Permission('emr.can_identify_problems') +# .Next(this.assess_problem) +# ) +# +# assess_problem = ( +# flow_view(ProblemAssessmentView) +# .Permission('emr.can_assess_problems') +# .Next(this.plan_treatment) +# ) +# +# plan_treatment = ( +# flow_view(TreatmentPlanningView) +# .Permission('emr.can_plan_treatment') +# .Next(this.implement_interventions) +# ) +# +# implement_interventions = ( +# flow_view(InterventionImplementationView) +# .Permission('emr.can_implement_interventions') +# .Next(this.monitor_progress) +# ) +# +# monitor_progress = ( +# flow_view(ProgressMonitoringView) +# .Permission('emr.can_monitor_progress') +# .Next(this.resolve_problem) +# ) +# +# resolve_problem = ( +# flow_func(this.complete_problem_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_problem_management) +# +# # Flow functions +# def start_problem_management(self, activation): +# """Initialize the problem management process""" +# process = activation.process +# problem = process.problem +# +# # Update problem status +# problem.status = 'ACTIVE' +# problem.save() +# +# # Send notification to care team +# self.notify_problem_identified(problem) +# +# def complete_problem_management(self, activation): +# """Finalize the problem management process""" +# process = activation.process +# problem = process.problem +# +# # Update problem status +# if problem.resolution_date: +# problem.status = 'RESOLVED' +# else: +# problem.status = 'ONGOING' +# +# problem.save() +# +# # Mark process as completed +# process.problem_resolved = True +# process.save() +# +# # Send completion notifications +# self.notify_problem_resolution(problem) +# +# def end_problem_management(self, activation): +# """End the problem management workflow""" +# process = activation.process +# +# # Generate problem summary +# self.generate_problem_summary(process.problem) +# +# # Helper methods +# def notify_problem_identified(self, problem): +# """Notify care team of problem identification""" +# # This would notify the care team +# pass +# +# def notify_problem_resolution(self, problem): +# """Notify problem resolution""" +# # This would notify relevant parties +# pass +# +# def generate_problem_summary(self, problem): +# """Generate problem management summary""" +# # This would generate problem summary +# pass +# +# +# class QualityAssuranceProcess(Process): +# """ +# Viewflow process model for clinical quality assurance +# """ +# encounter_id = CharField(max_length=50, help_text='Encounter identifier') +# review_type = CharField(max_length=20, help_text='Type of quality review') +# +# # Process status tracking +# review_initiated = models.BooleanField(default=False) +# documentation_reviewed = models.BooleanField(default=False) +# clinical_indicators_checked = models.BooleanField(default=False) +# compliance_verified = models.BooleanField(default=False) +# feedback_provided = models.BooleanField(default=False) +# quality_review_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Quality Assurance Process' +# verbose_name_plural = 'Quality Assurance Processes' +# +# +# class QualityAssuranceFlow(Flow): +# """ +# Clinical Quality Assurance Workflow +# +# This flow manages clinical quality reviews including documentation +# quality, clinical indicators, and compliance verification. +# """ +# +# process_class = QualityAssuranceProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_quality_review) +# .Next(this.review_documentation) +# ) +# +# review_documentation = ( +# flow_view(DocumentationReviewView) +# .Permission('emr.can_review_documentation') +# .Next(this.check_clinical_indicators) +# ) +# +# check_clinical_indicators = ( +# flow_view(ClinicalIndicatorCheckView) +# .Permission('emr.can_check_clinical_indicators') +# .Next(this.verify_compliance) +# ) +# +# verify_compliance = ( +# flow_view(ComplianceVerificationView) +# .Permission('emr.can_verify_compliance') +# .Next(this.provide_feedback) +# ) +# +# provide_feedback = ( +# flow_view(QualityFeedbackView) +# .Permission('emr.can_provide_quality_feedback') +# .Next(this.complete_review) +# ) +# +# complete_review = ( +# flow_func(this.finalize_quality_review) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_quality_review) +# +# # Flow functions +# def start_quality_review(self, activation): +# """Initialize the quality review process""" +# process = activation.process +# +# # Notify quality staff +# self.notify_quality_staff(process.encounter_id, process.review_type) +# +# def finalize_quality_review(self, activation): +# """Finalize the quality review process""" +# process = activation.process +# +# # Mark review as completed +# process.quality_review_completed = True +# process.save() +# +# # Generate quality report +# self.generate_quality_report(process.encounter_id, process.review_type) +# +# def end_quality_review(self, activation): +# """End the quality review workflow""" +# process = activation.process +# +# # Update quality metrics +# self.update_quality_metrics(process.encounter_id, process.review_type) +# +# # Helper methods +# def notify_quality_staff(self, encounter_id, review_type): +# """Notify quality staff""" +# quality_staff = User.objects.filter( +# groups__name='Quality Assurance' +# ) +# +# for staff in quality_staff: +# send_mail( +# subject=f'Quality Review Required: {encounter_id}', +# message=f'{review_type} quality review required for encounter {encounter_id}.', +# from_email='quality@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_quality_report(self, encounter_id, review_type): +# """Generate quality report""" +# # This would generate quality report +# pass +# +# def update_quality_metrics(self, encounter_id, review_type): +# """Update quality metrics""" +# # This would update quality metrics +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_generate_care_plans(): +# """Background task to automatically generate care plans""" +# try: +# # This would generate care plans based on problems +# return True +# except Exception: +# return False +# +# +# @celery.job +# def monitor_documentation_compliance(): +# """Background task to monitor documentation compliance""" +# try: +# # This would monitor documentation timeliness +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_clinical_reports(): +# """Background task to generate clinical reports""" +# try: +# # This would generate clinical quality reports +# return True +# except Exception: +# return False +# +# +# @celery.job +# def auto_schedule_care_plan_reviews(): +# """Background task to schedule care plan reviews""" +# try: +# # This would schedule care plan reviews +# return True +# except Exception: +# return False +# +# +# @celery.job +# def identify_quality_indicators(): +# """Background task to identify quality indicators""" +# try: +# # This would identify quality improvement opportunities +# return True +# except Exception: +# return False +# diff --git a/emr/urls.py b/emr/urls.py index 71c27d78..3ca745f7 100644 --- a/emr/urls.py +++ b/emr/urls.py @@ -11,7 +11,7 @@ urlpatterns = [ # Main views path('', views.EMRDashboardView.as_view(), name='dashboard'), path('encounters/', views.EncounterListView.as_view(), name='encounter_list'), - path('encounters//', views.EncounterDetailView.as_view(), name='encounter_detail'), + path('encounters//', views.EncounterDetailView.as_view(), name='encounter_detail'), # path('encounters//update/', views.EncounterUpdateView.as_view(), name='encounter_update'), # path('encounters//delete/', views.EncounterDeleteView.as_view(), name='encounter_delete'), path('encounters/create/', views.EncounterCreateView.as_view(), name='encounter_create'), diff --git a/hospital_management/__pycache__/settings.cpython-312.pyc b/hospital_management/__pycache__/settings.cpython-312.pyc index dbcf00ebef3509152917c1f95a09b2c4c57c729f..fad854ec60fce3c3d5855a43c342def492bdff4a 100644 GIT binary patch delta 285 zcmX?PdEb)vG%qg~0}%XU-Io!*kyn(Rk!`XvyQStcS zIflK2g;8zuMeY^Mj4G3>_)8fTCV$}n%IGlpnSi^HBhWle<{}p$RpbgH+$Y-$iYj}7 zn4Taxrdu2tiFqkGsYS(LRY1kwAW4_W<%02y-ixmbGKxk41#WSB_?XAL`Z+rJxVmUE z6{$>qBQ#ea4J5awPoBWZ?Pxm=N0GYq!xLCq&y%}92tpu zDL}Deur8oxFOa139zi3Y|Ulb1*&bFhgpU0@LSB(RxZ@(eS}HlQ>Bb$doS diff --git a/hospital_management/settings.py b/hospital_management/settings.py index d5b04d12..41bce3d5 100644 --- a/hospital_management/settings.py +++ b/hospital_management/settings.py @@ -46,6 +46,8 @@ THIRD_PARTY_APPS = [ 'corsheaders', 'django_extensions', 'allauth', + 'viewflow', + 'viewflow.workflow', # 'allauth.socialaccount', ] diff --git a/hr/__pycache__/flows.cpython-312.pyc b/hr/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58e95d4ff79e7afc5837690f880f1b8cc1139209 GIT binary patch literal 172 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 delta 11208 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 E0KWdIQ~&?~ diff --git a/hr/__pycache__/views.cpython-312.pyc b/hr/__pycache__/views.cpython-312.pyc index 65d387e8e9558a41480f036df8d5b5288ea191ea..cedb4c60782ff109efd412ddda48de6a10c61266 100644 GIT binary patch delta 18975 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 delta 12184 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 diff --git a/hr/flows.py b/hr/flows.py new file mode 100644 index 00000000..4aefd4c2 --- /dev/null +++ b/hr/flows.py @@ -0,0 +1,846 @@ +# """ +# Viewflow workflows for HR app. +# Provides employee onboarding, performance review, and training 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 Employee, PerformanceReview, TrainingRecord +# from .views import ( +# EmployeeOnboardingView, DocumentCollectionView, SystemAccessSetupView, +# OrientationSchedulingView, PerformanceReviewInitiationView, +# SelfAssessmentView, ManagerReviewView, ReviewMeetingView, +# TrainingNeedsAssessmentView, TrainingSchedulingView, TrainingDeliveryView, +# TrainingEvaluationView +# ) +# +# +# class EmployeeOnboardingProcess(Process): +# """ +# Viewflow process model for employee onboarding +# """ +# employee = ModelField(Employee, help_text='Associated employee') +# +# # Process status tracking +# employee_created = models.BooleanField(default=False) +# documents_collected = models.BooleanField(default=False) +# system_access_setup = models.BooleanField(default=False) +# orientation_scheduled = models.BooleanField(default=False) +# orientation_completed = models.BooleanField(default=False) +# probationary_review_scheduled = models.BooleanField(default=False) +# onboarding_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Employee Onboarding Process' +# verbose_name_plural = 'Employee Onboarding Processes' +# +# +# class EmployeeOnboardingFlow(Flow): +# """ +# Employee Onboarding Workflow +# +# This flow manages the complete employee onboarding process from +# initial setup through orientation and probationary period setup. +# """ +# +# process_class = EmployeeOnboardingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_onboarding) +# .Next(this.create_employee_record) +# ) +# +# create_employee_record = ( +# flow_view(EmployeeOnboardingView) +# .Permission('hr.can_create_employees') +# .Next(this.collect_documents) +# ) +# +# collect_documents = ( +# flow_view(DocumentCollectionView) +# .Permission('hr.can_collect_documents') +# .Next(this.setup_system_access) +# ) +# +# setup_system_access = ( +# flow_view(SystemAccessSetupView) +# .Permission('hr.can_setup_system_access') +# .Next(this.schedule_orientation) +# ) +# +# schedule_orientation = ( +# flow_view(OrientationSchedulingView) +# .Permission('hr.can_schedule_orientation') +# .Next(this.conduct_orientation) +# ) +# +# conduct_orientation = ( +# flow_view(OrientationDeliveryView) +# .Permission('hr.can_conduct_orientation') +# .Next(this.schedule_probationary_review) +# ) +# +# schedule_probationary_review = ( +# flow_func(this.setup_probationary_review) +# .Next(this.finalize_onboarding) +# ) +# +# finalize_onboarding = ( +# flow_func(this.complete_onboarding) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_onboarding) +# +# # Flow functions +# def start_onboarding(self, activation): +# """Initialize the onboarding process""" +# process = activation.process +# employee = process.employee +# +# # Send welcome notification +# self.send_welcome_notification(employee) +# +# # Notify HR staff +# self.notify_hr_staff(employee) +# +# def setup_probationary_review(self, activation): +# """Setup probationary review""" +# process = activation.process +# employee = process.employee +# +# # Schedule probationary review (typically 90 days) +# review_date = timezone.now().date() + timezone.timedelta(days=90) +# +# # Create probationary review record +# PerformanceReview.objects.create( +# employee=employee, +# review_period_start=employee.hire_date, +# review_period_end=review_date, +# review_date=review_date, +# review_type='PROBATIONARY', +# status='DRAFT' +# ) +# +# process.probationary_review_scheduled = True +# process.save() +# +# # Notify manager +# self.notify_manager_probationary_review(employee, review_date) +# +# def complete_onboarding(self, activation): +# """Finalize the onboarding process""" +# process = activation.process +# employee = process.employee +# +# # Update employee status +# employee.employment_status = 'ACTIVE' +# employee.save() +# +# # Mark process as completed +# process.onboarding_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_onboarding_completion(employee) +# +# def end_onboarding(self, activation): +# """End the onboarding workflow""" +# process = activation.process +# +# # Generate onboarding summary report +# self.generate_onboarding_summary(process.employee) +# +# # Helper methods +# def send_welcome_notification(self, employee): +# """Send welcome notification to new employee""" +# if employee.email: +# send_mail( +# subject=f'Welcome to {employee.tenant.name}!', +# message=f'Welcome {employee.first_name}! Your onboarding process has begun.', +# from_email='hr@hospital.com', +# recipient_list=[employee.email], +# fail_silently=True +# ) +# +# def notify_hr_staff(self, employee): +# """Notify HR staff of new employee onboarding""" +# from django.contrib.auth.models import Group +# +# hr_staff = User.objects.filter( +# groups__name='HR Staff' +# ) +# +# for staff in hr_staff: +# send_mail( +# subject=f'New Employee Onboarding: {employee.get_full_name()}', +# message=f'New employee {employee.get_full_name()} onboarding has started.', +# from_email='hr@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_manager_probationary_review(self, employee, review_date): +# """Notify manager of upcoming probationary review""" +# if employee.manager and employee.manager.email: +# send_mail( +# subject=f'Probationary Review Scheduled: {employee.get_full_name()}', +# message=f'Probationary review scheduled for {review_date}.', +# from_email='hr@hospital.com', +# recipient_list=[employee.manager.email], +# fail_silently=True +# ) +# +# def notify_onboarding_completion(self, employee): +# """Notify relevant parties of onboarding completion""" +# # Notify employee +# if employee.email: +# send_mail( +# subject='Onboarding Complete', +# message=f'Congratulations {employee.first_name}! Your onboarding is complete.', +# from_email='hr@hospital.com', +# recipient_list=[employee.email], +# fail_silently=True +# ) +# +# # Notify manager +# if employee.manager and employee.manager.email: +# send_mail( +# subject=f'Employee Onboarding Complete: {employee.get_full_name()}', +# message=f'{employee.get_full_name()} has completed onboarding.', +# from_email='hr@hospital.com', +# recipient_list=[employee.manager.email], +# fail_silently=True +# ) +# +# def generate_onboarding_summary(self, employee): +# """Generate onboarding summary report""" +# # This would generate a comprehensive onboarding report +# pass +# +# +# class PerformanceReviewProcess(Process): +# """ +# Viewflow process model for performance reviews +# """ +# performance_review = ModelField(PerformanceReview, help_text='Associated performance review') +# +# # Process status tracking +# review_initiated = models.BooleanField(default=False) +# self_assessment_completed = models.BooleanField(default=False) +# manager_review_completed = models.BooleanField(default=False) +# review_meeting_held = models.BooleanField(default=False) +# employee_acknowledged = models.BooleanField(default=False) +# development_plan_created = models.BooleanField(default=False) +# review_finalized = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Performance Review Process' +# verbose_name_plural = 'Performance Review Processes' +# +# +# class PerformanceReviewFlow(Flow): +# """ +# Performance Review Workflow +# +# This flow manages the complete performance review process including +# self-assessment, manager review, meeting, and development planning. +# """ +# +# process_class = PerformanceReviewProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_performance_review) +# .Next(this.initiate_review) +# ) +# +# initiate_review = ( +# flow_view(PerformanceReviewInitiationView) +# .Permission('hr.can_initiate_reviews') +# .Next(this.employee_self_assessment) +# ) +# +# employee_self_assessment = ( +# flow_view(SelfAssessmentView) +# .Permission('hr.can_complete_self_assessment') +# .Next(this.manager_review) +# ) +# +# manager_review = ( +# flow_view(ManagerReviewView) +# .Permission('hr.can_conduct_manager_review') +# .Next(this.review_meeting) +# ) +# +# review_meeting = ( +# flow_view(ReviewMeetingView) +# .Permission('hr.can_conduct_review_meeting') +# .Next(this.employee_acknowledgment) +# ) +# +# employee_acknowledgment = ( +# flow_view(EmployeeAcknowledgmentView) +# .Permission('hr.can_acknowledge_review') +# .Next(this.create_development_plan) +# ) +# +# create_development_plan = ( +# flow_view(DevelopmentPlanView) +# .Permission('hr.can_create_development_plan') +# .Next(this.finalize_review) +# ) +# +# finalize_review = ( +# flow_func(this.complete_performance_review) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_performance_review) +# +# # Flow functions +# def start_performance_review(self, activation): +# """Initialize the performance review process""" +# process = activation.process +# review = process.performance_review +# +# # Update review status +# review.status = 'IN_PROGRESS' +# review.save() +# +# # Notify employee and manager +# self.notify_review_start(review) +# +# def complete_performance_review(self, activation): +# """Finalize the performance review process""" +# process = activation.process +# review = process.performance_review +# +# # Update review status +# review.status = 'COMPLETED' +# review.save() +# +# # Mark process as completed +# process.review_finalized = True +# process.save() +# +# # Schedule next review +# self.schedule_next_review(review) +# +# # Send completion notifications +# self.notify_review_completion(review) +# +# def end_performance_review(self, activation): +# """End the performance review workflow""" +# process = activation.process +# +# # Generate review summary report +# self.generate_review_summary(process.performance_review) +# +# # Helper methods +# def notify_review_start(self, review): +# """Notify employee and manager of review start""" +# # Notify employee +# if review.employee.email: +# send_mail( +# subject='Performance Review Started', +# message=f'Your {review.get_review_type_display()} has been initiated.', +# from_email='hr@hospital.com', +# recipient_list=[review.employee.email], +# fail_silently=True +# ) +# +# # Notify manager +# if review.employee.manager and review.employee.manager.email: +# send_mail( +# subject=f'Performance Review: {review.employee.get_full_name()}', +# message=f'Performance review for {review.employee.get_full_name()} has started.', +# from_email='hr@hospital.com', +# recipient_list=[review.employee.manager.email], +# fail_silently=True +# ) +# +# def schedule_next_review(self, review): +# """Schedule next performance review""" +# if review.review_type == 'ANNUAL': +# # Schedule next annual review +# next_review_date = review.review_date + timezone.timedelta(days=365) +# +# PerformanceReview.objects.create( +# employee=review.employee, +# review_period_start=review.review_period_end + timezone.timedelta(days=1), +# review_period_end=next_review_date, +# review_date=next_review_date, +# review_type='ANNUAL', +# status='DRAFT' +# ) +# +# def notify_review_completion(self, review): +# """Notify relevant parties of review completion""" +# # Notify employee +# if review.employee.email: +# send_mail( +# subject='Performance Review Complete', +# message=f'Your {review.get_review_type_display()} has been completed.', +# from_email='hr@hospital.com', +# recipient_list=[review.employee.email], +# fail_silently=True +# ) +# +# # Notify HR +# hr_staff = User.objects.filter(groups__name='HR Staff') +# for staff in hr_staff: +# send_mail( +# subject=f'Performance Review Complete: {review.employee.get_full_name()}', +# message=f'Performance review for {review.employee.get_full_name()} has been completed.', +# from_email='hr@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_review_summary(self, review): +# """Generate performance review summary report""" +# # This would generate a comprehensive review report +# pass +# +# +# class TrainingProcess(Process): +# """ +# Viewflow process model for training programs +# """ +# training_record = ModelField(TrainingRecord, help_text='Associated training record') +# +# # Process status tracking +# training_needs_assessed = models.BooleanField(default=False) +# training_scheduled = models.BooleanField(default=False) +# training_delivered = models.BooleanField(default=False) +# training_evaluated = models.BooleanField(default=False) +# certification_issued = models.BooleanField(default=False) +# follow_up_scheduled = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Training Process' +# verbose_name_plural = 'Training Processes' +# +# +# class TrainingFlow(Flow): +# """ +# Training Workflow +# +# This flow manages training programs including needs assessment, +# scheduling, delivery, evaluation, and certification. +# """ +# +# process_class = TrainingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_training) +# .Next(this.assess_training_needs) +# ) +# +# assess_training_needs = ( +# flow_view(TrainingNeedsAssessmentView) +# .Permission('hr.can_assess_training_needs') +# .Next(this.schedule_training) +# ) +# +# schedule_training = ( +# flow_view(TrainingSchedulingView) +# .Permission('hr.can_schedule_training') +# .Next(this.deliver_training) +# ) +# +# deliver_training = ( +# flow_view(TrainingDeliveryView) +# .Permission('hr.can_deliver_training') +# .Next(this.evaluate_training) +# ) +# +# evaluate_training = ( +# flow_view(TrainingEvaluationView) +# .Permission('hr.can_evaluate_training') +# .Next(this.issue_certification) +# ) +# +# issue_certification = ( +# flow_func(this.process_certification) +# .Next(this.schedule_follow_up) +# ) +# +# schedule_follow_up = ( +# flow_func(this.setup_follow_up) +# .Next(this.finalize_training) +# ) +# +# finalize_training = ( +# flow_func(this.complete_training) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_training) +# +# # Flow functions +# def start_training(self, activation): +# """Initialize the training process""" +# process = activation.process +# training = process.training_record +# +# # Update training status +# training.status = 'SCHEDULED' +# training.save() +# +# # Notify employee and manager +# self.notify_training_start(training) +# +# def process_certification(self, activation): +# """Process certification if training passed""" +# process = activation.process +# training = process.training_record +# +# if training.passed and training.training_type == 'CERTIFICATION': +# # Generate certificate number +# training.certificate_number = self.generate_certificate_number() +# training.save() +# +# process.certification_issued = True +# process.save() +# +# # Notify employee of certification +# self.notify_certification_issued(training) +# +# def setup_follow_up(self, activation): +# """Setup follow-up training if needed""" +# process = activation.process +# training = process.training_record +# +# # Schedule follow-up based on training type +# if training.training_type in ['CERTIFICATION', 'MANDATORY']: +# if training.expiry_date: +# # Schedule renewal training +# renewal_date = training.expiry_date - timezone.timedelta(days=30) +# self.schedule_renewal_training(training, renewal_date) +# +# process.follow_up_scheduled = True +# process.save() +# +# def complete_training(self, activation): +# """Finalize the training process""" +# process = activation.process +# training = process.training_record +# +# # Update training status +# if training.passed: +# training.status = 'COMPLETED' +# else: +# training.status = 'FAILED' +# +# training.completion_date = timezone.now().date() +# training.save() +# +# # Send completion notifications +# self.notify_training_completion(training) +# +# def end_training(self, activation): +# """End the training workflow""" +# process = activation.process +# +# # Generate training summary report +# self.generate_training_summary(process.training_record) +# +# # Helper methods +# def notify_training_start(self, training): +# """Notify employee and manager of training start""" +# # Notify employee +# if training.employee.email: +# send_mail( +# subject=f'Training Scheduled: {training.training_name}', +# message=f'Your training "{training.training_name}" has been scheduled for {training.training_date}.', +# from_email='hr@hospital.com', +# recipient_list=[training.employee.email], +# fail_silently=True +# ) +# +# # Notify manager +# if training.employee.manager and training.employee.manager.email: +# send_mail( +# subject=f'Employee Training: {training.employee.get_full_name()}', +# message=f'{training.employee.get_full_name()} has training scheduled: {training.training_name}.', +# from_email='hr@hospital.com', +# recipient_list=[training.employee.manager.email], +# fail_silently=True +# ) +# +# def generate_certificate_number(self): +# """Generate unique certificate number""" +# from django.utils.crypto import get_random_string +# return f"CERT{timezone.now().strftime('%Y%m%d')}{get_random_string(4, '0123456789')}" +# +# def notify_certification_issued(self, training): +# """Notify employee of certification""" +# if training.employee.email: +# send_mail( +# subject=f'Certification Issued: {training.training_name}', +# message=f'Congratulations! You have been certified in {training.training_name}. Certificate #: {training.certificate_number}', +# from_email='hr@hospital.com', +# recipient_list=[training.employee.email], +# fail_silently=True +# ) +# +# def schedule_renewal_training(self, training, renewal_date): +# """Schedule renewal training""" +# TrainingRecord.objects.create( +# employee=training.employee, +# training_name=f"{training.training_name} - Renewal", +# training_type=training.training_type, +# training_date=renewal_date, +# status='SCHEDULED' +# ) +# +# def notify_training_completion(self, training): +# """Notify relevant parties of training completion""" +# # Notify employee +# if training.employee.email: +# status_text = "completed successfully" if training.passed else "not passed" +# send_mail( +# subject=f'Training {status_text.title()}: {training.training_name}', +# message=f'Your training "{training.training_name}" has been {status_text}.', +# from_email='hr@hospital.com', +# recipient_list=[training.employee.email], +# fail_silently=True +# ) +# +# def generate_training_summary(self, training): +# """Generate training summary report""" +# # This would generate a comprehensive training report +# pass +# +# +# class ComplianceTrackingProcess(Process): +# """ +# Viewflow process model for compliance tracking +# """ +# employee_id = CharField(max_length=50, help_text='Employee identifier') +# compliance_type = CharField(max_length=20, help_text='Type of compliance') +# +# # Process status tracking +# compliance_checked = models.BooleanField(default=False) +# deficiencies_identified = models.BooleanField(default=False) +# corrective_actions_planned = models.BooleanField(default=False) +# actions_implemented = models.BooleanField(default=False) +# compliance_verified = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Compliance Tracking Process' +# verbose_name_plural = 'Compliance Tracking Processes' +# +# +# class ComplianceTrackingFlow(Flow): +# """ +# Compliance Tracking Workflow +# +# This flow manages compliance tracking including monitoring, +# deficiency identification, and corrective actions. +# """ +# +# process_class = ComplianceTrackingProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_compliance_tracking) +# .Next(this.check_compliance) +# ) +# +# check_compliance = ( +# flow_func(this.monitor_compliance) +# .Next(this.identify_deficiencies) +# ) +# +# identify_deficiencies = ( +# flow_func(this.assess_deficiencies) +# .Next(this.plan_corrective_actions) +# ) +# +# plan_corrective_actions = ( +# flow_view(CorrectiveActionPlanningView) +# .Permission('hr.can_plan_corrective_actions') +# .Next(this.implement_actions) +# ) +# +# implement_actions = ( +# flow_view(CorrectiveActionImplementationView) +# .Permission('hr.can_implement_corrective_actions') +# .Next(this.verify_compliance) +# ) +# +# verify_compliance = ( +# flow_func(this.validate_compliance) +# .Next(this.finalize_compliance) +# ) +# +# finalize_compliance = ( +# flow_func(this.complete_compliance_tracking) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_compliance_tracking) +# +# # Flow functions +# def start_compliance_tracking(self, activation): +# """Initialize the compliance tracking process""" +# process = activation.process +# +# # Log compliance check initiation +# self.log_compliance_check(process.employee_id, process.compliance_type) +# +# def monitor_compliance(self, activation): +# """Monitor employee compliance""" +# process = activation.process +# +# # Check compliance status +# compliance_status = self.check_employee_compliance(process.employee_id, process.compliance_type) +# +# process.compliance_checked = True +# process.save() +# +# if not compliance_status: +# # Alert of compliance issues +# self.alert_compliance_issues(process.employee_id, process.compliance_type) +# +# def assess_deficiencies(self, activation): +# """Assess compliance deficiencies""" +# process = activation.process +# +# # Identify specific deficiencies +# deficiencies = self.identify_compliance_deficiencies(process.employee_id, process.compliance_type) +# +# if deficiencies: +# process.deficiencies_identified = True +# process.save() +# +# # Notify relevant parties +# self.notify_compliance_deficiencies(process.employee_id, deficiencies) +# +# def validate_compliance(self, activation): +# """Validate compliance after corrective actions""" +# process = activation.process +# +# # Re-check compliance +# compliance_status = self.check_employee_compliance(process.employee_id, process.compliance_type) +# +# if compliance_status: +# process.compliance_verified = True +# process.save() +# else: +# # Escalate if still non-compliant +# self.escalate_compliance_issue(process.employee_id, process.compliance_type) +# +# def complete_compliance_tracking(self, activation): +# """Finalize the compliance tracking process""" +# process = activation.process +# +# # Generate compliance report +# self.generate_compliance_report(process.employee_id, process.compliance_type) +# +# def end_compliance_tracking(self, activation): +# """End the compliance tracking workflow""" +# process = activation.process +# +# # Archive compliance tracking +# self.archive_compliance_tracking(process.employee_id, process.compliance_type) +# +# # Helper methods +# def log_compliance_check(self, employee_id, compliance_type): +# """Log compliance check""" +# # This would log the compliance check +# pass +# +# def check_employee_compliance(self, employee_id, compliance_type): +# """Check employee compliance status""" +# # This would check compliance status +# return True +# +# def alert_compliance_issues(self, employee_id, compliance_type): +# """Alert of compliance issues""" +# # This would send compliance alerts +# pass +# +# def identify_compliance_deficiencies(self, employee_id, compliance_type): +# """Identify specific compliance deficiencies""" +# # This would identify deficiencies +# return [] +# +# def notify_compliance_deficiencies(self, employee_id, deficiencies): +# """Notify of compliance deficiencies""" +# # This would send deficiency notifications +# pass +# +# def escalate_compliance_issue(self, employee_id, compliance_type): +# """Escalate compliance issue""" +# # This would escalate the issue +# pass +# +# def generate_compliance_report(self, employee_id, compliance_type): +# """Generate compliance report""" +# # This would generate compliance report +# pass +# +# def archive_compliance_tracking(self, employee_id, compliance_type): +# """Archive compliance tracking""" +# # This would archive the tracking +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_schedule_performance_reviews(): +# """Background task to automatically schedule performance reviews""" +# try: +# # This would schedule upcoming reviews +# return True +# except Exception: +# return False +# +# +# @celery.job +# def monitor_training_expiry(): +# """Background task to monitor training and certification expiry""" +# try: +# # This would monitor expiring certifications +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_hr_compliance_report(): +# """Background task to generate HR compliance reports""" +# try: +# # This would generate compliance reports +# return True +# except Exception: +# return False +# +# +# @celery.job +# def auto_assign_mandatory_training(): +# """Background task to automatically assign mandatory training""" +# try: +# # This would assign mandatory training +# return True +# except Exception: +# return False +# diff --git a/hr/migrations/0002_trainingrecord_is_certified.py b/hr/migrations/0002_trainingrecord_is_certified.py new file mode 100644 index 00000000..e80a416d --- /dev/null +++ b/hr/migrations/0002_trainingrecord_is_certified.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.4 on 2025-09-07 14:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("hr", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="trainingrecord", + name="is_certified", + field=models.BooleanField(default=False, help_text="Training is certified"), + ), + ] diff --git a/hr/migrations/__pycache__/0002_trainingrecord_is_certified.cpython-312.pyc b/hr/migrations/__pycache__/0002_trainingrecord_is_certified.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d772d2943cfc93f415995d2823ff331590f18e9 GIT binary patch literal 808 zcmY*XJ#P~+7`E>&m%CG1wGpVGRBDF?l%*FCBPt(5kq~s^L%PLsV>fZ+`>1`PgbAb$ zjGgEoU;wonGrxd^NJxpiGOQ2}Z;rUMt zwOO~(WslHBi#D^qFt4Ks2FUw59D=b6{I#)dU2)$&83({$eIE?H+Q6%gR&I`#*GAR) z(T!oXKB(3|(eL+O{HVS>D?5HLw%w}x?y 0: + return (self.employee_count / self.authorized_positions) * 100 + return 0 + + def get_all_sub_departments(self): + """Get all sub-departments recursively""" + sub_departments = [] + for sub_dept in self.sub_departments.all(): + sub_departments.append(sub_dept) + sub_departments.extend(sub_dept.get_all_sub_departments()) + return sub_departments + class Schedule(models.Model): """ Schedule model for employee work schedules. """ - + SCHEDULE_TYPE_CHOICES = [ + ('REGULAR', 'Regular Schedule'), + ('ROTATING', 'Rotating Schedule'), + ('FLEXIBLE', 'Flexible Schedule'), + ('ON_CALL', 'On-Call Schedule'), + ('TEMPORARY', 'Temporary Schedule'), + ] # Employee relationship employee = models.ForeignKey( Employee, @@ -566,13 +655,7 @@ class Schedule(models.Model): # Schedule Type schedule_type = models.CharField( max_length=20, - choices=[ - ('REGULAR', 'Regular Schedule'), - ('ROTATING', 'Rotating Schedule'), - ('FLEXIBLE', 'Flexible Schedule'), - ('ON_CALL', 'On-Call Schedule'), - ('TEMPORARY', 'Temporary Schedule'), - ], + choices=SCHEDULE_TYPE_CHOICES, help_text='Schedule type' ) @@ -668,7 +751,23 @@ class ScheduleAssignment(models.Model): """ Schedule assignment model for specific shift assignments. """ - + SHIFT_TYPE_CHOICES = [ + ('DAY', 'Day Shift'), + ('EVENING', 'Evening Shift'), + ('NIGHT', 'Night Shift'), + ('WEEKEND', 'Weekend Shift'), + ('HOLIDAY', 'Holiday Shift'), + ('ON_CALL', 'On-Call'), + ('OVERTIME', 'Overtime'), + ] + STATUS_CHOICES = [ + ('SCHEDULED', 'Scheduled'), + ('CONFIRMED', 'Confirmed'), + ('COMPLETED', 'Completed'), + ('CANCELLED', 'Cancelled'), + ('NO_SHOW', 'No Show'), + ] + # Schedule relationship schedule = models.ForeignKey( Schedule, @@ -699,15 +798,7 @@ class ScheduleAssignment(models.Model): # Shift Information shift_type = models.CharField( max_length=20, - choices=[ - ('DAY', 'Day Shift'), - ('EVENING', 'Evening Shift'), - ('NIGHT', 'Night Shift'), - ('WEEKEND', 'Weekend Shift'), - ('HOLIDAY', 'Holiday Shift'), - ('ON_CALL', 'On-Call'), - ('OVERTIME', 'Overtime'), - ], + choices=SHIFT_TYPE_CHOICES, help_text='Shift type' ) @@ -730,13 +821,7 @@ class ScheduleAssignment(models.Model): # Assignment Status status = models.CharField( max_length=20, - choices=[ - ('SCHEDULED', 'Scheduled'), - ('CONFIRMED', 'Confirmed'), - ('COMPLETED', 'Completed'), - ('CANCELLED', 'Cancelled'), - ('NO_SHOW', 'No Show'), - ], + choices=STATUS_CHOICES, default='SCHEDULED', help_text='Assignment status' ) @@ -812,7 +897,25 @@ class TimeEntry(models.Model): """ Time entry model for tracking actual work hours. """ - + ENTRY_TYPE_CHOICES = [ + ('REGULAR', 'Regular Time'), + ('OVERTIME', 'Overtime'), + ('HOLIDAY', 'Holiday'), + ('VACATION', 'Vacation'), + ('SICK', 'Sick Leave'), + ('PERSONAL', 'Personal Time'), + ('BEREAVEMENT', 'Bereavement'), + ('JURY_DUTY', 'Jury Duty'), + ('TRAINING', 'Training'), + ] + STATUS_CHOICES = [ + ('DRAFT', 'Draft'), + ('SUBMITTED', 'Submitted'), + ('APPROVED', 'Approved'), + ('REJECTED', 'Rejected'), + ('PAID', 'Paid'), + ] + # Employee relationship employee = models.ForeignKey( Employee, @@ -889,17 +992,7 @@ class TimeEntry(models.Model): # Entry Type entry_type = models.CharField( max_length=20, - choices=[ - ('REGULAR', 'Regular Time'), - ('OVERTIME', 'Overtime'), - ('HOLIDAY', 'Holiday'), - ('VACATION', 'Vacation'), - ('SICK', 'Sick Leave'), - ('PERSONAL', 'Personal Time'), - ('BEREAVEMENT', 'Bereavement'), - ('JURY_DUTY', 'Jury Duty'), - ('TRAINING', 'Training'), - ], + choices=ENTRY_TYPE_CHOICES, default='REGULAR', help_text='Entry type' ) @@ -938,13 +1031,7 @@ class TimeEntry(models.Model): # Entry Status status = models.CharField( max_length=20, - choices=[ - ('DRAFT', 'Draft'), - ('SUBMITTED', 'Submitted'), - ('APPROVED', 'Approved'), - ('REJECTED', 'Rejected'), - ('PAID', 'Paid'), - ], + choices=STATUS_CHOICES, default='DRAFT', help_text='Entry status' ) @@ -1024,7 +1111,21 @@ class PerformanceReview(models.Model): """ Performance review model for employee evaluations. """ - + REVIEW_TYPE_CHOICES = [ + ('ANNUAL', 'Annual Review'), + ('PROBATIONARY', 'Probationary Review'), + ('MID_YEAR', 'Mid-Year Review'), + ('PROJECT', 'Project Review'), + ('DISCIPLINARY', 'Disciplinary Review'), + ('PROMOTION', 'Promotion Review'), + ] + STATUS_CHOICES = [ + ('DRAFT', 'Draft'), + ('IN_PROGRESS', 'In Progress'), + ('COMPLETED', 'Completed'), + ('ACKNOWLEDGED', 'Acknowledged by Employee'), + ('DISPUTED', 'Disputed'), + ] # Employee relationship employee = models.ForeignKey( Employee, @@ -1055,14 +1156,7 @@ class PerformanceReview(models.Model): # Review Type review_type = models.CharField( max_length=20, - choices=[ - ('ANNUAL', 'Annual Review'), - ('PROBATIONARY', 'Probationary Review'), - ('MID_YEAR', 'Mid-Year Review'), - ('PROJECT', 'Project Review'), - ('DISCIPLINARY', 'Disciplinary Review'), - ('PROMOTION', 'Promotion Review'), - ], + choices=REVIEW_TYPE_CHOICES, help_text='Review type' ) @@ -1146,13 +1240,7 @@ class PerformanceReview(models.Model): # Review Status status = models.CharField( max_length=20, - choices=[ - ('DRAFT', 'Draft'), - ('IN_PROGRESS', 'In Progress'), - ('COMPLETED', 'Completed'), - ('ACKNOWLEDGED', 'Acknowledged by Employee'), - ('DISPUTED', 'Disputed'), - ], + choices=STATUS_CHOICES, default='DRAFT', help_text='Review status' ) @@ -1204,7 +1292,26 @@ class TrainingRecord(models.Model): """ Training record model for employee training and certifications. """ - + TRAINING_TYPE_CHOICES = [ + ('ORIENTATION', 'Orientation'), + ('MANDATORY', 'Mandatory Training'), + ('CONTINUING_ED', 'Continuing Education'), + ('CERTIFICATION', 'Certification'), + ('SKILLS', 'Skills Training'), + ('SAFETY', 'Safety Training'), + ('COMPLIANCE', 'Compliance Training'), + ('LEADERSHIP', 'Leadership Development'), + ('TECHNICAL', 'Technical Training'), + ('OTHER', 'Other'), + ] + STATUS_CHOICES = [ + ('SCHEDULED', 'Scheduled'), + ('IN_PROGRESS', 'In Progress'), + ('COMPLETED', 'Completed'), + ('CANCELLED', 'Cancelled'), + ('NO_SHOW', 'No Show'), + ('FAILED', 'Failed'), + ] # Employee relationship employee = models.ForeignKey( Employee, @@ -1229,25 +1336,14 @@ class TrainingRecord(models.Model): null=True, help_text='Training description' ) - + # Training Type training_type = models.CharField( max_length=20, - choices=[ - ('ORIENTATION', 'Orientation'), - ('MANDATORY', 'Mandatory Training'), - ('CONTINUING_ED', 'Continuing Education'), - ('CERTIFICATION', 'Certification'), - ('SKILLS', 'Skills Training'), - ('SAFETY', 'Safety Training'), - ('COMPLIANCE', 'Compliance Training'), - ('LEADERSHIP', 'Leadership Development'), - ('TECHNICAL', 'Technical Training'), - ('OTHER', 'Other'), - ], + choices=TRAINING_TYPE_CHOICES, help_text='Training type' ) - + # Training Provider training_provider = models.CharField( max_length=200, @@ -1261,7 +1357,7 @@ class TrainingRecord(models.Model): null=True, help_text='Instructor name' ) - + # Training Dates training_date = models.DateField( help_text='Training date' @@ -1294,14 +1390,7 @@ class TrainingRecord(models.Model): # Training Status status = models.CharField( max_length=20, - choices=[ - ('SCHEDULED', 'Scheduled'), - ('IN_PROGRESS', 'In Progress'), - ('COMPLETED', 'Completed'), - ('CANCELLED', 'Cancelled'), - ('NO_SHOW', 'No Show'), - ('FAILED', 'Failed'), - ], + choices=STATUS_CHOICES, default='SCHEDULED', help_text='Training status' ) @@ -1318,7 +1407,10 @@ class TrainingRecord(models.Model): default=False, help_text='Training passed' ) - + is_certified = models.BooleanField( + default=False, + help_text='Training is certified' + ) # Certification Information certificate_number = models.CharField( max_length=50, @@ -1409,3 +1501,411 @@ class TrainingRecord(models.Model): return (self.expiry_date - date.today()).days <= 30 return False + +# class TrainingPrograms(models.Model): +# PROGRAM_TYPE_CHOICES = [ +# ('ORIENTATION', 'Orientation'), +# ('MANDATORY', 'Mandatory Training'), +# ('CONTINUING_ED', 'Continuing Education'), +# ('CERTIFICATION', 'Certification'), +# ('SKILLS', 'Skills Training'), +# ('SAFETY', 'Safety Training'), +# ('COMPLIANCE', 'Compliance Training'), +# ('LEADERSHIP', 'Leadership Development'), +# ('TECHNICAL', 'Technical Training'), +# ('OTHER', 'Other'), +# ] +# +# # Multi-tenancy +# tenant = models.ForeignKey( +# 'core.Tenant', on_delete=models.CASCADE, related_name='training_programs' +# ) +# +# program_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) +# name = models.CharField(max_length=200) +# description = models.TextField(blank=True, null=True) +# program_type = models.CharField(max_length=20, choices=PROGRAM_TYPE_CHOICES) +# +# # Provider/Instructor at the program (defaults; sessions can override) +# program_provider = models.CharField(max_length=200, blank=True, null=True) +# default_instructor = models.ForeignKey( +# Employee, on_delete=models.SET_NULL, null=True, blank=True, +# related_name='default_instructor_programs', +# help_text='Default instructor; sessions may override' +# ) +# +# # Optional “program window” (e.g., for long initiatives) +# start_date = models.DateField(help_text='Program start date', blank=True, null=True) +# end_date = models.DateField(help_text='Program end date', blank=True, null=True) +# +# duration_hours = models.DecimalField(max_digits=5, decimal_places=2, +# default=Decimal('0.00')) +# cost = models.DecimalField(max_digits=10, decimal_places=2, +# default=Decimal('0.00')) +# is_certified = models.BooleanField(default=False) +# +# # Renewal/expiry policy (applies if is_certified) +# validity_days = models.PositiveIntegerField( +# blank=True, null=True, +# help_text='Days certificate is valid from completion (e.g., 365).' +# ) +# notify_before_days = models.PositiveIntegerField( +# blank=True, null=True, +# help_text='Days before expiry to flag for renewal.' +# ) +# +# # Metadata +# created_at = models.DateTimeField(auto_now_add=True) +# updated_at = models.DateTimeField(auto_now=True) +# created_by = models.ForeignKey( +# settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, +# null=True, blank=True, related_name='created_training_programs' +# ) +# +# class Meta: +# db_table = 'hr_training_program' +# ordering = ['name'] +# unique_together = [('tenant', 'name')] +# indexes = [ +# models.Index(fields=['tenant', 'program_type']), +# models.Index(fields=['tenant', 'is_certified']), +# ] +# +# def clean(self): +# if self.start_date and self.end_date and self.end_date < self.start_date: +# raise ValidationError(_('Program end_date cannot be before start_date.')) +# if self.is_certified and not self.validity_days: +# # Not hard error—could be open-ended—but warn as best practice. +# pass +# +# def __str__(self): +# return f'{self.name} ({self.get_program_type_display()})' +# +# +# class ProgramModule(models.Model): +# """Optional content structure for a program.""" +# program = models.ForeignKey( +# TrainingPrograms, on_delete=models.CASCADE, related_name='modules' +# ) +# title = models.CharField(max_length=200) +# order = models.PositiveIntegerField(default=1) +# hours = models.DecimalField(max_digits=5, decimal_places=2, +# default=Decimal('0.00')) +# +# class Meta: +# db_table = 'hr_training_program_module' +# ordering = ['program', 'order'] +# unique_together = [('program', 'order')] +# indexes = [models.Index(fields=['program', 'order'])] +# +# def __str__(self): +# return f'{self.program.name} · {self.order}. {self.title}' +# +# +# class ProgramPrerequisite(models.Model): +# """A program may require completion of other program(s).""" +# program = models.ForeignKey( +# TrainingPrograms, on_delete=models.CASCADE, related_name='prerequisites' +# ) +# required_program = models.ForeignKey( +# TrainingPrograms, on_delete=models.CASCADE, related_name='unlocking_programs' +# ) +# +# class Meta: +# db_table = 'hr_training_program_prerequisite' +# unique_together = [('program', 'required_program')] +# +# def clean(self): +# if self.program_id == self.required_program_id: +# raise ValidationError(_('Program cannot require itself.')) +# +# +# class TrainingSession(models.Model): +# """ +# A scheduled run of a program (cohort/class). +# """ +# DELIVERY_CHOICES = [ +# ('IN_PERSON', 'In-person'), +# ('VIRTUAL', 'Virtual'), +# ('HYBRID', 'Hybrid'), +# ('SELF_PACED', 'Self-paced'), +# ] +# +# tenant = models.ForeignKey( +# Tenant, on_delete=models.CASCADE, related_name='training_sessions' +# ) +# session_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) +# program = models.ForeignKey( +# TrainingPrograms, on_delete=models.CASCADE, related_name='sessions' +# ) +# title = models.CharField( +# max_length=200, blank=True, null=True, +# help_text='Optional run title; falls back to program name' +# ) +# instructor = models.ForeignKey( +# Employee, on_delete=models.SET_NULL, null=True, blank=True, +# related_name='instructed_sessions' +# ) +# delivery_method = models.CharField(max_length=12, choices=DELIVERY_CHOICES, default='IN_PERSON') +# +# # Schedule +# start_at = models.DateTimeField() +# end_at = models.DateTimeField() +# location = models.CharField(max_length=200, blank=True, null=True) +# capacity = models.PositiveIntegerField(default=0) +# +# # Overrides +# cost_override = models.DecimalField(max_digits=10, decimal_places=2, +# blank=True, null=True) +# hours_override = models.DecimalField(max_digits=5, decimal_places=2, +# blank=True, null=True) +# +# # Metadata +# created_at = models.DateTimeField(auto_now_add=True) +# created_by = models.ForeignKey( +# settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, +# null=True, blank=True, related_name='created_training_sessions' +# ) +# +# class Meta: +# db_table = 'hr_training_session' +# ordering = ['-start_at'] +# indexes = [ +# models.Index(fields=['tenant', 'start_at']), +# models.Index(fields=['tenant', 'program']), +# ] +# constraints = [ +# models.CheckConstraint( +# check=models.Q(end_at__gt=models.F('start_at')), +# name='session_end_after_start' +# ), +# ] +# +# def __str__(self): +# return self.title or f'{self.program.name} @ {self.start_at:%Y-%m-%d}' +# +# +# class TrainingRecord(models.Model): +# """ +# Enrollment/participation record (renamed semantic, kept class name). +# Each row = an employee participating in a specific session of a program. +# """ +# STATUS_CHOICES = [ +# ('SCHEDULED', 'Scheduled'), +# ('IN_PROGRESS', 'In Progress'), +# ('COMPLETED', 'Completed'), +# ('CANCELLED', 'Cancelled'), +# ('NO_SHOW', 'No Show'), +# ('FAILED', 'Failed'), +# ('WAITLISTED', 'Waitlisted'), +# ] +# +# tenant = models.ForeignKey( +# Tenant, on_delete=models.CASCADE, related_name='training_records' +# ) +# record_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) +# +# # Core links +# employee = models.ForeignKey( +# Employee, on_delete=models.CASCADE, related_name='training_records' +# ) +# program = models.ForeignKey( +# TrainingPrograms, on_delete=models.PROTECT, related_name='training_records' +# ) +# session = models.ForeignKey( +# TrainingSession, on_delete=models.PROTECT, related_name='enrollments', +# help_text='The specific run the employee is enrolled in.' +# ) +# +# # Timeline +# enrolled_at = models.DateTimeField(auto_now_add=True) +# started_at = models.DateTimeField(blank=True, null=True) +# completion_date = models.DateField(blank=True, null=True) +# +# # Outcomes +# status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='SCHEDULED') +# credits_earned = models.DecimalField(max_digits=5, decimal_places=2, +# default=Decimal('0.00')) +# score = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True) +# passed = models.BooleanField(default=False) +# +# # Notes/Cost +# notes = models.TextField(blank=True, null=True) +# cost_paid = models.DecimalField(max_digits=10, decimal_places=2, +# blank=True, null=True) +# +# created_at = models.DateTimeField(auto_now_add=True) +# updated_at = models.DateTimeField(auto_now=True) +# created_by = models.ForeignKey( +# settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, +# null=True, blank=True, related_name='created_training_records' +# ) +# +# class Meta: +# db_table = 'hr_training_record' +# verbose_name = 'Training Enrollment' +# verbose_name_plural = 'Training Enrollments' +# ordering = ['-enrolled_at'] +# unique_together = [('employee', 'session')] +# indexes = [ +# models.Index(fields=['tenant', 'employee']), +# models.Index(fields=['tenant', 'program']), +# models.Index(fields=['tenant', 'session']), +# models.Index(fields=['tenant', 'status']), +# models.Index(fields=['tenant', 'completion_date']), +# ] +# +# def clean(self): +# # Tenancy alignment +# if self.program and self.tenant_id != self.program.tenant_id: +# raise ValidationError(_('Tenant mismatch between record and program.')) +# if self.session and self.tenant_id != self.session.tenant_id: +# raise ValidationError(_('Tenant mismatch between record and session.')) +# if self.employee and self.tenant_id != self.employee.tenant_id: +# raise ValidationError(_('Tenant mismatch between record and employee.')) +# +# # Prevent enrolling into sessions of a different program (shouldn’t happen) +# if self.session and self.program and self.session.program_id != self.program_id: +# raise ValidationError(_('Session does not belong to the selected program.')) +# +# if self.completion_date and self.status not in ('COMPLETED', 'FAILED'): +# raise ValidationError(_('Completion date requires status COMPLETED or FAILED.')) +# +# def __str__(self): +# return f'{self.employee} → {self.program.name} ({self.get_status_display()})' +# +# # Helper properties +# @property +# def hours(self): +# return self.session.hours_override or self.program.duration_hours +# +# @property +# def effective_cost(self): +# return self.cost_paid if self.cost_paid is not None else \ +# (self.session.cost_override if self.session.cost_override is not None +# else self.program.cost) +# +# @property +# def eligible_for_certificate(self): +# return self.status == 'COMPLETED' and self.passed and self.program.is_certified +# +# +# class SessionAttendance(models.Model): +# """ +# Optional check-in/out per participant per session (or per day if multi-day). +# If you want per-day granularity, add a "session_day" field. +# """ +# ATTENDANCE_STATUS = [ +# ('PRESENT', 'Present'), +# ('LATE', 'Late'), +# ('ABSENT', 'Absent'), +# ('EXCUSED', 'Excused'), +# ] +# +# enrollment = models.ForeignKey( +# TrainingRecord, on_delete=models.CASCADE, related_name='attendance' +# ) +# checked_in_at = models.DateTimeField(blank=True, null=True) +# checked_out_at = models.DateTimeField(blank=True, null=True) +# status = models.CharField(max_length=10, choices=ATTENDANCE_STATUS, default='PRESENT') +# notes = models.CharField(max_length=255, blank=True, null=True) +# +# class Meta: +# db_table = 'hr_training_attendance' +# ordering = ['enrollment_id', 'checked_in_at'] +# indexes = [models.Index(fields=['enrollment'])] +# +# +# class SessionAssessment(models.Model): +# """ +# Optional evaluation (quiz/exam) tied to an enrollment. +# """ +# enrollment = models.ForeignKey( +# TrainingRecord, on_delete=models.CASCADE, related_name='assessments' +# ) +# name = models.CharField(max_length=200) +# max_score = models.DecimalField(max_digits=7, decimal_places=2, default=100) +# score = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True) +# passed = models.BooleanField(default=False) +# taken_at = models.DateTimeField(blank=True, null=True) +# +# class Meta: +# db_table = 'hr_training_assessment' +# ordering = ['-taken_at'] +# indexes = [models.Index(fields=['enrollment'])] +# +# +# class TrainingCertificates(models.Model): +# """ +# Issued certificates on completion. +# Usually tied to a program and the enrollment that produced it. +# """ +# tenant = models.ForeignKey( +# Tenant, on_delete=models.CASCADE, related_name='training_certificates' +# ) +# certificate_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) +# +# program = models.ForeignKey( +# TrainingPrograms, on_delete=models.PROTECT, related_name='certificates' +# ) +# employee = models.ForeignKey( +# Employee, on_delete=models.CASCADE, related_name='training_certificates' +# ) +# enrollment = models.OneToOneField( +# TrainingRecord, on_delete=models.CASCADE, related_name='certificate', +# help_text='The enrollment that generated this certificate.' +# ) +# +# certificate_name = models.CharField(max_length=200) +# certificate_number = models.CharField(max_length=50, blank=True, null=True) +# certification_body = models.CharField(max_length=200, blank=True, null=True) +# issued_date = models.DateField(auto_now_add=True) +# expiry_date = models.DateField(blank=True, null=True) +# file = models.FileField(upload_to='certificates/', blank=True, null=True) +# +# created_at = models.DateTimeField(auto_now_add=True) +# created_by = models.ForeignKey( +# settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, +# null=True, blank=True, related_name='created_training_certificates' +# ) +# +# class Meta: +# db_table = 'hr_training_certificate' +# ordering = ['-issued_date'] +# unique_together = [('employee', 'program', 'enrollment')] +# indexes = [ +# models.Index(fields=['tenant', 'employee']), +# models.Index(fields=['tenant', 'program']), +# models.Index(fields=['tenant', 'expiry_date']), +# models.Index(fields=['certificate_number']), +# ] +# +# def clean(self): +# # tenancy alignment +# if self.program and self.tenant_id != self.program.tenant_id: +# raise ValidationError(_('Tenant mismatch between certificate and program.')) +# if self.employee and self.tenant_id != self.employee.tenant_id: +# raise ValidationError(_('Tenant mismatch between certificate and employee.')) +# if self.enrollment and self.tenant_id != self.enrollment.tenant_id: +# raise ValidationError(_('Tenant mismatch between certificate and enrollment.')) +# if self.enrollment and self.enrollment.program_id != self.program_id: +# raise ValidationError(_('Enrollment does not belong to this program.')) +# +# def __str__(self): +# return f'{self.certificate_name} - {self.employee}' +# +# @property +# def is_expired(self): +# return bool(self.expiry_date and self.expiry_date < date.today()) +# +# @property +# def days_to_expiry(self): +# return (self.expiry_date - date.today()).days if self.expiry_date else None +# +# @classmethod +# def compute_expiry(cls, program: TrainingPrograms, issued_on: date) -> date | None: +# if program.is_certified and program.validity_days: +# return issued_on + timedelta(days=program.validity_days) +# return None + + diff --git a/hr/urls.py b/hr/urls.py index 28f18a0d..f1b272b4 100644 --- a/hr/urls.py +++ b/hr/urls.py @@ -65,10 +65,12 @@ urlpatterns = [ path('reviews//', views.PerformanceReviewDetailView.as_view(), name='performance_review_detail'), path('reviews//update/', views.PerformanceReviewUpdateView.as_view(), name='performance_review_update'), path('reviews//delete/', views.PerformanceReviewDeleteView.as_view(), name='performance_review_delete'), + path('reviews//complete/', views.complete_performance_review, name='complete_performance_review'), # ============================================================================ # TRAINING RECORD URLS (FULL CRUD - Operational Data) # ============================================================================ + path('training-management', views.TrainingManagementView.as_view(), name='training_management'), path('training/', views.TrainingRecordListView.as_view(), name='training_record_list'), path('training/create/', views.TrainingRecordCreateView.as_view(), name='training_record_create'), path('training//', views.TrainingRecordDetailView.as_view(), name='training_record_detail'), @@ -88,6 +90,7 @@ urlpatterns = [ path('clock-out/', views.clock_out, name='clock_out'), path('time-entries//approve/', views.approve_time_entry, name='approve_time_entry'), path('schedules//publish/', views.publish_schedule, name='publish_schedule'), + # ============================================================================ # API ENDPOINTS diff --git a/hr/views.py b/hr/views.py index ae42ae33..f09cf856 100644 --- a/hr/views.py +++ b/hr/views.py @@ -28,10 +28,6 @@ from .forms import ( ) -# ============================================================================ -# DASHBOARD AND OVERVIEW VIEWS -# ============================================================================ - class HRDashboardView(LoginRequiredMixin, TemplateView): """ Main HR dashboard with comprehensive statistics and recent activity. @@ -92,10 +88,6 @@ class HRDashboardView(LoginRequiredMixin, TemplateView): return context -# ============================================================================ -# EMPLOYEE VIEWS (FULL CRUD - Master Data) -# ============================================================================ - class EmployeeListView(LoginRequiredMixin, ListView): """ List all employees with filtering and search capabilities. @@ -236,7 +228,7 @@ class EmployeeDeleteView(LoginRequiredMixin, DeleteView): Soft delete an employee record (healthcare compliance). """ model = Employee - template_name = 'hr/employee_confirm_delete.html' + template_name = 'hr/employees/employee_confirm_delete.html' success_url = reverse_lazy('hr:employee_list') def get_queryset(self): @@ -253,16 +245,12 @@ class EmployeeDeleteView(LoginRequiredMixin, DeleteView): return redirect(self.success_url) -# ============================================================================ -# DEPARTMENT VIEWS (FULL CRUD - Master Data) -# ============================================================================ - class DepartmentListView(LoginRequiredMixin, ListView): """ List all departments with employee counts. """ model = Department - template_name = 'hr/department_list.html' + template_name = 'hr/departments/department_list.html' context_object_name = 'departments' paginate_by = 20 @@ -286,7 +274,7 @@ class DepartmentDetailView(LoginRequiredMixin, DetailView): Display detailed information about a specific department. """ model = Department - template_name = 'hr/department_detail.html' + template_name = 'hr/departments/department_detail.html' context_object_name = 'department' def get_queryset(self): @@ -316,7 +304,7 @@ class DepartmentCreateView(LoginRequiredMixin, CreateView): """ model = Department form_class = DepartmentForm - template_name = 'hr/department_form.html' + template_name = 'hr/departments/department_form.html' success_url = reverse_lazy('hr:department_list') def form_valid(self, form): @@ -336,7 +324,7 @@ class DepartmentUpdateView(LoginRequiredMixin, UpdateView): """ model = Department form_class = DepartmentForm - template_name = 'hr/department_form.html' + template_name = 'hr/departments/department_form.html' def get_queryset(self): return Department.objects.filter(tenant=self.request.user.tenant) @@ -359,7 +347,7 @@ class DepartmentDeleteView(LoginRequiredMixin, DeleteView): Delete a department (only if no employees assigned). """ model = Department - template_name = 'hr/department_confirm_delete.html' + template_name = 'hr/departments/department_confirm_delete.html' success_url = reverse_lazy('hr:department_list') def get_queryset(self): @@ -377,16 +365,12 @@ class DepartmentDeleteView(LoginRequiredMixin, DeleteView): return super().delete(request, *args, **kwargs) -# ============================================================================ -# SCHEDULE VIEWS (LIMITED CRUD - Operational Data) -# ============================================================================ - class ScheduleListView(LoginRequiredMixin, ListView): """ List all schedules with filtering capabilities. """ model = Schedule - template_name = 'hr/schedule_list.html' + template_name = 'hr/schedules/schedule_list.html' context_object_name = 'schedules' paginate_by = 20 @@ -414,7 +398,7 @@ class ScheduleDetailView(LoginRequiredMixin, DetailView): Display detailed information about a specific schedule. """ model = Schedule - template_name = 'hr/schedule_detail.html' + template_name = 'hr/schedules/schedule_detail.html' context_object_name = 'schedule' def get_queryset(self): @@ -438,7 +422,7 @@ class ScheduleCreateView(LoginRequiredMixin, CreateView): """ model = Schedule form_class = ScheduleForm - template_name = 'hr/schedule_form.html' + template_name = 'hr/schedules/schedule_form.html' success_url = reverse_lazy('hr:schedule_list') def form_valid(self, form): @@ -458,7 +442,7 @@ class ScheduleUpdateView(LoginRequiredMixin, UpdateView): """ model = Schedule form_class = ScheduleForm - template_name = 'hr/schedule_form.html' + template_name = 'hr/schedules/schedule_form.html' def get_queryset(self): return Schedule.objects.filter(employee__tenant=self.request.user.tenant) @@ -476,16 +460,12 @@ class ScheduleUpdateView(LoginRequiredMixin, UpdateView): return kwargs -# ============================================================================ -# SCHEDULE ASSIGNMENT VIEWS (LIMITED CRUD - Operational Data) -# ============================================================================ - class ScheduleAssignmentListView(LoginRequiredMixin, ListView): """ List all schedule assignments with filtering capabilities. """ model = ScheduleAssignment - template_name = 'hr/schedule_assignment_list.html' + template_name = 'hr/assignments/schedule_assignment_list.html' context_object_name = 'assignments' paginate_by = 20 @@ -521,7 +501,7 @@ class ScheduleAssignmentCreateView(LoginRequiredMixin, CreateView): """ model = ScheduleAssignment form_class = ScheduleAssignmentForm - template_name = 'hr/schedule_assignment_form.html' + template_name = 'hr/assignments/schedule_assignment_form.html' success_url = reverse_lazy('hr:schedule_assignment_list') def form_valid(self, form): @@ -540,7 +520,7 @@ class ScheduleAssignmentUpdateView(LoginRequiredMixin, UpdateView): """ model = ScheduleAssignment form_class = ScheduleAssignmentForm - template_name = 'hr/schedule_assignment_form.html' + template_name = 'hr/assignments/schedule_assignment_form.html' success_url = reverse_lazy('hr:schedule_assignment_list') def get_queryset(self): @@ -556,16 +536,12 @@ class ScheduleAssignmentUpdateView(LoginRequiredMixin, UpdateView): return kwargs -# ============================================================================ -# TIME ENTRY VIEWS (RESTRICTED CRUD - Operational Data) -# ============================================================================ - class TimeEntryListView(LoginRequiredMixin, ListView): """ List time entries with filtering capabilities. """ model = TimeEntry - template_name = 'hr/time_entry_list.html' + template_name = 'hr/time_entries/time_entry_list.html' context_object_name = 'time_entries' paginate_by = 20 @@ -600,7 +576,7 @@ class TimeEntryDetailView(LoginRequiredMixin, DetailView): Display detailed information about a specific time entry. """ model = TimeEntry - template_name = 'hr/time_entry_detail.html' + template_name = 'hr/time_entries/time_entry_detail.html' context_object_name = 'time_entry' def get_queryset(self): @@ -613,7 +589,7 @@ class TimeEntryCreateView(LoginRequiredMixin, CreateView): """ model = TimeEntry form_class = TimeEntryForm - template_name = 'hr/time_entry_form.html' + template_name = 'hr/time_entries/time_entry_form.html' success_url = reverse_lazy('hr:time_entry_list') def form_valid(self, form): @@ -632,7 +608,7 @@ class TimeEntryUpdateView(LoginRequiredMixin, UpdateView): """ model = TimeEntry form_class = TimeEntryForm - template_name = 'hr/time_entry_form.html' + template_name = 'hr/time_entries/time_entry_form.html' success_url = reverse_lazy('hr:time_entry_list') def get_queryset(self): @@ -653,16 +629,12 @@ class TimeEntryUpdateView(LoginRequiredMixin, UpdateView): return kwargs -# ============================================================================ -# PERFORMANCE REVIEW VIEWS (FULL CRUD - Operational Data) -# ============================================================================ - class PerformanceReviewListView(LoginRequiredMixin, ListView): """ List performance reviews with filtering capabilities. """ model = PerformanceReview - template_name = 'hr/performance_review_list.html' + template_name = 'hr/reviews/performance_review_list.html' context_object_name = 'reviews' paginate_by = 20 @@ -694,11 +666,80 @@ class PerformanceReviewDetailView(LoginRequiredMixin, DetailView): Display detailed information about a specific performance review. """ model = PerformanceReview - template_name = 'hr/performance_review_detail.html' + template_name = 'hr/reviews/performance_review_detail.html' context_object_name = 'review' - + def get_queryset(self): - return PerformanceReview.objects.filter(employee__tenant=self.request.user.tenant) + # Eager load employee + department + supervisor to reduce queries + return (PerformanceReview.objects + .select_related('employee', 'employee__department', 'employee__supervisor', 'reviewer') + .filter(employee__tenant=self.request.user.tenant)) + + def get_object(self, queryset=None): + queryset = queryset or self.get_queryset() + return get_object_or_404(queryset, pk=self.kwargs.get('pk') or self.kwargs.get('id')) + + @staticmethod + def _split_lines(text): + if not text: + return [] + parts = [] + for line in str(text).replace('\r', '').split('\n'): + for piece in line.split(';'): + piece = piece.strip() + if piece: + parts.append(piece) + return parts + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + review = ctx['review'] + + # Build categories from competency_ratings JSON: { "Teamwork": 4.0, ... } + # Make a list of dicts the template can iterate through. + categories = [] + ratings = review.competency_ratings or {} + # Keep a stable order (by key) to avoid chart jitter + for name in sorted(ratings.keys()): + try: + score = float(ratings[name]) + except (TypeError, ValueError): + score = 0.0 + categories.append({'name': name, 'score': score, 'comments': ''}) + + # Previous reviews (same employee, exclude current) + previous_reviews = ( + PerformanceReview.objects + .filter(employee=review.employee) + .exclude(pk=review.pk) + .order_by('-review_date')[:5] + .select_related('employee') + ) + + # Strengths / AFI lists for bullet rendering + strengths_list = self._split_lines(review.strengths) + afi_list = self._split_lines(review.areas_for_improvement) + + # Goals blocks as lists for nicer display + goals_achieved_list = self._split_lines(review.goals_achieved) + goals_not_achieved_list = self._split_lines(review.goals_not_achieved) + future_goals_list = self._split_lines(review.future_goals) + + ctx.update({ + 'categories': categories, + 'previous_reviews': previous_reviews, + 'review_strengths_list': strengths_list, + 'review_afi_list': afi_list, + 'goals_achieved_list': goals_achieved_list, + 'goals_not_achieved_list': goals_not_achieved_list, + 'future_goals_list': future_goals_list, + }) + + # convenience on the review object (template already expects these list props sometimes) + setattr(review, 'strengths_list', strengths_list) + setattr(review, 'areas_for_improvement_list', afi_list) + + return ctx class PerformanceReviewCreateView(LoginRequiredMixin, CreateView): @@ -707,7 +748,7 @@ class PerformanceReviewCreateView(LoginRequiredMixin, CreateView): """ model = PerformanceReview form_class = PerformanceReviewForm - template_name = 'hr/performance_review_form.html' + template_name = 'hr/reviews/performance_review_form.html' success_url = reverse_lazy('hr:performance_review_list') def form_valid(self, form): @@ -727,7 +768,7 @@ class PerformanceReviewUpdateView(LoginRequiredMixin, UpdateView): """ model = PerformanceReview form_class = PerformanceReviewForm - template_name = 'hr/performance_review_form.html' + template_name = 'hr/reviews/performance_review_form.html' def get_queryset(self): return PerformanceReview.objects.filter(employee__tenant=self.request.user.tenant) @@ -750,7 +791,7 @@ class PerformanceReviewDeleteView(LoginRequiredMixin, DeleteView): Delete a performance review (only if not finalized). """ model = PerformanceReview - template_name = 'hr/performance_review_confirm_delete.html' + template_name = 'hr/reviews/performance_review_confirm_delete.html' success_url = reverse_lazy('hr:performance_review_list') def get_queryset(self): @@ -768,39 +809,128 @@ class PerformanceReviewDeleteView(LoginRequiredMixin, DeleteView): return super().delete(request, *args, **kwargs) -# ============================================================================ -# TRAINING RECORD VIEWS (FULL CRUD - Operational Data) -# ============================================================================ +class TrainingManagementView(LoginRequiredMixin, ListView): + model = TrainingRecord + template_name = 'hr/training/training_management.html' + context_object_name = 'training_records' + paginate_by = 20 + + def get_queryset(self): + qs = (TrainingRecord.objects + .filter(employee__tenant=self.request.user.tenant) + .select_related('employee', 'employee__department') + .order_by('-training_date', '-completion_date')) + # optional GET filters (works with the template’s inputs) + if emp := self.request.GET.get('employee'): + qs = qs.filter(employee_id=emp) + if ttype := self.request.GET.get('training_type'): + qs = qs.filter(training_type=ttype) + if status := self.request.GET.get('status'): + qs = qs.filter(status=status) + return qs + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + tenant = self.request.user.tenant + today = timezone.now().date() + + base = TrainingRecord.objects.filter(employee__tenant=tenant) + + total_records = base.count() + completed_trainings = base.filter(status='COMPLETED').count() + pending_trainings = base.filter(status__in=['SCHEDULED', 'IN_PROGRESS']).count() + overdue_trainings = base.filter(expiry_date__lt=today, expiry_date__isnull=False).exclude( + status='COMPLETED').count() + + # compliance rate = “not expired” among trainings that have an expiry_date + with_expiry = base.filter(expiry_date__isnull=False) + valid_now = with_expiry.filter(expiry_date__gte=today).count() + compliance_rate = round((valid_now / with_expiry.count()) * 100, 1) if with_expiry.exists() else 100.0 + + # expiring soon = within 30 days + expiring_soon_count = with_expiry.filter(expiry_date__gte=today, + expiry_date__lte=today + timedelta(days=30)).count() + + # department compliance (simple example: percent of non-expired per dept among those with expiry) + dept_rows = [] + departments = Department.objects.filter(tenant=tenant).order_by('name') + for d in departments: + d_qs = with_expiry.filter(employee__department=d) + if not d_qs.exists(): + rate = 100 + else: + ok = d_qs.filter(expiry_date__gte=today).count() + rate = round((ok / d_qs.count()) * 100) + color = 'success' if rate >= 90 else 'warning' if rate >= 70 else 'danger' + dept_rows.append({'name': d.name, 'compliance_rate': rate, 'compliance_color': color}) + + # “compliance alerts” demo (overdue/expiring soon) + alerts = [] + for tr in base.select_related('employee'): + if tr.expiry_date: + if tr.expiry_date < today: + alerts.append({ + 'id': tr.id, + 'employee': tr.employee, + 'requirement': tr.training_name, + 'due_date': tr.expiry_date, + 'priority_color': 'danger', + 'urgency_color': 'danger', + 'get_priority_display': 'Overdue', + }) + elif today <= tr.expiry_date <= today + timedelta(days=30): + alerts.append({ + 'id': tr.id, + 'employee': tr.employee, + 'requirement': tr.training_name, + 'due_date': tr.expiry_date, + 'priority_color': 'warning', + 'urgency_color': 'warning', + 'get_priority_display': 'Expiring Soon', + }) + + ctx.update({ + 'total_records': total_records, + 'completed_trainings': completed_trainings, + 'pending_trainings': pending_trainings, + 'overdue_trainings': overdue_trainings, + 'departments': departments, + 'compliance_rate': compliance_rate, + 'expiring_soon_count': expiring_soon_count, + 'department_compliance': dept_rows, + 'compliance_alerts': alerts, + }) + return ctx class TrainingRecordListView(LoginRequiredMixin, ListView): """ - List training records with filtering capabilities. - """ + List training records with filtering capabilities. + """ model = TrainingRecord - template_name = 'hr/training_record_list.html' + template_name = 'hr/training/training_record_list.html' context_object_name = 'training_records' paginate_by = 20 - + def get_queryset(self): queryset = TrainingRecord.objects.filter( employee__tenant=self.request.user.tenant ).select_related('employee') - + # Filter by employee employee = self.request.GET.get('employee') if employee: queryset = queryset.filter(employee_id=employee) - + # Filter by training type training_type = self.request.GET.get('training_type') if training_type: queryset = queryset.filter(training_type=training_type) - + # Filter by completion status status = self.request.GET.get('status') if status: queryset = queryset.filter(status=status) - + return queryset.order_by('-completion_date') @@ -809,8 +939,8 @@ class TrainingRecordDetailView(LoginRequiredMixin, DetailView): Display detailed information about a specific training record. """ model = TrainingRecord - template_name = 'hr/training_record_detail.html' - context_object_name = 'training_record' + template_name = 'hr/training/training_record_detail.html' + context_object_name = 'record' def get_queryset(self): return TrainingRecord.objects.filter(employee__tenant=self.request.user.tenant) @@ -822,7 +952,7 @@ class TrainingRecordCreateView(LoginRequiredMixin, CreateView): """ model = TrainingRecord form_class = TrainingRecordForm - template_name = 'hr/training_record_form.html' + template_name = 'hr/training/training_record_form.html' success_url = reverse_lazy('hr:training_record_list') def form_valid(self, form): @@ -842,7 +972,7 @@ class TrainingRecordUpdateView(LoginRequiredMixin, UpdateView): """ model = TrainingRecord form_class = TrainingRecordForm - template_name = 'hr/training_record_form.html' + template_name = 'hr/training/training_record_form.html' def get_queryset(self): return TrainingRecord.objects.filter(employee__tenant=self.request.user.tenant) @@ -865,7 +995,7 @@ class TrainingRecordDeleteView(LoginRequiredMixin, DeleteView): Delete a training record. """ model = TrainingRecord - template_name = 'hr/training_record_confirm_delete.html' + template_name = 'hr/training/training_record_confirm_delete.html' success_url = reverse_lazy('hr:training_record_list') def get_queryset(self): @@ -876,9 +1006,15 @@ class TrainingRecordDeleteView(LoginRequiredMixin, DeleteView): return super().delete(request, *args, **kwargs) -# ============================================================================ -# HTMX VIEWS FOR REAL-TIME UPDATES -# ============================================================================ +@login_required +def complete_performance_review(request, review_id): + review = get_object_or_404(PerformanceReview, pk=review_id) + review.status = 'COMPLETED' + review.completed_by = request.user + review.save() + + messages.success(request, 'Performance review completed successfully.') + return redirect('hr:performance_review_detail', pk=review.pk) @login_required def hr_stats(request): @@ -961,10 +1097,6 @@ def attendance_summary(request): return render(request, 'hr/partials/attendance_summary.html', context) -# ============================================================================ -# ACTION VIEWS FOR WORKFLOW OPERATIONS -# ============================================================================ - @login_required def clock_in(request): """ @@ -1093,7 +1225,7 @@ def approve_time_entry(request, entry_id): next_url = request.POST.get('next', reverse('hr:time_entry_detail', kwargs={'pk': time_entry.id})) return redirect(next_url) - return render(request, 'hr/time_entry_approve.html', { + return render(request, 'hr/time_entries/time_entry_approve.html', { 'time_entry': time_entry }) @@ -1123,15 +1255,11 @@ def publish_schedule(request, schedule_id): messages.success(request, 'Schedule published successfully.') return redirect('hr:schedule_detail', pk=schedule.id) - return render(request, 'hr/schedule_publish.html', { + return render(request, 'hr/schedules/schedule_publish.html', { 'schedule': schedule }) -# ============================================================================ -# API ENDPOINTS -# ============================================================================ - @login_required def api_employee_list(request): """ @@ -1155,6 +1283,40 @@ def api_department_list(request): return JsonResponse({'departments': list(departments)}) + +# Query patterns to use if needed +# # All upcoming sessions for a tenant (next 30 days) +# TrainingSession.objects.filter( +# tenant=request.user.tenant, start_at__gte=timezone.now(), +# start_at__lte=timezone.now() + timedelta(days=30) +# ).select_related('program', 'instructor') +# +# # Employees due for renewal in 30 days +# TrainingCertificates.objects.filter( +# tenant=request.user.tenant, +# expiry_date__lte=date.today() + timedelta(days=30), +# expiry_date__gte=date.today() +# ).select_related('employee', 'program') +# +# # Enroll an employee, respecting capacity +# session = TrainingSession.objects.select_for_update().get(pk=session_pk, tenant=tenant) +# if session.capacity and session.enrollments.count() >= session.capacity: +# status = 'WAITLISTED' +# else: +# status = 'SCHEDULED' +# enrollment = TrainingRecord.objects.create( +# tenant=tenant, employee=emp, program=session.program, session=session, +# status=status, created_by=request.user +# ) +# +# # Mark completion + pass (auto-certificate will fire via signal) +# enrollment.status = 'COMPLETED' +# enrollment.passed = True +# enrollment.completion_date = date.today() +# enrollment.credits_earned = enrollment.hours +# enrollment.save() + + # # from django.shortcuts import render, redirect, get_object_or_404 # from django.views.generic import ( diff --git a/inpatients/__pycache__/flows.cpython-312.pyc b/inpatients/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cd8ebb6fe02c4292fbe9887d3a9c3f8c1e02b5a GIT binary patch literal 180 zcmX@j%ge<81bQ<2GP*Mu7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@Tc{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqMw;pkXVul6f4$G%gHY<)+?yI#bJ}1pHiBWYFESxw1W|di$RQ!%#4hTMa)1J03{MJ AWB>pF literal 0 HcmV?d00001 diff --git a/inpatients/flows.py b/inpatients/flows.py new file mode 100644 index 00000000..0d7ed355 --- /dev/null +++ b/inpatients/flows.py @@ -0,0 +1,757 @@ +# """ +# Viewflow workflows for inpatients app. +# Provides admission, transfer, and discharge 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 Admission, Transfer, DischargeSummary, Ward, Bed +# from .views import ( +# AdmissionRegistrationView, BedAssignmentView, MedicalAssessmentView, +# NursingAssessmentView, AdmissionOrdersView, TransferRequestView, +# TransferApprovalView, TransferExecutionView, DischargeInitiationView, +# DischargePlanningView, DischargeExecutionView +# ) +# +# +# class AdmissionProcess(Process): +# """ +# Viewflow process model for patient admissions +# """ +# admission = ModelField(Admission, help_text='Associated admission record') +# +# # Process status tracking +# registration_completed = models.BooleanField(default=False) +# bed_assigned = models.BooleanField(default=False) +# medical_assessment_completed = models.BooleanField(default=False) +# nursing_assessment_completed = models.BooleanField(default=False) +# orders_written = models.BooleanField(default=False) +# admission_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Admission Process' +# verbose_name_plural = 'Admission Processes' +# +# +# class AdmissionFlow(Flow): +# """ +# Hospital Patient Admission Workflow +# +# This flow manages the complete patient admission process from +# initial registration through final admission completion. +# """ +# +# process_class = AdmissionProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_admission) +# .Next(this.patient_registration) +# ) +# +# patient_registration = ( +# flow_view(AdmissionRegistrationView) +# .Permission('inpatients.can_register_admissions') +# .Next(this.check_bed_availability) +# ) +# +# check_bed_availability = ( +# flow_func(this.check_beds) +# .Next(this.bed_assignment) +# ) +# +# bed_assignment = ( +# flow_view(BedAssignmentView) +# .Permission('inpatients.can_assign_beds') +# .Next(this.parallel_assessments) +# ) +# +# parallel_assessments = ( +# flow_func(this.start_parallel_assessments) +# .Next(this.medical_assessment) +# .Next(this.nursing_assessment) +# ) +# +# medical_assessment = ( +# flow_view(MedicalAssessmentView) +# .Permission('inpatients.can_perform_medical_assessment') +# .Next(this.join_assessments) +# ) +# +# nursing_assessment = ( +# flow_view(NursingAssessmentView) +# .Permission('inpatients.can_perform_nursing_assessment') +# .Next(this.join_assessments) +# ) +# +# join_assessments = ( +# flow_func(this.join_parallel_assessments) +# .Next(this.write_admission_orders) +# ) +# +# write_admission_orders = ( +# flow_view(AdmissionOrdersView) +# .Permission('inpatients.can_write_orders') +# .Next(this.finalize_admission) +# ) +# +# finalize_admission = ( +# flow_func(this.complete_admission) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_admission) +# +# # Flow functions +# def start_admission(self, activation): +# """Initialize the admission process""" +# process = activation.process +# admission = process.admission +# +# # Update admission status +# admission.status = 'PENDING' +# admission.save() +# +# # Send notification to registration staff +# self.notify_registration_staff(admission) +# +# def check_beds(self, activation): +# """Check bed availability for the patient""" +# process = activation.process +# admission = process.admission +# +# # Check if beds are available in the requested ward +# available_beds = Bed.objects.filter( +# ward=admission.current_ward, +# status='AVAILABLE' +# ).count() +# +# if available_beds == 0: +# # Handle no beds available - could trigger waiting list +# admission.admission_notes += f"\nNo beds available in {admission.current_ward.name} at {timezone.now()}" +# admission.save() +# +# # Notify bed management +# self.notify_bed_shortage(admission) +# +# def start_parallel_assessments(self, activation): +# """Start parallel medical and nursing assessments""" +# process = activation.process +# +# # Create assessment tasks +# self.create_assessment_tasks(process) +# +# def join_parallel_assessments(self, activation): +# """Wait for both assessments to complete""" +# process = activation.process +# +# # Check if both assessments are completed +# if (process.medical_assessment_completed and +# process.nursing_assessment_completed): +# +# # Notify physician to write orders +# self.notify_physician_for_orders(process.admission) +# +# def complete_admission(self, activation): +# """Finalize the admission process""" +# process = activation.process +# admission = process.admission +# +# # Update admission status +# admission.status = 'ADMITTED' +# admission.save() +# +# # Update bed status +# if admission.current_bed: +# admission.current_bed.status = 'OCCUPIED' +# admission.current_bed.current_patient = admission.patient +# admission.current_bed.current_admission = admission +# admission.current_bed.occupied_since = timezone.now() +# admission.current_bed.save() +# +# # Mark process as completed +# process.admission_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_admission_complete(admission) +# +# def end_admission(self, activation): +# """End the admission workflow""" +# process = activation.process +# +# # Generate admission summary report +# self.generate_admission_summary(process.admission) +# +# # Helper methods +# def notify_registration_staff(self, admission): +# """Notify registration staff of new admission""" +# from django.contrib.auth.models import Group +# +# registration_staff = User.objects.filter( +# groups__name='Registration Staff' +# ) +# +# for staff in registration_staff: +# send_mail( +# subject=f'New Admission: {admission.patient.get_full_name()}', +# message=f'A new {admission.get_admission_type_display()} admission has been initiated.', +# from_email='admissions@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_bed_shortage(self, admission): +# """Notify bed management of shortage""" +# from django.contrib.auth.models import Group +# +# bed_managers = User.objects.filter( +# groups__name='Bed Management' +# ) +# +# for manager in bed_managers: +# send_mail( +# subject=f'Bed Shortage Alert - {admission.current_ward.name}', +# message=f'No beds available for admission of {admission.patient.get_full_name()}.', +# from_email='admissions@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def create_assessment_tasks(self, process): +# """Create assessment tasks for medical and nursing staff""" +# # This would create tasks in a task management system +# pass +# +# def notify_physician_for_orders(self, admission): +# """Notify attending physician to write orders""" +# if admission.attending_physician and admission.attending_physician.email: +# send_mail( +# subject=f'Admission Orders Required: {admission.patient.get_full_name()}', +# message=f'Please write admission orders. Both assessments are complete.', +# from_email='admissions@hospital.com', +# recipient_list=[admission.attending_physician.email], +# fail_silently=True +# ) +# +# def notify_admission_complete(self, admission): +# """Notify relevant staff that admission is complete""" +# # Notify nursing staff +# nursing_staff = User.objects.filter( +# groups__name='Nursing Staff', +# profile__department=admission.current_ward +# ) +# +# for nurse in nursing_staff: +# send_mail( +# subject=f'New Patient Admitted: {admission.patient.get_full_name()}', +# message=f'Patient has been admitted to {admission.current_bed.room_number if admission.current_bed else "TBD"}.', +# from_email='admissions@hospital.com', +# recipient_list=[nurse.email], +# fail_silently=True +# ) +# +# def generate_admission_summary(self, admission): +# """Generate admission summary report""" +# # This would generate a comprehensive admission report +# pass +# +# +# class TransferProcess(Process): +# """ +# Viewflow process model for patient transfers +# """ +# transfer = ModelField(Transfer, help_text='Associated transfer record') +# +# # Process status tracking +# request_approved = models.BooleanField(default=False) +# bed_prepared = models.BooleanField(default=False) +# transport_arranged = models.BooleanField(default=False) +# handoff_completed = models.BooleanField(default=False) +# transfer_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Transfer Process' +# verbose_name_plural = 'Transfer Processes' +# +# +# class TransferFlow(Flow): +# """ +# Hospital Patient Transfer Workflow +# +# This flow manages patient transfers between wards, beds, or units. +# """ +# +# process_class = TransferProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_transfer) +# .Next(this.transfer_request) +# ) +# +# transfer_request = ( +# flow_view(TransferRequestView) +# .Permission('inpatients.can_request_transfers') +# .Next(this.transfer_approval) +# ) +# +# transfer_approval = ( +# flow_view(TransferApprovalView) +# .Permission('inpatients.can_approve_transfers') +# .Next(this.prepare_destination) +# ) +# +# prepare_destination = ( +# flow_func(this.prepare_bed) +# .Next(this.arrange_transport) +# ) +# +# arrange_transport = ( +# flow_func(this.schedule_transport) +# .Next(this.execute_transfer) +# ) +# +# execute_transfer = ( +# flow_view(TransferExecutionView) +# .Permission('inpatients.can_execute_transfers') +# .Next(this.complete_transfer) +# ) +# +# complete_transfer = ( +# flow_func(this.finalize_transfer) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_transfer) +# +# # Flow functions +# def start_transfer(self, activation): +# """Initialize the transfer process""" +# process = activation.process +# transfer = process.transfer +# +# # Update transfer status +# transfer.status = 'REQUESTED' +# transfer.save() +# +# # Notify receiving ward +# self.notify_receiving_ward(transfer) +# +# def prepare_bed(self, activation): +# """Prepare destination bed""" +# process = activation.process +# transfer = process.transfer +# +# if transfer.to_bed: +# # Reserve the destination bed +# transfer.to_bed.status = 'RESERVED' +# transfer.to_bed.reserved_until = timezone.now() + timezone.timedelta(hours=2) +# transfer.to_bed.save() +# +# process.bed_prepared = True +# process.save() +# +# def schedule_transport(self, activation): +# """Schedule patient transport""" +# process = activation.process +# transfer = process.transfer +# +# # Auto-schedule transport based on priority +# if transfer.priority in ['EMERGENT', 'STAT']: +# transfer.scheduled_datetime = timezone.now() + timezone.timedelta(minutes=15) +# elif transfer.priority == 'URGENT': +# transfer.scheduled_datetime = timezone.now() + timezone.timedelta(hours=1) +# else: +# transfer.scheduled_datetime = timezone.now() + timezone.timedelta(hours=4) +# +# transfer.save() +# +# process.transport_arranged = True +# process.save() +# +# # Notify transport team +# self.notify_transport_team(transfer) +# +# def finalize_transfer(self, activation): +# """Finalize the transfer process""" +# process = activation.process +# transfer = process.transfer +# admission = transfer.admission +# +# # Update admission location +# admission.current_ward = transfer.to_ward +# admission.current_bed = transfer.to_bed +# admission.save() +# +# # Update bed statuses +# if transfer.from_bed: +# transfer.from_bed.status = 'AVAILABLE' +# transfer.from_bed.current_patient = None +# transfer.from_bed.current_admission = None +# transfer.from_bed.occupied_since = None +# transfer.from_bed.save() +# +# if transfer.to_bed: +# transfer.to_bed.status = 'OCCUPIED' +# transfer.to_bed.current_patient = transfer.patient +# transfer.to_bed.current_admission = admission +# transfer.to_bed.occupied_since = timezone.now() +# transfer.to_bed.save() +# +# # Update transfer status +# transfer.status = 'COMPLETED' +# transfer.actual_datetime = timezone.now() +# transfer.save() +# +# process.transfer_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_transfer_complete(transfer) +# +# def end_transfer(self, activation): +# """End the transfer workflow""" +# process = activation.process +# +# # Generate transfer summary +# self.generate_transfer_summary(process.transfer) +# +# # Helper methods +# def notify_receiving_ward(self, transfer): +# """Notify receiving ward of incoming transfer""" +# receiving_staff = User.objects.filter( +# groups__name='Nursing Staff', +# profile__department=transfer.to_ward +# ) +# +# for staff in receiving_staff: +# send_mail( +# subject=f'Incoming Transfer: {transfer.patient.get_full_name()}', +# message=f'Patient transfer requested from {transfer.from_ward.name}.', +# from_email='transfers@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_transport_team(self, transfer): +# """Notify transport team of scheduled transfer""" +# transport_staff = User.objects.filter( +# groups__name='Transport Team' +# ) +# +# for staff in transport_staff: +# send_mail( +# subject=f'Transport Scheduled: {transfer.patient.get_full_name()}', +# message=f'Transfer scheduled for {transfer.scheduled_datetime}.', +# from_email='transport@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_transfer_complete(self, transfer): +# """Notify relevant staff that transfer is complete""" +# # Notify both sending and receiving wards +# all_staff = User.objects.filter( +# groups__name='Nursing Staff', +# profile__department__in=[transfer.from_ward, transfer.to_ward] +# ) +# +# for staff in all_staff: +# send_mail( +# subject=f'Transfer Complete: {transfer.patient.get_full_name()}', +# message=f'Patient transfer from {transfer.from_ward.name} to {transfer.to_ward.name} completed.', +# from_email='transfers@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_transfer_summary(self, transfer): +# """Generate transfer summary report""" +# # This would generate a comprehensive transfer report +# pass +# +# +# class DischargeProcess(Process): +# """ +# Viewflow process model for patient discharges +# """ +# admission = ModelField(Admission, help_text='Associated admission record') +# discharge_summary = ModelField(DischargeSummary, null=True, blank=True, +# help_text='Associated discharge summary') +# +# # Process status tracking +# discharge_planning_started = models.BooleanField(default=False) +# discharge_orders_written = models.BooleanField(default=False) +# discharge_summary_completed = models.BooleanField(default=False) +# patient_education_completed = models.BooleanField(default=False) +# medications_reconciled = models.BooleanField(default=False) +# follow_up_scheduled = models.BooleanField(default=False) +# discharge_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Discharge Process' +# verbose_name_plural = 'Discharge Processes' +# +# +# class DischargeFlow(Flow): +# """ +# Hospital Patient Discharge Workflow +# +# This flow manages the complete patient discharge process from +# discharge planning through final discharge completion. +# """ +# +# process_class = DischargeProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_discharge) +# .Next(this.discharge_planning) +# ) +# +# discharge_planning = ( +# flow_view(DischargePlanningView) +# .Permission('inpatients.can_plan_discharges') +# .Next(this.write_discharge_orders) +# ) +# +# write_discharge_orders = ( +# flow_view(DischargeOrdersView) +# .Permission('inpatients.can_write_discharge_orders') +# .Next(this.parallel_discharge_tasks) +# ) +# +# parallel_discharge_tasks = ( +# flow_func(this.start_parallel_discharge_tasks) +# .Next(this.complete_discharge_summary) +# .Next(this.patient_education) +# .Next(this.medication_reconciliation) +# .Next(this.schedule_follow_up) +# ) +# +# complete_discharge_summary = ( +# flow_view(DischargeDocumentationView) +# .Permission('inpatients.can_complete_discharge_summary') +# .Next(this.join_discharge_tasks) +# ) +# +# patient_education = ( +# flow_view(PatientEducationView) +# .Permission('inpatients.can_provide_patient_education') +# .Next(this.join_discharge_tasks) +# ) +# +# medication_reconciliation = ( +# flow_view(MedicationReconciliationView) +# .Permission('inpatients.can_reconcile_medications') +# .Next(this.join_discharge_tasks) +# ) +# +# schedule_follow_up = ( +# flow_view(FollowUpSchedulingView) +# .Permission('inpatients.can_schedule_follow_up') +# .Next(this.join_discharge_tasks) +# ) +# +# join_discharge_tasks = ( +# flow_func(this.join_parallel_discharge_tasks) +# .Next(this.execute_discharge) +# ) +# +# execute_discharge = ( +# flow_view(DischargeExecutionView) +# .Permission('inpatients.can_execute_discharges') +# .Next(this.finalize_discharge) +# ) +# +# finalize_discharge = ( +# flow_func(this.complete_discharge) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_discharge) +# +# # Flow functions +# def start_discharge(self, activation): +# """Initialize the discharge process""" +# process = activation.process +# admission = process.admission +# +# # Update admission discharge planning status +# admission.discharge_planning_started = True +# admission.save() +# +# # Notify discharge planning team +# self.notify_discharge_planning_team(admission) +# +# def start_parallel_discharge_tasks(self, activation): +# """Start parallel discharge preparation tasks""" +# process = activation.process +# +# # Create discharge preparation tasks +# self.create_discharge_tasks(process) +# +# def join_parallel_discharge_tasks(self, activation): +# """Wait for all discharge tasks to complete""" +# process = activation.process +# +# # Check if all discharge tasks are completed +# if (process.discharge_summary_completed and +# process.patient_education_completed and +# process.medications_reconciled and +# process.follow_up_scheduled): +# +# # Notify that patient is ready for discharge +# self.notify_ready_for_discharge(process.admission) +# +# def complete_discharge(self, activation): +# """Finalize the discharge process""" +# process = activation.process +# admission = process.admission +# +# # Update admission status +# admission.status = 'DISCHARGED' +# admission.discharge_datetime = timezone.now() +# admission.save() +# +# # Update bed status +# if admission.current_bed: +# admission.current_bed.status = 'CLEANING' +# admission.current_bed.current_patient = None +# admission.current_bed.current_admission = None +# admission.current_bed.occupied_since = None +# admission.current_bed.save() +# +# # Mark process as completed +# process.discharge_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_discharge_complete(admission) +# +# def end_discharge(self, activation): +# """End the discharge workflow""" +# process = activation.process +# +# # Generate discharge summary report +# self.generate_final_discharge_report(process.admission) +# +# # Helper methods +# def notify_discharge_planning_team(self, admission): +# """Notify discharge planning team""" +# discharge_planners = User.objects.filter( +# groups__name='Discharge Planning' +# ) +# +# for planner in discharge_planners: +# send_mail( +# subject=f'Discharge Planning Required: {admission.patient.get_full_name()}', +# message=f'Discharge planning has been initiated.', +# from_email='discharge@hospital.com', +# recipient_list=[planner.email], +# fail_silently=True +# ) +# +# def create_discharge_tasks(self, process): +# """Create discharge preparation tasks""" +# # This would create tasks in a task management system +# pass +# +# def notify_ready_for_discharge(self, admission): +# """Notify that patient is ready for discharge""" +# if admission.attending_physician and admission.attending_physician.email: +# send_mail( +# subject=f'Patient Ready for Discharge: {admission.patient.get_full_name()}', +# message=f'All discharge preparations are complete.', +# from_email='discharge@hospital.com', +# recipient_list=[admission.attending_physician.email], +# fail_silently=True +# ) +# +# def notify_discharge_complete(self, admission): +# """Notify relevant staff that discharge is complete""" +# # Notify nursing staff and housekeeping +# relevant_staff = User.objects.filter( +# groups__name__in=['Nursing Staff', 'Housekeeping'], +# profile__department=admission.current_ward +# ) +# +# for staff in relevant_staff: +# send_mail( +# subject=f'Patient Discharged: {admission.patient.get_full_name()}', +# message=f'Patient has been discharged from {admission.current_bed.room_number if admission.current_bed else "ward"}.', +# from_email='discharge@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_final_discharge_report(self, admission): +# """Generate final discharge report""" +# # This would generate a comprehensive discharge report +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_assign_bed(admission_id, ward_id): +# """Background task to automatically assign available bed""" +# try: +# admission = Admission.objects.get(id=admission_id) +# ward = Ward.objects.get(id=ward_id) +# +# available_bed = Bed.objects.filter( +# ward=ward, +# status='AVAILABLE' +# ).first() +# +# if available_bed: +# admission.current_bed = available_bed +# available_bed.status = 'RESERVED' +# available_bed.save() +# admission.save() +# return True +# +# return False +# except (Admission.DoesNotExist, Ward.DoesNotExist): +# return False +# +# +# @celery.job +# def schedule_discharge_planning(admission_id, days_before_discharge=2): +# """Background task to schedule discharge planning""" +# try: +# admission = Admission.objects.get(id=admission_id) +# +# if admission.estimated_length_of_stay: +# planning_date = admission.admission_datetime + timezone.timedelta( +# days=admission.estimated_length_of_stay - days_before_discharge +# ) +# +# # Schedule discharge planning +# # This would integrate with a scheduling system +# return True +# +# return False +# except Admission.DoesNotExist: +# return False +# +# +# @celery.job +# def generate_encounter_number(): +# """Generate unique encounter number""" +# from django.utils.crypto import get_random_string +# return f"ENC{timezone.now().strftime('%Y%m%d')}{get_random_string(4, '0123456789')}" +# diff --git a/integration/__pycache__/flows.cpython-312.pyc b/integration/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b3c24349f27e70e79323357e70dcfd123324299 GIT binary patch literal 181 zcmX@j%ge<81bQ<2GR`J3Fgylv(7|UGpvZKFN(N0vzm*I{OhDdekeXj1`k}?CMaBBL ziACj!d5JmYi8+}-PF`tod_hruR%&vIenx(AL1sx}PCQUJF+DXmHLoPTxU#q;H8;M@ zL_agHBsIM#u_QA;Pd_auzr0wlpz;=nO>TZlX-=wL5i8IVMj$Q*F+MUgGBOr116cru CKQaaY literal 0 HcmV?d00001 diff --git a/integration/flows.py b/integration/flows.py new file mode 100644 index 00000000..23834ca0 --- /dev/null +++ b/integration/flows.py @@ -0,0 +1,781 @@ +# """ +# Viewflow workflows for integration app. +# Provides external system integration, data synchronization, and API management 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 ( +# ExternalSystem, IntegrationEndpoint, DataMapping, SyncConfiguration, +# IntegrationExecution, WebhookEndpoint, WebhookExecution, IntegrationLog +# ) +# from .views import ( +# SystemSetupView, EndpointConfigurationView, DataMappingView, +# SyncConfigurationView, TestConnectionView, MonitoringView, +# WebhookManagementView, SecurityConfigurationView, PerformanceOptimizationView +# ) +# +# +# class SystemIntegrationProcess(Process): +# """ +# Viewflow process model for system integration +# """ +# external_system = ModelField(ExternalSystem, help_text='Associated external system') +# +# # Process status tracking +# system_registered = models.BooleanField(default=False) +# connection_tested = models.BooleanField(default=False) +# endpoints_configured = models.BooleanField(default=False) +# data_mapping_created = models.BooleanField(default=False) +# security_configured = models.BooleanField(default=False) +# testing_completed = models.BooleanField(default=False) +# monitoring_setup = models.BooleanField(default=False) +# integration_activated = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'System Integration Process' +# verbose_name_plural = 'System Integration Processes' +# +# +# class SystemIntegrationFlow(Flow): +# """ +# System Integration Workflow +# +# This flow manages complete external system integration including +# setup, configuration, testing, and activation. +# """ +# +# process_class = SystemIntegrationProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_system_integration) +# .Next(this.register_system) +# ) +# +# register_system = ( +# flow_view(SystemSetupView) +# .Permission('integration.can_setup_systems') +# .Next(this.test_connection) +# ) +# +# test_connection = ( +# flow_view(TestConnectionView) +# .Permission('integration.can_test_connections') +# .Next(this.configure_endpoints) +# ) +# +# configure_endpoints = ( +# flow_view(EndpointConfigurationView) +# .Permission('integration.can_configure_endpoints') +# .Next(this.create_data_mapping) +# ) +# +# create_data_mapping = ( +# flow_view(DataMappingView) +# .Permission('integration.can_create_mappings') +# .Next(this.configure_security) +# ) +# +# configure_security = ( +# flow_view(SecurityConfigurationView) +# .Permission('integration.can_configure_security') +# .Next(this.complete_testing) +# ) +# +# complete_testing = ( +# flow_func(this.perform_integration_testing) +# .Next(this.setup_monitoring) +# ) +# +# setup_monitoring = ( +# flow_view(MonitoringView) +# .Permission('integration.can_setup_monitoring') +# .Next(this.activate_integration) +# ) +# +# activate_integration = ( +# flow_func(this.activate_system_integration) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_system_integration) +# +# # Flow functions +# def start_system_integration(self, activation): +# """Initialize the system integration process""" +# process = activation.process +# system = process.external_system +# +# # Send integration notification +# self.notify_integration_start(system) +# +# # Create integration checklist +# self.create_integration_checklist(system) +# +# # Initialize integration logging +# self.setup_integration_logging(system) +# +# def perform_integration_testing(self, activation): +# """Perform comprehensive integration testing""" +# process = activation.process +# system = process.external_system +# +# # Execute integration tests +# test_results = self.execute_integration_tests(system) +# +# # Mark testing completed +# process.testing_completed = True +# process.save() +# +# # Store test results +# self.store_integration_test_results(system, test_results) +# +# # Validate test results +# self.validate_test_results(system, test_results) +# +# def activate_system_integration(self, activation): +# """Activate the system integration""" +# process = activation.process +# system = process.external_system +# +# # Activate system +# system.is_active = True +# system.save() +# +# # Mark integration activated +# process.integration_activated = True +# process.save() +# +# # Send activation notifications +# self.notify_integration_activation(system) +# +# # Schedule health checks +# self.schedule_health_checks(system) +# +# # Start monitoring +# self.start_integration_monitoring(system) +# +# def end_system_integration(self, activation): +# """End the system integration workflow""" +# process = activation.process +# +# # Generate integration summary +# self.generate_integration_summary(process.external_system) +# +# # Helper methods +# def notify_integration_start(self, system): +# """Notify integration start""" +# integration_team = User.objects.filter(groups__name='Integration Team') +# for staff in integration_team: +# send_mail( +# subject=f'System Integration Started: {system.name}', +# message=f'Integration process started for "{system.name}".', +# from_email='integration@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def create_integration_checklist(self, system): +# """Create integration checklist""" +# # This would create integration checklist +# pass +# +# def setup_integration_logging(self, system): +# """Setup integration logging""" +# IntegrationLog.objects.create( +# external_system=system, +# level='info', +# category='system', +# message=f'Integration process started for {system.name}' +# ) +# +# def execute_integration_tests(self, system): +# """Execute comprehensive integration tests""" +# # This would run integration tests +# return {'status': 'passed', 'tests_run': 10, 'failures': 0} +# +# def store_integration_test_results(self, system, results): +# """Store integration test results""" +# # This would store test results +# pass +# +# def validate_test_results(self, system, results): +# """Validate integration test results""" +# # This would validate test results +# if results.get('failures', 0) > 0: +# raise Exception('Integration tests failed') +# +# def notify_integration_activation(self, system): +# """Notify integration activation""" +# # Notify relevant teams +# integration_team = User.objects.filter(groups__name='Integration Team') +# for staff in integration_team: +# send_mail( +# subject=f'System Integration Activated: {system.name}', +# message=f'Integration for "{system.name}" has been activated.', +# from_email='integration@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def schedule_health_checks(self, system): +# """Schedule periodic health checks""" +# # Schedule health check task +# system_health_check.apply_async( +# args=[system.system_id], +# countdown=300 # 5 minutes +# ) +# +# def start_integration_monitoring(self, system): +# """Start integration monitoring""" +# # This would start monitoring +# pass +# +# def generate_integration_summary(self, system): +# """Generate integration summary""" +# # This would generate integration summary +# pass +# +# +# class DataSynchronizationProcess(Process): +# """ +# Viewflow process model for data synchronization +# """ +# sync_configuration = ModelField(SyncConfiguration, help_text='Associated sync configuration') +# +# # Process status tracking +# sync_initiated = models.BooleanField(default=False) +# data_extracted = models.BooleanField(default=False) +# data_transformed = models.BooleanField(default=False) +# data_validated = models.BooleanField(default=False) +# data_loaded = models.BooleanField(default=False) +# conflicts_resolved = models.BooleanField(default=False) +# sync_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Data Synchronization Process' +# verbose_name_plural = 'Data Synchronization Processes' +# +# +# class DataSynchronizationFlow(Flow): +# """ +# Data Synchronization Workflow +# +# This flow manages automated data synchronization between +# external systems and the hospital management system. +# """ +# +# process_class = DataSynchronizationProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_data_synchronization) +# .Next(this.initiate_sync) +# ) +# +# initiate_sync = ( +# flow_func(this.setup_sync_process) +# .Next(this.extract_data) +# ) +# +# extract_data = ( +# flow_func(this.perform_data_extraction) +# .Next(this.transform_data) +# ) +# +# transform_data = ( +# flow_func(this.perform_data_transformation) +# .Next(this.validate_data) +# ) +# +# validate_data = ( +# flow_func(this.perform_data_validation) +# .Next(this.load_data) +# ) +# +# load_data = ( +# flow_func(this.perform_data_loading) +# .Next(this.resolve_conflicts) +# ) +# +# resolve_conflicts = ( +# flow_func(this.handle_data_conflicts) +# .Next(this.complete_sync) +# ) +# +# complete_sync = ( +# flow_func(this.finalize_data_synchronization) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_data_synchronization) +# +# # Flow functions +# def start_data_synchronization(self, activation): +# """Initialize the data synchronization process""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Send sync notification +# self.notify_sync_start(sync_config) +# +# # Create sync execution record +# self.create_sync_execution(sync_config) +# +# def setup_sync_process(self, activation): +# """Setup synchronization process""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Mark sync initiated +# process.sync_initiated = True +# process.save() +# +# # Prepare sync environment +# self.prepare_sync_environment(sync_config) +# +# def perform_data_extraction(self, activation): +# """Extract data from source system""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Extract data +# extracted_data = self.extract_source_data(sync_config) +# +# # Mark data extracted +# process.data_extracted = True +# process.save() +# +# # Store extracted data +# self.store_extracted_data(sync_config, extracted_data) +# +# def perform_data_transformation(self, activation): +# """Transform data according to mapping rules""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Transform data +# transformed_data = self.transform_sync_data(sync_config) +# +# # Mark data transformed +# process.data_transformed = True +# process.save() +# +# # Store transformed data +# self.store_transformed_data(sync_config, transformed_data) +# +# def perform_data_validation(self, activation): +# """Validate transformed data""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Validate data +# validation_results = self.validate_sync_data(sync_config) +# +# # Mark data validated +# process.data_validated = True +# process.save() +# +# # Store validation results +# self.store_validation_results(sync_config, validation_results) +# +# def perform_data_loading(self, activation): +# """Load data into target system""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Load data +# loading_results = self.load_sync_data(sync_config) +# +# # Mark data loaded +# process.data_loaded = True +# process.save() +# +# # Store loading results +# self.store_loading_results(sync_config, loading_results) +# +# def handle_data_conflicts(self, activation): +# """Handle data conflicts and duplicates""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Resolve conflicts +# conflict_results = self.resolve_data_conflicts(sync_config) +# +# # Mark conflicts resolved +# process.conflicts_resolved = True +# process.save() +# +# # Store conflict resolution results +# self.store_conflict_results(sync_config, conflict_results) +# +# def finalize_data_synchronization(self, activation): +# """Finalize the data synchronization process""" +# process = activation.process +# sync_config = process.sync_configuration +# +# # Mark sync completed +# process.sync_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_sync_completion(sync_config) +# +# # Update sync statistics +# self.update_sync_statistics(sync_config) +# +# # Schedule next sync if recurring +# self.schedule_next_sync(sync_config) +# +# def end_data_synchronization(self, activation): +# """End the data synchronization workflow""" +# process = activation.process +# +# # Generate sync summary +# self.generate_sync_summary(process.sync_configuration) +# +# # Helper methods +# def notify_sync_start(self, sync_config): +# """Notify sync start""" +# # This would notify relevant parties +# pass +# +# def create_sync_execution(self, sync_config): +# """Create sync execution record""" +# # This would create execution record +# pass +# +# def prepare_sync_environment(self, sync_config): +# """Prepare synchronization environment""" +# # This would prepare sync environment +# pass +# +# def extract_source_data(self, sync_config): +# """Extract data from source system""" +# # This would extract data from source +# return {'status': 'extracted', 'records': 1000} +# +# def store_extracted_data(self, sync_config, data): +# """Store extracted data""" +# # This would store extracted data +# pass +# +# def transform_sync_data(self, sync_config): +# """Transform data according to mapping""" +# # This would transform data +# return {'status': 'transformed', 'records': 1000} +# +# def store_transformed_data(self, sync_config, data): +# """Store transformed data""" +# # This would store transformed data +# pass +# +# def validate_sync_data(self, sync_config): +# """Validate transformed data""" +# # This would validate data +# return {'status': 'valid', 'errors': []} +# +# def store_validation_results(self, sync_config, results): +# """Store validation results""" +# # This would store validation results +# pass +# +# def load_sync_data(self, sync_config): +# """Load data into target system""" +# # This would load data +# return {'status': 'loaded', 'records': 1000} +# +# def store_loading_results(self, sync_config, results): +# """Store loading results""" +# # This would store loading results +# pass +# +# def resolve_data_conflicts(self, sync_config): +# """Resolve data conflicts""" +# # This would resolve conflicts +# return {'status': 'resolved', 'conflicts': 0} +# +# def store_conflict_results(self, sync_config, results): +# """Store conflict resolution results""" +# # This would store conflict results +# pass +# +# def notify_sync_completion(self, sync_config): +# """Notify sync completion""" +# # This would notify completion +# pass +# +# def update_sync_statistics(self, sync_config): +# """Update synchronization statistics""" +# # This would update sync stats +# pass +# +# def schedule_next_sync(self, sync_config): +# """Schedule next synchronization""" +# if sync_config.is_recurring: +# # Schedule next sync +# data_sync.apply_async( +# args=[sync_config.sync_id], +# countdown=sync_config.sync_interval_seconds +# ) +# +# def generate_sync_summary(self, sync_config): +# """Generate synchronization summary""" +# # This would generate sync summary +# pass +# +# +# class WebhookManagementProcess(Process): +# """ +# Viewflow process model for webhook management +# """ +# webhook_endpoint = ModelField(WebhookEndpoint, help_text='Associated webhook endpoint') +# +# # Process status tracking +# webhook_created = models.BooleanField(default=False) +# security_configured = models.BooleanField(default=False) +# testing_completed = models.BooleanField(default=False) +# monitoring_setup = models.BooleanField(default=False) +# webhook_activated = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Webhook Management Process' +# verbose_name_plural = 'Webhook Management Processes' +# +# +# class WebhookManagementFlow(Flow): +# """ +# Webhook Management Workflow +# +# This flow manages webhook endpoint creation, configuration, +# testing, and activation for receiving external data. +# """ +# +# process_class = WebhookManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_webhook_management) +# .Next(this.create_webhook) +# ) +# +# create_webhook = ( +# flow_view(WebhookManagementView) +# .Permission('integration.can_manage_webhooks') +# .Next(this.configure_security) +# ) +# +# configure_security = ( +# flow_func(this.setup_webhook_security) +# .Next(this.test_webhook) +# ) +# +# test_webhook = ( +# flow_func(this.perform_webhook_testing) +# .Next(this.setup_monitoring) +# ) +# +# setup_monitoring = ( +# flow_func(this.configure_webhook_monitoring) +# .Next(this.activate_webhook) +# ) +# +# activate_webhook = ( +# flow_func(this.activate_webhook_endpoint) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_webhook_management) +# +# # Flow functions +# def start_webhook_management(self, activation): +# """Initialize the webhook management process""" +# process = activation.process +# webhook = process.webhook_endpoint +# +# # Send webhook creation notification +# self.notify_webhook_creation(webhook) +# +# def setup_webhook_security(self, activation): +# """Setup webhook security configuration""" +# process = activation.process +# webhook = process.webhook_endpoint +# +# # Configure security settings +# self.configure_webhook_security(webhook) +# +# # Mark security configured +# process.security_configured = True +# process.save() +# +# def perform_webhook_testing(self, activation): +# """Perform webhook testing""" +# process = activation.process +# webhook = process.webhook_endpoint +# +# # Test webhook functionality +# test_results = self.test_webhook_functionality(webhook) +# +# # Mark testing completed +# process.testing_completed = True +# process.save() +# +# # Store test results +# self.store_webhook_test_results(webhook, test_results) +# +# def configure_webhook_monitoring(self, activation): +# """Configure webhook monitoring""" +# process = activation.process +# webhook = process.webhook_endpoint +# +# # Setup monitoring +# self.setup_webhook_monitoring(webhook) +# +# # Mark monitoring setup +# process.monitoring_setup = True +# process.save() +# +# def activate_webhook_endpoint(self, activation): +# """Activate webhook endpoint""" +# process = activation.process +# webhook = process.webhook_endpoint +# +# # Activate webhook +# webhook.is_active = True +# webhook.save() +# +# # Mark webhook activated +# process.webhook_activated = True +# process.save() +# +# # Send activation notifications +# self.notify_webhook_activation(webhook) +# +# def end_webhook_management(self, activation): +# """End the webhook management workflow""" +# process = activation.process +# +# # Generate webhook summary +# self.generate_webhook_summary(process.webhook_endpoint) +# +# # Helper methods +# def notify_webhook_creation(self, webhook): +# """Notify webhook creation""" +# integration_team = User.objects.filter(groups__name='Integration Team') +# for staff in integration_team: +# send_mail( +# subject=f'Webhook Created: {webhook.name}', +# message=f'Webhook endpoint "{webhook.name}" has been created.', +# from_email='integration@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def configure_webhook_security(self, webhook): +# """Configure webhook security""" +# # This would configure security settings +# pass +# +# def test_webhook_functionality(self, webhook): +# """Test webhook functionality""" +# # This would test webhook +# return {'status': 'passed', 'tests': 5} +# +# def store_webhook_test_results(self, webhook, results): +# """Store webhook test results""" +# # This would store test results +# pass +# +# def setup_webhook_monitoring(self, webhook): +# """Setup webhook monitoring""" +# # This would setup monitoring +# pass +# +# def notify_webhook_activation(self, webhook): +# """Notify webhook activation""" +# # This would notify activation +# pass +# +# def generate_webhook_summary(self, webhook): +# """Generate webhook summary""" +# # This would generate webhook summary +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def system_health_check(system_id): +# """Background task for system health monitoring""" +# try: +# system = ExternalSystem.objects.get(system_id=system_id) +# +# # Perform health check +# # This would perform system health check +# +# # Schedule next health check +# system_health_check.apply_async( +# args=[system_id], +# countdown=300 # 5 minutes +# ) +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def data_sync(sync_id): +# """Background task for data synchronization""" +# try: +# sync_config = SyncConfiguration.objects.get(sync_id=sync_id) +# +# # Start data synchronization workflow +# # This would start the data sync workflow +# +# return True +# except Exception: +# return False +# +# +# @celery.job +# def webhook_health_check(): +# """Background task for webhook health monitoring""" +# try: +# # This would monitor webhook health +# return True +# except Exception: +# return False +# +# +# @celery.job +# def integration_performance_monitoring(): +# """Background task for integration performance monitoring""" +# try: +# # This would monitor integration performance +# return True +# except Exception: +# return False +# +# +# @celery.job +# def cleanup_integration_logs(): +# """Background task to cleanup old integration logs""" +# try: +# # This would cleanup old logs +# return True +# except Exception: +# return False +# diff --git a/inventory/__pycache__/flows.cpython-312.pyc b/inventory/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98e4ebf1803468793be5ef80ea6bbf2b1194cf5e GIT binary patch literal 179 zcmX@j%ge<81bQ<2GF(a+7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@Sx{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqMw;p1{BCIs?<-*$uBR~E2zB1VUwGmQks)$SHudmf)R*|L5z>gjEsy$%s>_Z$uKb2 literal 0 HcmV?d00001 diff --git a/inventory/flows.py b/inventory/flows.py new file mode 100644 index 00000000..845c5d5e --- /dev/null +++ b/inventory/flows.py @@ -0,0 +1,905 @@ +# """ +# Viewflow workflows for inventory app. +# Provides inventory management, procurement, and supply chain 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 InventoryItem, PurchaseOrder, PurchaseOrderItem, Supplier, InventoryStock, InventoryLocation +# from .views import ( +# PurchaseRequestView, VendorSelectionView, PurchaseOrderCreationView, +# ApprovalView, OrderSubmissionView, ReceivingView, InspectionView, +# StockUpdateView, InvoiceMatchingView, PaymentProcessingView, +# StockReplenishmentView, StockTransferView, StockAdjustmentView, +# CycleCountView, InventoryAuditView +# ) +# +# +# class ProcurementProcess(Process): +# """ +# Viewflow process model for procurement +# """ +# purchase_order = ModelField(PurchaseOrder, help_text='Associated purchase order') +# +# # Process status tracking +# request_submitted = models.BooleanField(default=False) +# vendor_selected = models.BooleanField(default=False) +# order_created = models.BooleanField(default=False) +# order_approved = models.BooleanField(default=False) +# order_sent = models.BooleanField(default=False) +# goods_received = models.BooleanField(default=False) +# invoice_processed = models.BooleanField(default=False) +# payment_completed = models.BooleanField(default=False) +# procurement_closed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Procurement Process' +# verbose_name_plural = 'Procurement Processes' +# +# +# class ProcurementFlow(Flow): +# """ +# Procurement Workflow +# +# This flow manages the complete procurement process from purchase +# request through payment and order closure. +# """ +# +# process_class = ProcurementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_procurement) +# .Next(this.submit_request) +# ) +# +# submit_request = ( +# flow_view(PurchaseRequestView) +# .Permission('inventory.can_submit_purchase_requests') +# .Next(this.select_vendor) +# ) +# +# select_vendor = ( +# flow_view(VendorSelectionView) +# .Permission('inventory.can_select_vendors') +# .Next(this.create_order) +# ) +# +# create_order = ( +# flow_view(PurchaseOrderCreationView) +# .Permission('inventory.can_create_purchase_orders') +# .Next(this.approve_order) +# ) +# +# approve_order = ( +# flow_view(ApprovalView) +# .Permission('inventory.can_approve_purchase_orders') +# .Next(this.send_order) +# ) +# +# send_order = ( +# flow_view(OrderSubmissionView) +# .Permission('inventory.can_send_purchase_orders') +# .Next(this.receive_goods) +# ) +# +# receive_goods = ( +# flow_view(ReceivingView) +# .Permission('inventory.can_receive_goods') +# .Next(this.inspect_goods) +# ) +# +# inspect_goods = ( +# flow_view(InspectionView) +# .Permission('inventory.can_inspect_goods') +# .Next(this.update_stock) +# ) +# +# update_stock = ( +# flow_view(StockUpdateView) +# .Permission('inventory.can_update_stock') +# .Next(this.process_invoice) +# ) +# +# process_invoice = ( +# flow_view(InvoiceMatchingView) +# .Permission('inventory.can_process_invoices') +# .Next(this.process_payment) +# ) +# +# process_payment = ( +# flow_view(PaymentProcessingView) +# .Permission('inventory.can_process_payments') +# .Next(this.close_order) +# ) +# +# close_order = ( +# flow_func(this.complete_procurement) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_procurement) +# +# # Flow functions +# def start_procurement(self, activation): +# """Initialize the procurement process""" +# process = activation.process +# order = process.purchase_order +# +# # Update order status +# order.status = 'DRAFT' +# order.save() +# +# # Send notification to procurement staff +# self.notify_procurement_staff(order) +# +# # Check for urgent orders +# if order.priority in ['HIGH', 'URGENT']: +# self.notify_urgent_procurement(order) +# +# def complete_procurement(self, activation): +# """Finalize the procurement process""" +# process = activation.process +# order = process.purchase_order +# +# # Update order status +# order.status = 'CLOSED' +# order.save() +# +# # Mark process as completed +# process.procurement_closed = True +# process.save() +# +# # Send completion notifications +# self.notify_procurement_completion(order) +# +# # Update supplier performance metrics +# self.update_supplier_performance(order) +# +# # Update procurement metrics +# self.update_procurement_metrics(order) +# +# def end_procurement(self, activation): +# """End the procurement workflow""" +# process = activation.process +# +# # Generate procurement summary report +# self.generate_procurement_summary(process.purchase_order) +# +# # Helper methods +# def notify_procurement_staff(self, order): +# """Notify procurement staff of new order""" +# from django.contrib.auth.models import Group +# +# procurement_staff = User.objects.filter( +# groups__name='Procurement Staff' +# ) +# +# for staff in procurement_staff: +# send_mail( +# subject=f'New Purchase Order: {order.po_number}', +# message=f'New purchase order for {order.supplier.name} requires processing.', +# from_email='procurement@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_urgent_procurement(self, order): +# """Notify of urgent procurement""" +# procurement_managers = User.objects.filter( +# groups__name='Procurement Managers' +# ) +# +# for manager in procurement_managers: +# send_mail( +# subject=f'URGENT Purchase Order: {order.po_number}', +# message=f'{order.get_priority_display()} purchase order requires immediate attention.', +# from_email='procurement@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def notify_procurement_completion(self, order): +# """Notify procurement completion""" +# # Notify requestor +# if order.requested_by and order.requested_by.email: +# send_mail( +# subject=f'Purchase Order Complete: {order.po_number}', +# message=f'Your purchase order has been completed and goods received.', +# from_email='procurement@hospital.com', +# recipient_list=[order.requested_by.email], +# fail_silently=True +# ) +# +# def update_supplier_performance(self, order): +# """Update supplier performance metrics""" +# supplier = order.supplier +# +# # Calculate on-time delivery +# if order.actual_delivery_date and order.promised_delivery_date: +# if order.actual_delivery_date <= order.promised_delivery_date: +# # Update on-time delivery rate +# pass +# +# # This would update comprehensive supplier metrics +# pass +# +# def update_procurement_metrics(self, order): +# """Update procurement performance metrics""" +# # This would update procurement cycle time and other metrics +# pass +# +# def generate_procurement_summary(self, order): +# """Generate procurement summary report""" +# # This would generate a comprehensive procurement report +# pass +# +# +# class InventoryReplenishmentProcess(Process): +# """ +# Viewflow process model for inventory replenishment +# """ +# inventory_item = ModelField(InventoryItem, help_text='Associated inventory item') +# +# # Process status tracking +# reorder_triggered = models.BooleanField(default=False) +# demand_analyzed = models.BooleanField(default=False) +# quantity_calculated = models.BooleanField(default=False) +# supplier_contacted = models.BooleanField(default=False) +# order_placed = models.BooleanField(default=False) +# delivery_scheduled = models.BooleanField(default=False) +# stock_replenished = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Inventory Replenishment Process' +# verbose_name_plural = 'Inventory Replenishment Processes' +# +# +# class InventoryReplenishmentFlow(Flow): +# """ +# Inventory Replenishment Workflow +# +# This flow manages automatic and manual inventory replenishment +# including demand analysis and supplier coordination. +# """ +# +# process_class = InventoryReplenishmentProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_replenishment) +# .Next(this.trigger_reorder) +# ) +# +# trigger_reorder = ( +# flow_func(this.check_reorder_point) +# .Next(this.analyze_demand) +# ) +# +# analyze_demand = ( +# flow_view(DemandAnalysisView) +# .Permission('inventory.can_analyze_demand') +# .Next(this.calculate_quantity) +# ) +# +# calculate_quantity = ( +# flow_view(QuantityCalculationView) +# .Permission('inventory.can_calculate_quantities') +# .Next(this.contact_supplier) +# ) +# +# contact_supplier = ( +# flow_view(SupplierContactView) +# .Permission('inventory.can_contact_suppliers') +# .Next(this.place_order) +# ) +# +# place_order = ( +# flow_view(OrderPlacementView) +# .Permission('inventory.can_place_orders') +# .Next(this.schedule_delivery) +# ) +# +# schedule_delivery = ( +# flow_view(DeliverySchedulingView) +# .Permission('inventory.can_schedule_deliveries') +# .Next(this.replenish_stock) +# ) +# +# replenish_stock = ( +# flow_func(this.complete_replenishment) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_replenishment) +# +# # Flow functions +# def start_replenishment(self, activation): +# """Initialize the replenishment process""" +# process = activation.process +# item = process.inventory_item +# +# # Send notification to inventory staff +# self.notify_replenishment_needed(item) +# +# def check_reorder_point(self, activation): +# """Check if item has reached reorder point""" +# process = activation.process +# item = process.inventory_item +# +# # Check current stock levels +# current_stock = item.total_stock +# +# if current_stock <= item.reorder_point: +# process.reorder_triggered = True +# process.save() +# +# # Send urgent notification if below safety stock +# if current_stock <= item.safety_stock: +# self.notify_critical_stock(item) +# +# def complete_replenishment(self, activation): +# """Finalize the replenishment process""" +# process = activation.process +# item = process.inventory_item +# +# # Mark process as completed +# process.stock_replenished = True +# process.save() +# +# # Send completion notifications +# self.notify_replenishment_completion(item) +# +# # Update inventory metrics +# self.update_inventory_metrics(item) +# +# def end_replenishment(self, activation): +# """End the replenishment workflow""" +# process = activation.process +# +# # Generate replenishment summary +# self.generate_replenishment_summary(process.inventory_item) +# +# # Helper methods +# def notify_replenishment_needed(self, item): +# """Notify inventory staff of replenishment need""" +# inventory_staff = User.objects.filter( +# groups__name='Inventory Staff' +# ) +# +# for staff in inventory_staff: +# send_mail( +# subject=f'Replenishment Needed: {item.item_name}', +# message=f'Item {item.item_code} has reached reorder point.', +# from_email='inventory@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_critical_stock(self, item): +# """Notify of critical stock levels""" +# inventory_managers = User.objects.filter( +# groups__name='Inventory Managers' +# ) +# +# for manager in inventory_managers: +# send_mail( +# subject=f'CRITICAL STOCK: {item.item_name}', +# message=f'Item {item.item_code} is below safety stock level.', +# from_email='inventory@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def notify_replenishment_completion(self, item): +# """Notify replenishment completion""" +# # This would notify relevant staff +# pass +# +# def update_inventory_metrics(self, item): +# """Update inventory performance metrics""" +# # This would update inventory turnover and other metrics +# pass +# +# def generate_replenishment_summary(self, item): +# """Generate replenishment summary""" +# # This would generate replenishment summary +# pass +# +# +# class StockMovementProcess(Process): +# """ +# Viewflow process model for stock movements +# """ +# movement_type = CharField(max_length=20, help_text='Type of stock movement') +# item_id = CharField(max_length=50, help_text='Item identifier') +# +# # Process status tracking +# movement_initiated = models.BooleanField(default=False) +# authorization_verified = models.BooleanField(default=False) +# stock_reserved = models.BooleanField(default=False) +# movement_executed = models.BooleanField(default=False) +# documentation_completed = models.BooleanField(default=False) +# movement_verified = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Stock Movement Process' +# verbose_name_plural = 'Stock Movement Processes' +# +# +# class StockMovementFlow(Flow): +# """ +# Stock Movement Workflow +# +# This flow manages stock transfers, adjustments, and other +# inventory movements with proper authorization and tracking. +# """ +# +# process_class = StockMovementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_movement) +# .Next(this.initiate_movement) +# ) +# +# initiate_movement = ( +# flow_view(MovementInitiationView) +# .Permission('inventory.can_initiate_movements') +# .Next(this.verify_authorization) +# ) +# +# verify_authorization = ( +# flow_view(AuthorizationVerificationView) +# .Permission('inventory.can_verify_authorization') +# .Next(this.reserve_stock) +# ) +# +# reserve_stock = ( +# flow_view(StockReservationView) +# .Permission('inventory.can_reserve_stock') +# .Next(this.execute_movement) +# ) +# +# execute_movement = ( +# flow_view(MovementExecutionView) +# .Permission('inventory.can_execute_movements') +# .Next(this.complete_documentation) +# ) +# +# complete_documentation = ( +# flow_view(DocumentationView) +# .Permission('inventory.can_complete_documentation') +# .Next(this.verify_movement) +# ) +# +# verify_movement = ( +# flow_view(MovementVerificationView) +# .Permission('inventory.can_verify_movements') +# .Next(this.finalize_movement) +# ) +# +# finalize_movement = ( +# flow_func(this.complete_movement) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_movement) +# +# # Flow functions +# def start_movement(self, activation): +# """Initialize the stock movement process""" +# process = activation.process +# +# # Send notification to inventory staff +# self.notify_movement_initiated(process.movement_type, process.item_id) +# +# def complete_movement(self, activation): +# """Finalize the stock movement process""" +# process = activation.process +# +# # Mark process as completed +# process.movement_verified = True +# process.save() +# +# # Send completion notifications +# self.notify_movement_completion(process.movement_type, process.item_id) +# +# # Update inventory records +# self.update_inventory_records(process.movement_type, process.item_id) +# +# def end_movement(self, activation): +# """End the stock movement workflow""" +# process = activation.process +# +# # Generate movement summary +# self.generate_movement_summary(process.movement_type, process.item_id) +# +# # Helper methods +# def notify_movement_initiated(self, movement_type, item_id): +# """Notify inventory staff of movement initiation""" +# inventory_staff = User.objects.filter( +# groups__name='Inventory Staff' +# ) +# +# for staff in inventory_staff: +# send_mail( +# subject=f'Stock Movement Initiated: {item_id}', +# message=f'{movement_type} movement initiated for item {item_id}.', +# from_email='inventory@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_movement_completion(self, movement_type, item_id): +# """Notify movement completion""" +# # This would notify relevant staff +# pass +# +# def update_inventory_records(self, movement_type, item_id): +# """Update inventory records""" +# # This would update inventory records +# pass +# +# def generate_movement_summary(self, movement_type, item_id): +# """Generate movement summary""" +# # This would generate movement summary +# pass +# +# +# class InventoryAuditProcess(Process): +# """ +# Viewflow process model for inventory audits +# """ +# audit_type = CharField(max_length=20, help_text='Type of audit') +# location_id = CharField(max_length=50, help_text='Location identifier') +# +# # Process status tracking +# audit_scheduled = models.BooleanField(default=False) +# audit_team_assigned = models.BooleanField(default=False) +# physical_count_completed = models.BooleanField(default=False) +# discrepancies_identified = models.BooleanField(default=False) +# adjustments_made = models.BooleanField(default=False) +# audit_report_generated = models.BooleanField(default=False) +# audit_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Inventory Audit Process' +# verbose_name_plural = 'Inventory Audit Processes' +# +# +# class InventoryAuditFlow(Flow): +# """ +# Inventory Audit Workflow +# +# This flow manages inventory audits including cycle counts, +# physical inventories, and discrepancy resolution. +# """ +# +# process_class = InventoryAuditProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_audit) +# .Next(this.schedule_audit) +# ) +# +# schedule_audit = ( +# flow_view(AuditSchedulingView) +# .Permission('inventory.can_schedule_audits') +# .Next(this.assign_team) +# ) +# +# assign_team = ( +# flow_view(TeamAssignmentView) +# .Permission('inventory.can_assign_audit_teams') +# .Next(this.conduct_count) +# ) +# +# conduct_count = ( +# flow_view(CycleCountView) +# .Permission('inventory.can_conduct_counts') +# .Next(this.identify_discrepancies) +# ) +# +# identify_discrepancies = ( +# flow_func(this.analyze_discrepancies) +# .Next(this.make_adjustments) +# ) +# +# make_adjustments = ( +# flow_view(InventoryAdjustmentView) +# .Permission('inventory.can_make_adjustments') +# .Next(this.generate_report) +# ) +# +# generate_report = ( +# flow_view(AuditReportView) +# .Permission('inventory.can_generate_audit_reports') +# .Next(this.complete_audit) +# ) +# +# complete_audit = ( +# flow_func(this.finalize_audit) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_audit) +# +# # Flow functions +# def start_audit(self, activation): +# """Initialize the audit process""" +# process = activation.process +# +# # Send notification to audit team +# self.notify_audit_scheduled(process.audit_type, process.location_id) +# +# def analyze_discrepancies(self, activation): +# """Analyze inventory discrepancies""" +# process = activation.process +# +# # Check for discrepancies +# discrepancies = self.check_discrepancies(process.location_id) +# +# if discrepancies: +# process.discrepancies_identified = True +# process.save() +# +# # Alert audit supervisor +# self.alert_audit_supervisor(process.location_id, discrepancies) +# +# def finalize_audit(self, activation): +# """Finalize the audit process""" +# process = activation.process +# +# # Mark audit as completed +# process.audit_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_audit_completion(process.audit_type, process.location_id) +# +# # Update audit metrics +# self.update_audit_metrics(process.audit_type, process.location_id) +# +# def end_audit(self, activation): +# """End the audit workflow""" +# process = activation.process +# +# # Generate audit summary +# self.generate_audit_summary(process.audit_type, process.location_id) +# +# # Helper methods +# def notify_audit_scheduled(self, audit_type, location_id): +# """Notify audit team of scheduled audit""" +# audit_staff = User.objects.filter( +# groups__name='Audit Staff' +# ) +# +# for staff in audit_staff: +# send_mail( +# subject=f'Audit Scheduled: {location_id}', +# message=f'{audit_type} audit scheduled for location {location_id}.', +# from_email='audit@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def check_discrepancies(self, location_id): +# """Check for inventory discrepancies""" +# # This would implement discrepancy checking logic +# return [] +# +# def alert_audit_supervisor(self, location_id, discrepancies): +# """Alert audit supervisor of discrepancies""" +# supervisors = User.objects.filter( +# groups__name='Audit Supervisors' +# ) +# +# for supervisor in supervisors: +# send_mail( +# subject=f'Audit Discrepancies Found: {location_id}', +# message=f'Inventory discrepancies identified during audit.', +# from_email='audit@hospital.com', +# recipient_list=[supervisor.email], +# fail_silently=True +# ) +# +# def notify_audit_completion(self, audit_type, location_id): +# """Notify audit completion""" +# # This would notify relevant parties +# pass +# +# def update_audit_metrics(self, audit_type, location_id): +# """Update audit metrics""" +# # This would update audit performance metrics +# pass +# +# def generate_audit_summary(self, audit_type, location_id): +# """Generate audit summary""" +# # This would generate audit summary +# pass +# +# +# class SupplierManagementProcess(Process): +# """ +# Viewflow process model for supplier management +# """ +# supplier = ModelField(Supplier, help_text='Associated supplier') +# +# # Process status tracking +# supplier_onboarded = models.BooleanField(default=False) +# qualifications_verified = models.BooleanField(default=False) +# contracts_negotiated = models.BooleanField(default=False) +# performance_monitored = models.BooleanField(default=False) +# relationship_maintained = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Supplier Management Process' +# verbose_name_plural = 'Supplier Management Processes' +# +# +# class SupplierManagementFlow(Flow): +# """ +# Supplier Management Workflow +# +# This flow manages supplier onboarding, qualification, +# performance monitoring, and relationship management. +# """ +# +# process_class = SupplierManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_supplier_management) +# .Next(this.onboard_supplier) +# ) +# +# onboard_supplier = ( +# flow_view(SupplierOnboardingView) +# .Permission('inventory.can_onboard_suppliers') +# .Next(this.verify_qualifications) +# ) +# +# verify_qualifications = ( +# flow_view(QualificationVerificationView) +# .Permission('inventory.can_verify_qualifications') +# .Next(this.negotiate_contracts) +# ) +# +# negotiate_contracts = ( +# flow_view(ContractNegotiationView) +# .Permission('inventory.can_negotiate_contracts') +# .Next(this.monitor_performance) +# ) +# +# monitor_performance = ( +# flow_view(PerformanceMonitoringView) +# .Permission('inventory.can_monitor_performance') +# .Next(this.maintain_relationship) +# ) +# +# maintain_relationship = ( +# flow_func(this.complete_supplier_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_supplier_management) +# +# # Flow functions +# def start_supplier_management(self, activation): +# """Initialize the supplier management process""" +# process = activation.process +# supplier = process.supplier +# +# # Send notification to procurement team +# self.notify_supplier_onboarding(supplier) +# +# def complete_supplier_management(self, activation): +# """Finalize the supplier management process""" +# process = activation.process +# supplier = process.supplier +# +# # Mark process as completed +# process.relationship_maintained = True +# process.save() +# +# # Send completion notifications +# self.notify_supplier_management_completion(supplier) +# +# def end_supplier_management(self, activation): +# """End the supplier management workflow""" +# process = activation.process +# +# # Generate supplier management summary +# self.generate_supplier_summary(process.supplier) +# +# # Helper methods +# def notify_supplier_onboarding(self, supplier): +# """Notify procurement team of supplier onboarding""" +# procurement_staff = User.objects.filter( +# groups__name='Procurement Staff' +# ) +# +# for staff in procurement_staff: +# send_mail( +# subject=f'Supplier Onboarding: {supplier.name}', +# message=f'New supplier {supplier.name} requires onboarding.', +# from_email='procurement@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_supplier_management_completion(self, supplier): +# """Notify supplier management completion""" +# # This would notify relevant parties +# pass +# +# def generate_supplier_summary(self, supplier): +# """Generate supplier management summary""" +# # This would generate supplier summary +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_reorder_items(): +# """Background task to automatically reorder items""" +# try: +# # This would check reorder points and create orders +# return True +# except Exception: +# return False +# +# +# @celery.job +# def monitor_expiring_items(): +# """Background task to monitor expiring inventory items""" +# try: +# # This would identify items nearing expiration +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_inventory_reports(): +# """Background task to generate inventory reports""" +# try: +# # This would generate daily inventory reports +# return True +# except Exception: +# return False +# +# +# @celery.job +# def update_supplier_performance(): +# """Background task to update supplier performance metrics""" +# try: +# # This would calculate supplier performance metrics +# return True +# except Exception: +# return False +# +# +# @celery.job +# def schedule_cycle_counts(): +# """Background task to schedule cycle counts""" +# try: +# # This would schedule regular cycle counts +# return True +# except Exception: +# return False +# diff --git a/laboratory/__pycache__/flows.cpython-312.pyc b/laboratory/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55c792fd317247b32610f72eecdcdb2b69f0cab2 GIT binary patch literal 180 zcmX@j%ge<81bQ<2G6Gx~7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@Tc{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqMwtPlwXusl3!G*pO%wfUaVJ8d5gm)H$SB`C)KWq6=(+|5Ep|OADI~$8H<>KECA;o BF$Mqt literal 0 HcmV?d00001 diff --git a/laboratory/flows.py b/laboratory/flows.py new file mode 100644 index 00000000..855bc531 --- /dev/null +++ b/laboratory/flows.py @@ -0,0 +1,523 @@ +# """ +# Viewflow workflows for laboratory app. +# Provides lab test ordering, specimen processing, and result reporting 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 LabOrder, Specimen, LabResult, LabTest +# from .views import ( +# LabOrderCreationView, SpecimenCollectionView, SpecimenReceiptView, +# TestProcessingView, ResultEntryView, ResultVerificationView, +# ResultReportingView +# ) +# +# +# class LabOrderProcess(Process): +# """ +# Viewflow process model for laboratory test orders +# """ +# lab_order = ModelField(LabOrder, help_text='Associated lab order') +# +# # Process status tracking +# order_created = models.BooleanField(default=False) +# specimen_collected = models.BooleanField(default=False) +# specimen_received = models.BooleanField(default=False) +# tests_processed = models.BooleanField(default=False) +# results_verified = models.BooleanField(default=False) +# results_reported = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Lab Order Process' +# verbose_name_plural = 'Lab Order Processes' +# +# +# class LabOrderFlow(Flow): +# """ +# Laboratory Test Order Workflow +# +# This flow manages the complete laboratory testing process from +# order creation through result reporting. +# """ +# +# process_class = LabOrderProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_lab_order) +# .Next(this.create_order) +# ) +# +# create_order = ( +# flow_view(LabOrderCreationView) +# .Permission('laboratory.can_create_orders') +# .Next(this.schedule_collection) +# ) +# +# schedule_collection = ( +# flow_func(this.schedule_specimen_collection) +# .Next(this.collect_specimen) +# ) +# +# collect_specimen = ( +# flow_view(SpecimenCollectionView) +# .Permission('laboratory.can_collect_specimens') +# .Next(this.transport_specimen) +# ) +# +# transport_specimen = ( +# flow_func(this.handle_specimen_transport) +# .Next(this.receive_specimen) +# ) +# +# receive_specimen = ( +# flow_view(SpecimenReceiptView) +# .Permission('laboratory.can_receive_specimens') +# .Next(this.check_specimen_quality) +# ) +# +# check_specimen_quality = ( +# flow_func(this.validate_specimen_quality) +# .Next(this.process_tests) +# ) +# +# process_tests = ( +# flow_view(TestProcessingView) +# .Permission('laboratory.can_process_tests') +# .Next(this.enter_results) +# ) +# +# enter_results = ( +# flow_view(ResultEntryView) +# .Permission('laboratory.can_enter_results') +# .Next(this.verify_results) +# ) +# +# verify_results = ( +# flow_view(ResultVerificationView) +# .Permission('laboratory.can_verify_results') +# .Next(this.check_critical_values) +# ) +# +# check_critical_values = ( +# flow_func(this.check_for_critical_values) +# .Next(this.report_results) +# ) +# +# report_results = ( +# flow_view(ResultReportingView) +# .Permission('laboratory.can_report_results') +# .Next(this.finalize_order) +# ) +# +# finalize_order = ( +# flow_func(this.complete_lab_order) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_lab_order) +# +# # Flow functions +# def start_lab_order(self, activation): +# """Initialize the lab order process""" +# process = activation.process +# lab_order = process.lab_order +# +# # Update order status +# lab_order.status = 'PENDING' +# lab_order.save() +# +# # Send notification to lab staff +# self.notify_lab_staff(lab_order) +# +# def schedule_specimen_collection(self, activation): +# """Schedule specimen collection based on order priority""" +# process = activation.process +# lab_order = process.lab_order +# +# # Calculate collection time based on priority +# if lab_order.priority == 'STAT': +# collection_time = timezone.now() + timezone.timedelta(minutes=15) +# elif lab_order.priority == 'URGENT': +# collection_time = timezone.now() + timezone.timedelta(hours=1) +# else: +# collection_time = timezone.now() + timezone.timedelta(hours=4) +# +# # Update order with scheduled collection time +# lab_order.collection_datetime = collection_time +# lab_order.save() +# +# # Notify collection staff +# self.notify_collection_staff(lab_order) +# +# def handle_specimen_transport(self, activation): +# """Handle specimen transport to laboratory""" +# process = activation.process +# lab_order = process.lab_order +# +# # Update specimen status to in transit +# for specimen in lab_order.specimens.all(): +# specimen.status = 'IN_TRANSIT' +# specimen.save() +# +# # Schedule transport based on priority +# if lab_order.priority in ['STAT', 'URGENT']: +# # Immediate transport +# self.notify_transport_team(lab_order, urgent=True) +# else: +# # Regular transport schedule +# self.schedule_regular_transport(lab_order) +# +# def validate_specimen_quality(self, activation): +# """Validate specimen quality and reject if necessary""" +# process = activation.process +# lab_order = process.lab_order +# +# rejected_specimens = [] +# +# for specimen in lab_order.specimens.all(): +# if specimen.quality == 'REJECTED': +# rejected_specimens.append(specimen) +# +# # Notify ordering physician of rejection +# self.notify_specimen_rejection(specimen) +# +# # Request new specimen collection +# self.request_recollection(specimen) +# +# if rejected_specimens: +# # Update order status if specimens rejected +# lab_order.status = 'SPECIMEN_REJECTED' +# lab_order.save() +# else: +# # Proceed with processing +# lab_order.status = 'PROCESSING' +# lab_order.save() +# +# process.specimen_received = True +# process.save() +# +# def check_for_critical_values(self, activation): +# """Check for critical values and alert if found""" +# process = activation.process +# lab_order = process.lab_order +# +# critical_results = [] +# +# for result in lab_order.results.all(): +# if self.is_critical_value(result): +# critical_results.append(result) +# +# if critical_results: +# # Immediate notification for critical values +# self.notify_critical_values(lab_order, critical_results) +# +# # Mark as critical in order +# lab_order.has_critical_values = True +# lab_order.save() +# +# def complete_lab_order(self, activation): +# """Finalize the lab order process""" +# process = activation.process +# lab_order = process.lab_order +# +# # Update order status +# lab_order.status = 'COMPLETED' +# lab_order.completed_datetime = timezone.now() +# lab_order.save() +# +# # Mark process as completed +# process.results_reported = True +# process.save() +# +# # Send completion notifications +# self.notify_order_completion(lab_order) +# +# def end_lab_order(self, activation): +# """End the lab order workflow""" +# process = activation.process +# +# # Generate order summary report +# self.generate_order_summary(process.lab_order) +# +# # Helper methods +# def notify_lab_staff(self, lab_order): +# """Notify laboratory staff of new order""" +# from django.contrib.auth.models import Group +# +# lab_staff = User.objects.filter( +# groups__name='Laboratory Staff' +# ) +# +# for staff in lab_staff: +# send_mail( +# subject=f'New Lab Order: {lab_order.order_number}', +# message=f'New {lab_order.get_priority_display()} lab order for {lab_order.patient.get_full_name()}.', +# from_email='laboratory@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_collection_staff(self, lab_order): +# """Notify specimen collection staff""" +# collection_staff = User.objects.filter( +# groups__name='Specimen Collection' +# ) +# +# for staff in collection_staff: +# send_mail( +# subject=f'Specimen Collection Required: {lab_order.order_number}', +# message=f'Specimen collection scheduled for {lab_order.collection_datetime}.', +# from_email='laboratory@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_transport_team(self, lab_order, urgent=False): +# """Notify transport team for specimen pickup""" +# transport_staff = User.objects.filter( +# groups__name='Transport Team' +# ) +# +# priority_text = "URGENT" if urgent else "ROUTINE" +# +# for staff in transport_staff: +# send_mail( +# subject=f'{priority_text} Transport: {lab_order.order_number}', +# message=f'Specimen transport required for lab order {lab_order.order_number}.', +# from_email='transport@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def schedule_regular_transport(self, lab_order): +# """Schedule regular transport pickup""" +# # This would integrate with transport scheduling system +# pass +# +# def notify_specimen_rejection(self, specimen): +# """Notify ordering physician of specimen rejection""" +# if specimen.order.ordering_physician and specimen.order.ordering_physician.email: +# send_mail( +# subject=f'Specimen Rejected: {specimen.specimen_number}', +# message=f'Specimen rejected due to: {specimen.rejection_reason}. Please reorder.', +# from_email='laboratory@hospital.com', +# recipient_list=[specimen.order.ordering_physician.email], +# fail_silently=True +# ) +# +# def request_recollection(self, specimen): +# """Request new specimen collection""" +# # This would trigger a new collection workflow +# pass +# +# def is_critical_value(self, result): +# """Check if result value is critical""" +# # This would implement critical value checking logic +# # based on test-specific critical ranges +# return False # Placeholder +# +# def notify_critical_values(self, lab_order, critical_results): +# """Notify physicians of critical values immediately""" +# if lab_order.ordering_physician and lab_order.ordering_physician.email: +# result_details = "\n".join([ +# f"{result.test.test_name}: {result.result_value} {result.result_unit}" +# for result in critical_results +# ]) +# +# send_mail( +# subject=f'CRITICAL VALUES: {lab_order.order_number}', +# message=f'Critical values detected:\n{result_details}', +# from_email='laboratory@hospital.com', +# recipient_list=[lab_order.ordering_physician.email], +# fail_silently=True +# ) +# +# def notify_order_completion(self, lab_order): +# """Notify ordering physician of completed results""" +# if lab_order.ordering_physician and lab_order.ordering_physician.email: +# send_mail( +# subject=f'Lab Results Available: {lab_order.order_number}', +# message=f'Laboratory results are now available for {lab_order.patient.get_full_name()}.', +# from_email='laboratory@hospital.com', +# recipient_list=[lab_order.ordering_physician.email], +# fail_silently=True +# ) +# +# def generate_order_summary(self, lab_order): +# """Generate lab order summary report""" +# # This would generate a comprehensive lab order report +# pass +# +# +# class QualityControlProcess(Process): +# """ +# Viewflow process model for quality control procedures +# """ +# qc_batch = CharField(max_length=50, help_text='QC batch identifier') +# +# # Process status tracking +# qc_samples_prepared = models.BooleanField(default=False) +# qc_tests_run = models.BooleanField(default=False) +# qc_results_reviewed = models.BooleanField(default=False) +# qc_approved = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Quality Control Process' +# verbose_name_plural = 'Quality Control Processes' +# +# +# class QualityControlFlow(Flow): +# """ +# Laboratory Quality Control Workflow +# +# This flow manages quality control procedures for laboratory testing. +# """ +# +# process_class = QualityControlProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_qc_process) +# .Next(this.prepare_qc_samples) +# ) +# +# prepare_qc_samples = ( +# flow_view(QCSamplePreparationView) +# .Permission('laboratory.can_prepare_qc_samples') +# .Next(this.run_qc_tests) +# ) +# +# run_qc_tests = ( +# flow_view(QCTestExecutionView) +# .Permission('laboratory.can_run_qc_tests') +# .Next(this.review_qc_results) +# ) +# +# review_qc_results = ( +# flow_view(QCResultReviewView) +# .Permission('laboratory.can_review_qc_results') +# .Next(this.approve_qc) +# ) +# +# approve_qc = ( +# flow_view(QCApprovalView) +# .Permission('laboratory.can_approve_qc') +# .Next(this.finalize_qc) +# ) +# +# finalize_qc = ( +# flow_func(this.complete_qc_process) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_qc_process) +# +# # Flow functions +# def start_qc_process(self, activation): +# """Initialize the QC process""" +# process = activation.process +# +# # Notify QC staff +# self.notify_qc_staff(process.qc_batch) +# +# def complete_qc_process(self, activation): +# """Finalize the QC process""" +# process = activation.process +# +# # Mark QC as approved +# process.qc_approved = True +# process.save() +# +# # Release patient results if QC passed +# self.release_patient_results(process.qc_batch) +# +# def end_qc_process(self, activation): +# """End the QC workflow""" +# process = activation.process +# +# # Generate QC summary report +# self.generate_qc_summary(process.qc_batch) +# +# # Helper methods +# def notify_qc_staff(self, qc_batch): +# """Notify QC staff of new QC batch""" +# qc_staff = User.objects.filter( +# groups__name='Quality Control' +# ) +# +# for staff in qc_staff: +# send_mail( +# subject=f'QC Batch Ready: {qc_batch}', +# message=f'Quality control batch {qc_batch} is ready for processing.', +# from_email='laboratory@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def release_patient_results(self, qc_batch): +# """Release patient results after QC approval""" +# # This would release held patient results +# pass +# +# def generate_qc_summary(self, qc_batch): +# """Generate QC summary report""" +# # This would generate a comprehensive QC report +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_schedule_collection(order_id): +# """Background task to automatically schedule specimen collection""" +# try: +# lab_order = LabOrder.objects.get(id=order_id) +# +# # Auto-assign collection staff based on location and availability +# collection_staff = User.objects.filter( +# groups__name='Specimen Collection', +# is_active=True +# ).first() +# +# if collection_staff: +# # Create collection task +# # This would integrate with task management system +# return True +# +# return False +# except LabOrder.DoesNotExist: +# return False +# +# +# @celery.job +# def process_batch_results(batch_id): +# """Background task to process batch of test results""" +# try: +# # This would process a batch of results +# # and perform automated quality checks +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_daily_qc_report(): +# """Background task to generate daily QC report""" +# try: +# # This would generate daily QC summary +# return True +# except Exception: +# return False +# diff --git a/logs/hospital_management.log b/logs/hospital_management.log index a86f851d..30ff10a4 100644 --- a/logs/hospital_management.log +++ b/logs/hospital_management.log @@ -182694,3 +182694,6911 @@ INFO 2025-09-06 19:06:33,154 basehttp 33886 6203437056 "GET /en/blood-bank/donor WARNING 2025-09-06 19:06:33,179 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json WARNING 2025-09-06 19:06:33,181 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 INFO 2025-09-06 19:06:33,226 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:07:33,242 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:08:33,254 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:09:33,261 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:09:59,880 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-06 19:09:59,887 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:09:59,888 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:09:59,899 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:09:59,899 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:10:01,883 basehttp 33886 6203437056 "GET /en/blood-bank/donors/34/eligibility/ HTTP/1.1" 200 34004 +WARNING 2025-09-06 19:10:01,906 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:10:01,907 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:10:01,947 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:10:12,338 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:10:12,338 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:10:12,351 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:10:12,353 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:10:18,495 basehttp 33886 6203437056 "GET /en/blood-bank/donors/create/ HTTP/1.1" 200 33924 +WARNING 2025-09-06 19:10:18,514 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:10:18,514 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:10:18,564 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:11:18,590 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:11:31,467 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:11:31,480 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:11:31,480 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:11:31,503 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:11:31,503 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:11:41,047 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:11:41,048 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:11:45,501 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95494 +WARNING 2025-09-06 19:11:45,523 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:11:45,523 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:11:45,576 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:11:56,062 basehttp 33886 6203437056 "GET /en/blood-bank/requests/21/ HTTP/1.1" 200 32303 +WARNING 2025-09-06 19:11:56,083 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:11:56,083 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:11:56,125 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:11:59,419 basehttp 33886 6203437056 "GET /en/blood-bank/requests/21/issue/ HTTP/1.1" 200 44297 +WARNING 2025-09-06 19:11:59,445 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:11:59,446 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:11:59,488 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:12:59,502 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:13:11,618 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-06 19:13:11,618 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:13:11,619 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:13:11,629 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:13:11,629 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:13:26,553 basehttp 33886 6220263424 "GET /blood-bank/api/blood-availability/?blood_group=2&component=1 HTTP/1.1" 302 0 +INFO 2025-09-06 19:13:26,565 basehttp 33886 6203437056 "GET /en/blood-bank/api/blood-availability/?blood_group=2&component=1 HTTP/1.1" 200 22 +INFO 2025-09-06 19:13:36,486 basehttp 33886 6203437056 "GET /en/blood-bank/requests/21/issue/ HTTP/1.1" 200 44297 +WARNING 2025-09-06 19:13:36,502 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:13:36,502 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:13:36,548 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:13:38,899 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:13:38,899 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:13:38,909 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:13:38,909 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:14:11,624 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:15:11,630 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:15:38,062 basehttp 33886 6203437056 "GET /blood-bank/api/blood-availability/?blood_group=2&component=1 HTTP/1.1" 302 0 +INFO 2025-09-06 19:15:38,074 basehttp 33886 6203437056 "GET /en/blood-bank/api/blood-availability/?blood_group=2&component=1 HTTP/1.1" 200 22 +INFO 2025-09-06 19:15:41,784 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:15:41,786 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:15:41,786 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:15:41,807 basehttp 33886 6220263424 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95494 +WARNING 2025-09-06 19:15:41,820 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:15:41,820 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:15:41,825 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:15:41,825 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:15:41,853 basehttp 33886 6220263424 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:16:41,864 basehttp 33886 6220263424 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:16:41,956 basehttp 33886 6220263424 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95494 +WARNING 2025-09-06 19:16:41,971 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:16:41,971 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:16:42,040 basehttp 33886 6220263424 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:16:57,789 basehttp 33886 6220263424 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95494 +INFO 2025-09-06 19:16:57,799 basehttp 33886 6203437056 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-06 19:16:57,801 basehttp 33886 6270742528 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-06 19:16:57,801 basehttp 33886 6287568896 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +WARNING 2025-09-06 19:16:57,807 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:16:57,807 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:16:57,809 basehttp 33886 6220263424 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-06 19:16:57,810 basehttp 33886 6270742528 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-06 19:16:57,810 basehttp 33886 6203437056 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-06 19:16:57,813 basehttp 33886 6203437056 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-06 19:16:57,815 basehttp 33886 6220263424 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-06 19:16:57,815 basehttp 33886 6203437056 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-06 19:16:57,818 basehttp 33886 6237089792 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-06 19:16:57,818 basehttp 33886 6270742528 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-06 19:16:57,820 basehttp 33886 6287568896 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-06 19:16:57,820 basehttp 33886 6253916160 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-06 19:16:58,663 basehttp 33886 6287568896 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-06 19:16:58,772 basehttp 33886 6287568896 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-06 19:16:58,772 basehttp 33886 6270742528 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-06 19:16:58,773 basehttp 33886 6253916160 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-06 19:16:58,773 basehttp 33886 6203437056 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-06 19:16:58,773 basehttp 33886 6237089792 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-06 19:16:58,774 basehttp 33886 6220263424 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-06 19:16:58,779 basehttp 33886 6237089792 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-06 19:16:58,780 basehttp 33886 6270742528 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-06 19:16:58,781 basehttp 33886 6287568896 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-06 19:16:58,781 basehttp 33886 6220263424 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-06 19:16:58,781 basehttp 33886 6203437056 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-06 19:16:58,783 basehttp 33886 6203437056 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-06 19:16:58,784 basehttp 33886 6270742528 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-06 19:16:58,784 basehttp 33886 6220263424 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-06 19:16:58,785 basehttp 33886 6253916160 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-06 19:16:58,785 basehttp 33886 6287568896 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-06 19:16:58,786 basehttp 33886 6237089792 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-06 19:16:58,788 basehttp 33886 6237089792 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-06 19:16:58,789 basehttp 33886 6270742528 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-06 19:16:58,789 basehttp 33886 6220263424 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-06 19:16:58,789 basehttp 33886 6253916160 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-06 19:16:58,790 basehttp 33886 6287568896 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-06 19:16:58,791 basehttp 33886 6237089792 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-06 19:16:58,793 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:16:59,723 log 33886 6203437056 Not Found: /favicon.ico +WARNING 2025-09-06 19:16:59,724 basehttp 33886 6203437056 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-06 19:17:37,138 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95494 +WARNING 2025-09-06 19:17:37,154 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:17:37,154 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:17:37,243 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:18:37,263 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:18:37,321 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:18:37,335 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:18:37,335 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:18:37,388 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:19:37,405 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:19:37,469 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:19:37,484 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:19:37,484 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:19:37,539 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:20:33,296 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:20:33,311 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:20:33,311 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:20:33,370 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:21:33,375 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:21:33,443 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:21:33,455 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:21:33,455 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:21:33,507 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:21:39,147 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:21:39,161 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:21:39,162 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:21:39,213 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:22:39,221 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:22:39,288 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:22:39,308 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:22:39,308 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:22:39,362 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:23:39,371 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:23:39,446 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:23:39,464 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:23:39,464 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:23:39,517 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:24:39,535 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:24:39,590 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:24:39,608 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:24:39,608 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:24:39,669 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:25:16,406 basehttp 33886 6203437056 "GET /en/blood-bank/requests/31/issue/ HTTP/1.1" 200 44569 +INFO 2025-09-06 19:25:16,420 basehttp 33886 6220263424 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +INFO 2025-09-06 19:25:16,422 basehttp 33886 6220263424 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +WARNING 2025-09-06 19:25:16,424 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:25:16,424 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:25:16,476 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:25:29,649 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:25:29,650 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:25:29,676 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:25:29,676 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:25:39,675 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:25:39,747 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:25:39,767 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:25:39,767 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:25:39,816 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:26:39,831 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:26:39,887 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:26:39,901 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:26:39,901 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:26:39,973 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:27:04,018 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:27:04,039 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:27:04,039 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:27:04,088 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:27:20,045 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:27:20,067 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:27:20,067 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:27:20,120 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:27:45,754 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:27:45,772 log 33886 6203437056 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:27:45,772 basehttp 33886 6203437056 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:27:45,827 basehttp 33886 6203437056 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:27:53,028 basehttp 33886 6203437056 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +INFO 2025-09-06 19:27:53,037 basehttp 33886 6203437056 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-06 19:27:53,042 basehttp 33886 6237089792 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-06 19:27:53,043 basehttp 33886 6270742528 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-06 19:27:53,044 basehttp 33886 6287568896 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-06 19:27:53,044 basehttp 33886 6203437056 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-06 19:27:53,045 basehttp 33886 6237089792 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-06 19:27:53,047 basehttp 33886 6237089792 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +WARNING 2025-09-06 19:27:53,052 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:27:53,053 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:27:53,054 basehttp 33886 6203437056 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-06 19:27:53,055 basehttp 33886 6237089792 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-06 19:27:53,056 basehttp 33886 6287568896 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-06 19:27:53,057 basehttp 33886 6253916160 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-06 19:27:53,059 basehttp 33886 6220263424 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-06 19:27:53,059 basehttp 33886 6270742528 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-06 19:27:53,900 basehttp 33886 6270742528 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-06 19:27:53,925 basehttp 33886 6253916160 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-06 19:27:53,926 basehttp 33886 6220263424 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-06 19:27:53,926 basehttp 33886 6237089792 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-06 19:27:53,927 basehttp 33886 6270742528 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-06 19:27:53,928 basehttp 33886 6287568896 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-06 19:27:53,929 basehttp 33886 6237089792 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-06 19:27:53,930 basehttp 33886 6203437056 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-06 19:27:53,930 basehttp 33886 6220263424 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-06 19:27:53,932 basehttp 33886 6237089792 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-06 19:27:53,932 basehttp 33886 6287568896 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-06 19:27:53,932 basehttp 33886 6203437056 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-06 19:27:53,933 basehttp 33886 6270742528 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-06 19:27:53,934 basehttp 33886 6220263424 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-06 19:27:53,936 basehttp 33886 6203437056 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-06 19:27:53,936 basehttp 33886 6287568896 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-06 19:27:53,937 basehttp 33886 6270742528 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-06 19:27:53,937 basehttp 33886 6253916160 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-06 19:27:53,938 basehttp 33886 6237089792 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-06 19:27:53,938 basehttp 33886 6220263424 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-06 19:27:53,945 basehttp 33886 6270742528 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-06 19:27:53,956 basehttp 33886 6287568896 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-06 19:27:53,956 basehttp 33886 6203437056 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-06 19:27:53,957 basehttp 33886 6253916160 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-06 19:27:53,962 basehttp 33886 6220263424 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:27:54,851 log 33886 6220263424 Not Found: /favicon.ico +WARNING 2025-09-06 19:27:54,851 basehttp 33886 6220263424 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-06 19:28:36,420 basehttp 33886 6220263424 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:28:36,438 log 33886 6220263424 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:36,438 basehttp 33886 6220263424 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:36,519 basehttp 33886 6220263424 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:28:41,333 basehttp 33886 6220263424 "GET /en/blood-bank/requests/ HTTP/1.1" 200 95604 +INFO 2025-09-06 19:28:41,340 basehttp 33886 6220263424 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-06 19:28:41,346 basehttp 33886 6270742528 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-06 19:28:41,347 basehttp 33886 6203437056 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-06 19:28:41,347 basehttp 33886 6220263424 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-06 19:28:41,350 basehttp 33886 6237089792 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-06 19:28:41,350 basehttp 33886 6203437056 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-06 19:28:41,355 basehttp 33886 6203437056 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-06 19:28:41,357 basehttp 33886 6220263424 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-06 19:28:41,358 basehttp 33886 6203437056 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +WARNING 2025-09-06 19:28:41,359 log 33886 6287568896 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:41,359 basehttp 33886 6287568896 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:41,360 basehttp 33886 6220263424 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-06 19:28:41,360 basehttp 33886 6237089792 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-06 19:28:41,363 basehttp 33886 6253916160 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-06 19:28:41,363 basehttp 33886 6270742528 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-06 19:28:41,553 basehttp 33886 6270742528 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-06 19:28:41,578 basehttp 33886 6253916160 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-06 19:28:41,579 basehttp 33886 6237089792 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-06 19:28:41,579 basehttp 33886 6270742528 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-06 19:28:41,579 basehttp 33886 6220263424 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-06 19:28:41,579 basehttp 33886 6287568896 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-06 19:28:41,580 basehttp 33886 6203437056 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-06 19:28:41,583 basehttp 33886 6220263424 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-06 19:28:41,584 basehttp 33886 6270742528 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-06 19:28:41,584 basehttp 33886 6237089792 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-06 19:28:41,585 basehttp 33886 6253916160 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-06 19:28:41,586 basehttp 33886 6203437056 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-06 19:28:41,588 basehttp 33886 6270742528 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-06 19:28:41,597 basehttp 33886 6270742528 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-06 19:28:41,598 basehttp 33886 6237089792 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-06 19:28:41,592 basehttp 33886 6253916160 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-06 19:28:41,595 basehttp 33886 6220263424 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-06 19:28:41,604 basehttp 33886 6287568896 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-06 19:28:41,596 basehttp 33886 6203437056 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-06 19:28:41,608 basehttp 33886 6287568896 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-06 19:28:41,608 basehttp 33886 6220263424 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-06 19:28:41,608 basehttp 33886 6270742528 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-06 19:28:41,609 basehttp 33886 6237089792 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-06 19:28:41,609 basehttp 33886 6203437056 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-06 19:28:41,612 basehttp 33886 6253916160 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:28:41,707 log 33886 6253916160 Not Found: /favicon.ico +WARNING 2025-09-06 19:28:41,707 basehttp 33886 6253916160 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-06 19:28:43,985 basehttp 33886 6253916160 "GET /en/blood-bank/requests/39/ HTTP/1.1" 200 32942 +WARNING 2025-09-06 19:28:44,003 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:44,004 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:44,073 basehttp 33886 6253916160 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:28:46,841 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:46,842 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:28:46,858 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:46,859 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:48,647 basehttp 33886 6253916160 "GET /en/blood-bank/requests/39/ HTTP/1.1" 200 32942 +WARNING 2025-09-06 19:28:48,669 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:48,669 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:48,709 basehttp 33886 6253916160 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:28:50,535 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:50,535 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:28:50,547 log 33886 6253916160 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:50,547 basehttp 33886 6253916160 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:52,138 basehttp 33886 6253916160 "GET /en/blood-bank/requests/38/issue/ HTTP/1.1" 200 44569 +INFO 2025-09-06 19:28:52,150 basehttp 33886 6253916160 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +INFO 2025-09-06 19:28:52,150 basehttp 33886 6203437056 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +WARNING 2025-09-06 19:28:52,155 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:52,155 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:52,206 basehttp 33886 6237089792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:28:54,000 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:54,000 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:28:54,010 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:54,010 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:56,856 basehttp 33886 6237089792 "GET /en/blood-bank/requests/37/issue/ HTTP/1.1" 200 44297 +WARNING 2025-09-06 19:28:56,876 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:28:56,877 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:28:56,923 basehttp 33886 6237089792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:29:04,827 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:29:04,828 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 19:29:04,841 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:29:04,841 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:29:09,836 basehttp 33886 6237089792 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 70207 +WARNING 2025-09-06 19:29:09,853 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:29:09,853 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:29:09,881 basehttp 33886 6237089792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:29:12,237 basehttp 33886 6237089792 "GET /en/blood-bank/requests/?page=1 HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:29:12,259 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:29:12,259 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:29:12,305 basehttp 33886 6237089792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:30:12,315 basehttp 33886 6237089792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:30:12,389 basehttp 33886 6237089792 "GET /en/blood-bank/requests/?page=1 HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:30:12,402 log 33886 6237089792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:30:12,402 basehttp 33886 6237089792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:30:12,449 basehttp 33886 6237089792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:31:05,224 autoreload 33886 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/views.py changed, reloading. +INFO 2025-09-06 19:31:05,721 autoreload 58836 8747049152 Watching for file changes with StatReloader +INFO 2025-09-06 19:31:12,538 basehttp 58836 6157119488 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:31:12,555 basehttp 58836 6173945856 "GET /en/blood-bank/requests/?page=1 HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:31:12,568 log 58836 6173945856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:31:12,568 basehttp 58836 6173945856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:31:12,623 basehttp 58836 6173945856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:32:12,642 basehttp 58836 6173945856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:32:12,696 basehttp 58836 6173945856 "GET /en/blood-bank/requests/?page=1 HTTP/1.1" 200 95604 +WARNING 2025-09-06 19:32:12,710 log 58836 6173945856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:32:12,710 basehttp 58836 6173945856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:32:12,762 basehttp 58836 6173945856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:32:49,006 autoreload 58836 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/views.py changed, reloading. +INFO 2025-09-06 19:32:49,342 autoreload 59644 8747049152 Watching for file changes with StatReloader +INFO 2025-09-06 19:33:26,538 autoreload 59644 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/views.py changed, reloading. +INFO 2025-09-06 19:33:26,855 autoreload 59959 8747049152 Watching for file changes with StatReloader +INFO 2025-09-06 19:34:36,707 autoreload 59959 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/views.py changed, reloading. +INFO 2025-09-06 19:34:37,017 autoreload 60430 8747049152 Watching for file changes with StatReloader +INFO 2025-09-06 19:37:51,202 autoreload 60430 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/views.py changed, reloading. +INFO 2025-09-06 19:37:51,504 autoreload 61907 8747049152 Watching for file changes with StatReloader +INFO 2025-09-06 19:40:12,981 autoreload 61907 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/urls.py changed, reloading. +INFO 2025-09-06 19:40:13,258 autoreload 62923 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-06 19:40:24,226 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:40:24,226 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:40:24,350 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:40:25,120 basehttp 62923 6159593472 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69125 +WARNING 2025-09-06 19:40:25,140 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:40:25,140 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:40:25,221 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:41:10,879 basehttp 62923 6159593472 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69125 +WARNING 2025-09-06 19:41:10,895 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:41:10,895 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:41:10,947 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:41:41,734 basehttp 62923 6159593472 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69125 +INFO 2025-09-06 19:41:41,749 basehttp 62923 6226898944 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-06 19:41:41,750 basehttp 62923 6193246208 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-06 19:41:41,752 basehttp 62923 6210072576 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-06 19:41:41,753 basehttp 62923 6193246208 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-06 19:41:41,756 basehttp 62923 6243725312 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-06 19:41:41,758 basehttp 62923 6159593472 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +WARNING 2025-09-06 19:41:41,760 log 62923 6226898944 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:41:41,761 basehttp 62923 6226898944 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:41:41,761 basehttp 62923 6159593472 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-06 19:41:41,765 basehttp 62923 6159593472 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-06 19:41:41,766 basehttp 62923 6226898944 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-06 19:41:41,775 basehttp 62923 6193246208 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-06 19:41:41,786 basehttp 62923 6243725312 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-06 19:41:41,787 basehttp 62923 6176419840 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-06 19:41:41,788 basehttp 62923 6210072576 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-06 19:41:42,607 basehttp 62923 6210072576 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-06 19:41:42,627 basehttp 62923 6210072576 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-06 19:41:42,629 basehttp 62923 6193246208 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-06 19:41:42,629 basehttp 62923 6176419840 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-06 19:41:42,629 basehttp 62923 6243725312 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-06 19:41:42,629 basehttp 62923 6226898944 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-06 19:41:42,637 basehttp 62923 6193246208 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-06 19:41:42,653 basehttp 62923 6226898944 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-06 19:41:42,654 basehttp 62923 6243725312 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-06 19:41:42,654 basehttp 62923 6159593472 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-06 19:41:42,655 basehttp 62923 6193246208 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-06 19:41:42,655 basehttp 62923 6176419840 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-06 19:41:42,656 basehttp 62923 6159593472 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-06 19:41:42,658 basehttp 62923 6226898944 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-06 19:41:42,658 basehttp 62923 6176419840 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-06 19:41:42,658 basehttp 62923 6243725312 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-06 19:41:42,658 basehttp 62923 6193246208 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-06 19:41:42,660 basehttp 62923 6159593472 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-06 19:41:42,660 basehttp 62923 6210072576 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-06 19:41:42,662 basehttp 62923 6226898944 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-06 19:41:42,663 basehttp 62923 6176419840 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-06 19:41:42,664 basehttp 62923 6243725312 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-06 19:41:42,665 basehttp 62923 6193246208 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-06 19:41:42,665 basehttp 62923 6159593472 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-06 19:41:42,684 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:41:43,610 log 62923 6159593472 Not Found: /favicon.ico +WARNING 2025-09-06 19:41:43,610 basehttp 62923 6159593472 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-06 19:42:07,122 basehttp 62923 6159593472 "GET /en/blood-bank/requests/15/issue/ HTTP/1.1" 200 44297 +INFO 2025-09-06 19:42:07,134 basehttp 62923 6159593472 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +INFO 2025-09-06 19:42:07,134 basehttp 62923 6193246208 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +WARNING 2025-09-06 19:42:07,138 log 62923 6243725312 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:42:07,138 basehttp 62923 6243725312 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:42:07,204 basehttp 62923 6243725312 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:43:02,125 basehttp 62923 6243725312 "GET /en/blood-bank/requests/15/issue/ HTTP/1.1" 200 44298 +WARNING 2025-09-06 19:43:02,152 log 62923 6243725312 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:43:02,152 basehttp 62923 6243725312 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:43:02,191 basehttp 62923 6243725312 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:43:14,691 basehttp 62923 6243725312 "GET /en/blood-bank/requests/15/issue/ HTTP/1.1" 200 44298 +INFO 2025-09-06 19:43:14,701 basehttp 62923 6159593472 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-06 19:43:14,702 basehttp 62923 6210072576 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-06 19:43:14,703 basehttp 62923 6176419840 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +INFO 2025-09-06 19:43:14,708 basehttp 62923 6226898944 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-06 19:43:14,710 basehttp 62923 6243725312 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-06 19:43:14,711 basehttp 62923 6176419840 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +WARNING 2025-09-06 19:43:14,715 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:43:14,715 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:43:14,715 basehttp 62923 6226898944 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +INFO 2025-09-06 19:43:14,718 basehttp 62923 6193246208 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-06 19:43:14,719 basehttp 62923 6210072576 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-06 19:43:14,856 basehttp 62923 6210072576 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-06 19:43:14,878 basehttp 62923 6210072576 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-06 19:43:14,879 basehttp 62923 6176419840 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-06 19:43:14,879 basehttp 62923 6193246208 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-06 19:43:14,880 basehttp 62923 6159593472 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-06 19:43:14,880 basehttp 62923 6226898944 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-06 19:43:14,882 basehttp 62923 6226898944 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-06 19:43:14,882 basehttp 62923 6243725312 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-06 19:43:14,882 basehttp 62923 6176419840 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-06 19:43:14,883 basehttp 62923 6159593472 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-06 19:43:14,883 basehttp 62923 6193246208 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-06 19:43:14,886 basehttp 62923 6243725312 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-06 19:43:14,886 basehttp 62923 6176419840 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-06 19:43:14,886 basehttp 62923 6193246208 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-06 19:43:14,887 basehttp 62923 6226898944 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-06 19:43:14,887 basehttp 62923 6210072576 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-06 19:43:14,887 basehttp 62923 6159593472 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-06 19:43:14,888 basehttp 62923 6226898944 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-06 19:43:14,889 basehttp 62923 6159593472 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-06 19:43:14,889 basehttp 62923 6210072576 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-06 19:43:14,890 basehttp 62923 6226898944 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-06 19:43:14,891 basehttp 62923 6176419840 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-06 19:43:14,891 basehttp 62923 6210072576 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-06 19:43:14,892 basehttp 62923 6193246208 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-06 19:43:14,894 basehttp 62923 6243725312 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 19:43:14,998 log 62923 6243725312 Not Found: /favicon.ico +WARNING 2025-09-06 19:43:14,998 basehttp 62923 6243725312 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-06 19:43:26,976 basehttp 62923 6243725312 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69125 +INFO 2025-09-06 19:43:26,992 basehttp 62923 6193246208 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-06 19:43:26,992 basehttp 62923 6226898944 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-06 19:43:26,993 basehttp 62923 6243725312 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-06 19:43:26,993 basehttp 62923 6176419840 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +WARNING 2025-09-06 19:43:26,998 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:43:26,998 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:43:26,998 basehttp 62923 6176419840 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-06 19:43:26,998 basehttp 62923 6243725312 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-06 19:44:27,096 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:44:27,147 basehttp 62923 6176419840 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69125 +WARNING 2025-09-06 19:44:27,161 log 62923 6176419840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:44:27,162 basehttp 62923 6176419840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:44:27,214 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:45:27,226 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:45:27,281 basehttp 62923 6176419840 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69125 +WARNING 2025-09-06 19:45:27,296 log 62923 6176419840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:45:27,296 basehttp 62923 6176419840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:45:27,348 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:46:13,992 basehttp 62923 6176419840 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69127 +WARNING 2025-09-06 19:46:14,008 log 62923 6176419840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:46:14,008 basehttp 62923 6176419840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:46:14,061 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:47:04,387 basehttp 62923 6176419840 "GET /en/admin/blood_bank/bloodrequest/ HTTP/1.1" 200 113405 +INFO 2025-09-06 19:47:04,399 basehttp 62923 6226898944 "GET /static/admin/css/nav_sidebar.css HTTP/1.1" 200 2810 +INFO 2025-09-06 19:47:04,399 basehttp 62923 6243725312 "GET /static/admin/css/dark_mode.css HTTP/1.1" 200 2808 +INFO 2025-09-06 19:47:04,399 basehttp 62923 6193246208 "GET /static/admin/css/changelists.css HTTP/1.1" 200 6878 +INFO 2025-09-06 19:47:04,399 basehttp 62923 6176419840 "GET /static/admin/css/base.css HTTP/1.1" 200 22120 +INFO 2025-09-06 19:47:04,399 basehttp 62923 6210072576 "GET /static/admin/js/theme.js HTTP/1.1" 200 1653 +INFO 2025-09-06 19:47:04,401 basehttp 62923 6243725312 "GET /static/admin/css/responsive.css HTTP/1.1" 200 16565 +INFO 2025-09-06 19:47:04,402 basehttp 62923 6210072576 "GET /static/admin/js/jquery.init.js HTTP/1.1" 200 347 +INFO 2025-09-06 19:47:04,402 basehttp 62923 6193246208 "GET /static/admin/js/admin/RelatedObjectLookups.js HTTP/1.1" 200 9777 +INFO 2025-09-06 19:47:04,403 basehttp 62923 6176419840 "GET /static/admin/js/core.js HTTP/1.1" 200 6208 +INFO 2025-09-06 19:47:04,405 basehttp 62923 6243725312 "GET /static/admin/js/actions.js HTTP/1.1" 200 8076 +INFO 2025-09-06 19:47:04,405 basehttp 62923 6193246208 "GET /static/admin/js/prepopulate.js HTTP/1.1" 200 1531 +INFO 2025-09-06 19:47:04,406 basehttp 62923 6210072576 "GET /static/admin/js/urlify.js HTTP/1.1" 200 7887 +INFO 2025-09-06 19:47:04,407 basehttp 62923 6159593472 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-06 19:47:04,407 basehttp 62923 6193246208 "GET /static/admin/img/search.svg HTTP/1.1" 200 458 +INFO 2025-09-06 19:47:04,408 basehttp 62923 6226898944 "GET /static/admin/js/vendor/jquery/jquery.js HTTP/1.1" 200 285314 +INFO 2025-09-06 19:47:04,409 basehttp 62923 6176419840 "GET /static/admin/js/vendor/xregexp/xregexp.js HTTP/1.1" 200 325171 +INFO 2025-09-06 19:47:04,412 basehttp 62923 6226898944 "GET /static/admin/js/nav_sidebar.js HTTP/1.1" 200 3063 +INFO 2025-09-06 19:47:04,414 basehttp 62923 6176419840 "GET /static/admin/js/filters.js HTTP/1.1" 200 978 +INFO 2025-09-06 19:47:04,422 basehttp 62923 6176419840 "GET /static/admin/img/icon-addlink.svg HTTP/1.1" 200 331 +INFO 2025-09-06 19:47:04,422 basehttp 62923 6176419840 "GET /static/admin/img/sorting-icons.svg HTTP/1.1" 200 1097 +INFO 2025-09-06 19:47:04,422 basehttp 62923 6226898944 "GET /static/admin/img/tooltag-add.svg HTTP/1.1" 200 331 +INFO 2025-09-06 19:47:04,423 basehttp 62923 6193246208 "GET /static/admin/img/icon-viewlink.svg HTTP/1.1" 200 581 +INFO 2025-09-06 19:47:06,558 basehttp 62923 6193246208 "GET /en/admin/blood_bank/bloodrequest/40/change/ HTTP/1.1" 200 128128 +INFO 2025-09-06 19:47:06,577 basehttp 62923 6193246208 "GET /static/admin/css/forms.css HTTP/1.1" 200 8525 +INFO 2025-09-06 19:47:06,577 basehttp 62923 6243725312 "GET /static/admin/js/prepopulate_init.js HTTP/1.1" 200 586 +INFO 2025-09-06 19:47:06,578 basehttp 62923 6176419840 "GET /static/admin/js/calendar.js HTTP/1.1" 200 9141 +INFO 2025-09-06 19:47:06,578 basehttp 62923 6210072576 "GET /static/admin/js/inlines.js HTTP/1.1" 200 15628 +INFO 2025-09-06 19:47:06,578 basehttp 62923 6159593472 "GET /static/admin/js/admin/DateTimeShortcuts.js HTTP/1.1" 200 19319 +INFO 2025-09-06 19:47:06,578 basehttp 62923 6210072576 "GET /static/admin/css/widgets.css HTTP/1.1" 200 11991 +INFO 2025-09-06 19:47:06,580 basehttp 62923 6210072576 "GET /static/admin/img/icon-changelink.svg HTTP/1.1" 200 380 +INFO 2025-09-06 19:47:06,581 basehttp 62923 6210072576 "GET /static/admin/img/icon-deletelink.svg HTTP/1.1" 200 392 +INFO 2025-09-06 19:47:06,582 basehttp 62923 6226898944 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-06 19:47:06,583 basehttp 62923 6210072576 "GET /static/admin/js/change_form.js HTTP/1.1" 200 606 +INFO 2025-09-06 19:47:06,609 basehttp 62923 6226898944 "GET /static/admin/img/icon-clock.svg HTTP/1.1" 200 677 +INFO 2025-09-06 19:47:06,609 basehttp 62923 6210072576 "GET /static/admin/img/icon-calendar.svg HTTP/1.1" 200 1086 +INFO 2025-09-06 19:47:11,976 basehttp 62923 6210072576 "POST /en/admin/blood_bank/bloodrequest/40/change/ HTTP/1.1" 302 0 +INFO 2025-09-06 19:47:12,013 basehttp 62923 6210072576 "GET /en/admin/blood_bank/bloodrequest/ HTTP/1.1" 200 113680 +INFO 2025-09-06 19:47:12,028 basehttp 62923 6210072576 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-06 19:47:12,036 basehttp 62923 6210072576 "GET /static/admin/img/icon-yes.svg HTTP/1.1" 200 436 +INFO 2025-09-06 19:47:14,103 basehttp 62923 6210072576 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:47:14,114 basehttp 62923 6226898944 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69127 +WARNING 2025-09-06 19:47:14,125 log 62923 6226898944 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:47:14,125 basehttp 62923 6226898944 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:47:14,175 basehttp 62923 6226898944 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:48:15,133 basehttp 62923 6226898944 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:48:15,144 basehttp 62923 6210072576 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69127 +WARNING 2025-09-06 19:48:15,156 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:48:15,157 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:48:15,218 basehttp 62923 6210072576 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:48:37,932 basehttp 62923 6210072576 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69123 +WARNING 2025-09-06 19:48:37,948 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:48:37,948 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:48:38,001 basehttp 62923 6210072576 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:49:23,812 basehttp 62923 6210072576 "GET /en/blood-bank/requests/?page=2 HTTP/1.1" 200 69119 +WARNING 2025-09-06 19:49:23,831 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:49:23,831 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:49:23,874 basehttp 62923 6210072576 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:49:37,620 basehttp 62923 6210072576 "GET /en/blood-bank/requests/ HTTP/1.1" 200 94515 +WARNING 2025-09-06 19:49:37,637 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:49:37,637 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:49:38,885 basehttp 62923 6210072576 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +WARNING 2025-09-06 19:49:38,905 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:49:38,905 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:49:45,653 basehttp 62923 6210072576 "GET /en/blood-bank/units/ HTTP/1.1" 200 88820 +WARNING 2025-09-06 19:49:45,673 log 62923 6210072576 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 19:49:45,673 basehttp 62923 6210072576 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 19:49:45,735 basehttp 62923 6210072576 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:50:53,650 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:51:54,644 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:52:55,646 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:54:25,871 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:57:18,309 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 19:58:19,303 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:32:39,307 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:43:02,490 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-06 20:43:02,491 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:43:02,492 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:02,506 basehttp 62923 6176419840 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +WARNING 2025-09-06 20:43:02,517 log 62923 6176419840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:02,518 basehttp 62923 6176419840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 20:43:02,524 log 62923 6176419840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:02,524 basehttp 62923 6176419840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:02,594 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:43:03,304 basehttp 62923 6176419840 "GET /en/inventory/stock/ HTTP/1.1" 200 134411 +INFO 2025-09-06 20:43:03,318 basehttp 62923 6176419840 "GET /static/plugins/dropzone/src/options.js HTTP/1.1" 200 23721 +WARNING 2025-09-06 20:43:03,321 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:03,321 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:04,834 basehttp 62923 6159593472 "GET / HTTP/1.1" 302 0 +INFO 2025-09-06 20:43:04,854 basehttp 62923 6176419840 "GET /en/ HTTP/1.1" 200 49790 +WARNING 2025-09-06 20:43:04,870 log 62923 6176419840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:04,871 basehttp 62923 6176419840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:04,922 basehttp 62923 6176419840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:43:04,932 basehttp 62923 6210072576 "GET /en/htmx/tenant-info/ HTTP/1.1" 200 1043 +INFO 2025-09-06 20:43:04,935 basehttp 62923 6193246208 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +INFO 2025-09-06 20:43:04,948 basehttp 62923 6159593472 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +INFO 2025-09-06 20:43:20,053 basehttp 62923 6159593472 "GET /en/patients/register/ HTTP/1.1" 200 27711 +WARNING 2025-09-06 20:43:20,075 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:20,075 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:20,113 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:43:35,146 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-06 20:43:35,146 basehttp 62923 6159593472 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +WARNING 2025-09-06 20:43:35,146 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 20:43:35,177 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:35,182 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:36,812 basehttp 62923 6159593472 "GET /en/appointments/create/ HTTP/1.1" 200 36462 +WARNING 2025-09-06 20:43:36,833 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:36,833 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:36,869 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:43:44,391 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:44,391 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 20:43:44,403 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:44,404 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:45,956 basehttp 62923 6159593472 "GET /en/ HTTP/1.1" 200 49790 +WARNING 2025-09-06 20:43:45,970 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:45,970 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:46,043 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:43:46,047 basehttp 62923 6210072576 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +INFO 2025-09-06 20:43:46,047 basehttp 62923 6176419840 "GET /en/htmx/tenant-info/ HTTP/1.1" 200 1043 +INFO 2025-09-06 20:43:46,049 basehttp 62923 6193246208 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +INFO 2025-09-06 20:43:51,723 basehttp 62923 6193246208 "GET /en/billing/bills/create/ HTTP/1.1" 200 109266 +WARNING 2025-09-06 20:43:51,746 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:43:51,746 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:43:51,798 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:44:51,815 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:45:51,819 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:46:51,820 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:47:51,813 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:48:12,511 basehttp 62923 6193246208 "GET /en/billing/bills/create/ HTTP/1.1" 200 110464 +WARNING 2025-09-06 20:48:12,528 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:48:12,529 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:48:12,588 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:48:33,842 basehttp 62923 6193246208 "GET /en/billing/bills/create/ HTTP/1.1" 200 110432 +WARNING 2025-09-06 20:48:33,859 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:48:33,859 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:48:33,912 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:49:22,973 basehttp 62923 6193246208 "GET /en/billing/bills/ HTTP/1.1" 200 135104 +WARNING 2025-09-06 20:49:22,996 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:49:22,996 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:49:23,028 basehttp 62923 6193246208 "GET /static/css/saudiriyalsymbol.woff2 HTTP/1.1" 200 720 +INFO 2025-09-06 20:49:23,071 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:49:23,076 basehttp 62923 6159593472 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 20:50:23,072 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:50:23,075 basehttp 62923 6193246208 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 20:51:23,085 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:51:23,088 basehttp 62923 6159593472 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 20:51:33,802 basehttp 62923 6159593472 "GET /en/billing/bills/ HTTP/1.1" 200 101540 +WARNING 2025-09-06 20:51:33,820 log 62923 6159593472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:51:33,820 basehttp 62923 6159593472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:51:33,880 basehttp 62923 6159593472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:51:33,884 basehttp 62923 6193246208 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +ERROR 2025-09-06 20:51:54,500 log 62923 6193246208 Internal Server Error: /en/billing/bills/a668a9c6-ab05-40eb-96f3-5c56e1efc6d9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'encounter_detail' with arguments '(UUID('23e89bd9-30d2-4da2-accd-8579ce105ca3'),)' not found. 1 pattern(s) tried: ['en/emr/encounters/(?P[0-9]+)/\\Z'] +ERROR 2025-09-06 20:51:54,501 basehttp 62923 6193246208 "GET /en/billing/bills/a668a9c6-ab05-40eb-96f3-5c56e1efc6d9/ HTTP/1.1" 500 201537 +WARNING 2025-09-06 20:51:54,519 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:51:54,519 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:52:38,832 basehttp 62923 6193246208 "GET /en/billing/bills/a668a9c6-ab05-40eb-96f3-5c56e1efc6d9/ HTTP/1.1" 200 40744 +WARNING 2025-09-06 20:52:38,849 log 62923 6193246208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:52:38,849 basehttp 62923 6193246208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:52:38,891 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:53:38,899 basehttp 62923 6193246208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:53:44,589 autoreload 62923 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/emr/urls.py changed, reloading. +INFO 2025-09-06 20:53:45,035 autoreload 75155 8747049152 Watching for file changes with StatReloader +INFO 2025-09-06 20:53:45,500 basehttp 75155 6163345408 "GET /en/billing/bills/a668a9c6-ab05-40eb-96f3-5c56e1efc6d9/ HTTP/1.1" 200 40777 +WARNING 2025-09-06 20:53:45,518 log 75155 6163345408 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:45,519 basehttp 75155 6163345408 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:45,565 basehttp 75155 6163345408 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:53:48,154 log 75155 6196998144 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:48,155 basehttp 75155 6196998144 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:48,160 basehttp 75155 6163345408 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:53:48,164 basehttp 75155 6180171776 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +WARNING 2025-09-06 20:53:48,190 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:48,190 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:48,846 basehttp 75155 6180171776 "GET /en/billing/bills/ HTTP/1.1" 200 101540 +WARNING 2025-09-06 20:53:48,861 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:48,861 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:48,924 basehttp 75155 6180171776 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:53:48,927 basehttp 75155 6163345408 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 20:53:50,969 basehttp 75155 6163345408 "GET /en/billing/bills/a668a9c6-ab05-40eb-96f3-5c56e1efc6d9/ HTTP/1.1" 200 40777 +WARNING 2025-09-06 20:53:50,995 log 75155 6163345408 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:50,995 basehttp 75155 6163345408 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:51,034 basehttp 75155 6163345408 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:53:55,492 log 75155 6163345408 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:55,493 basehttp 75155 6163345408 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 20:53:55,504 log 75155 6163345408 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:55,504 basehttp 75155 6163345408 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:59,272 basehttp 75155 6163345408 "GET /en/billing/bills/ HTTP/1.1" 200 101540 +WARNING 2025-09-06 20:53:59,288 log 75155 6163345408 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:53:59,288 basehttp 75155 6163345408 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:53:59,349 basehttp 75155 6163345408 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 20:53:59,351 basehttp 75155 6180171776 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 20:54:03,209 basehttp 75155 6180171776 "GET /en/billing/bills/a668a9c6-ab05-40eb-96f3-5c56e1efc6d9/edit/ HTTP/1.1" 200 110457 +WARNING 2025-09-06 20:54:03,231 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:54:03,231 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:54:03,275 basehttp 75155 6180171776 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 20:54:08,801 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:54:08,801 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 20:54:08,833 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:54:08,833 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 20:54:14,430 log 75155 6180171776 Internal Server Error: /en/billing/bills/49ecf1c4-8024-4107-ad14-0d46cf66fe79/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 243, in render + nodelist.append(node.render_annotated(context)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_print' not found. 'claim_print' is not a valid view function or pattern name. +ERROR 2025-09-06 20:54:14,431 basehttp 75155 6180171776 "GET /en/billing/bills/49ecf1c4-8024-4107-ad14-0d46cf66fe79/ HTTP/1.1" 500 194361 +WARNING 2025-09-06 20:54:14,448 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:54:14,448 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:55:26,412 basehttp 75155 6180171776 "GET /en/billing/bills/49ecf1c4-8024-4107-ad14-0d46cf66fe79/ HTTP/1.1" 200 38565 +WARNING 2025-09-06 20:55:26,428 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:55:26,428 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:55:26,471 basehttp 75155 6180171776 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-06 20:55:32,484 log 75155 6180171776 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 113, in get + context = self.get_context_data(object=self.object) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py", line 396, in get_context_data + context['status_updates'] = claim.claimstatusupdate_set.all().order_by('-update_date') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AttributeError: 'InsuranceClaim' object has no attribute 'claimstatusupdate_set' +ERROR 2025-09-06 20:55:32,488 basehttp 75155 6180171776 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 87057 +WARNING 2025-09-06 20:55:32,505 log 75155 6180171776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:55:32,505 basehttp 75155 6180171776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 20:58:35,611 autoreload 75155 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-06 20:58:36,030 autoreload 77344 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-06 20:58:37,142 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_print' not found. 'claim_print' is not a valid view function or pattern name. +ERROR 2025-09-06 20:58:37,144 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 176843 +WARNING 2025-09-06 20:58:37,155 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:58:37,155 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 20:58:38,805 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_print' not found. 'claim_print' is not a valid view function or pattern name. +ERROR 2025-09-06 20:58:38,806 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 176843 +WARNING 2025-09-06 20:58:38,822 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:58:38,822 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 20:59:09,893 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_download' not found. 'claim_download' is not a valid view function or pattern name. +ERROR 2025-09-06 20:59:09,894 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 176762 +WARNING 2025-09-06 20:59:09,908 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:59:09,908 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 20:59:38,455 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_download' not found. 'claim_download' is not a valid view function or pattern name. +ERROR 2025-09-06 20:59:38,456 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 176671 +WARNING 2025-09-06 20:59:38,469 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:59:38,469 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 20:59:50,130 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_status_check' not found. 'claim_status_check' is not a valid view function or pattern name. +ERROR 2025-09-06 20:59:50,131 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 190725 +WARNING 2025-09-06 20:59:50,143 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 20:59:50,143 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 21:00:01,988 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_status_check' not found. 'claim_status_check' is not a valid view function or pattern name. +ERROR 2025-09-06 21:00:01,989 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 191087 +WARNING 2025-09-06 21:00:02,004 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:00:02,004 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 21:00:16,339 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_print' not found. 'claim_print' is not a valid view function or pattern name. +ERROR 2025-09-06 21:00:16,340 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 176728 +WARNING 2025-09-06 21:00:16,353 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:00:16,353 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 21:00:27,731 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_download' not found. 'claim_download' is not a valid view function or pattern name. +ERROR 2025-09-06 21:00:27,732 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 176265 +WARNING 2025-09-06 21:00:27,745 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:00:27,745 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-06 21:00:39,384 log 77344 6157611008 Internal Server Error: /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1075, in render + output = self.filter_expression.resolve(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 749, in resolve + new_obj = func(obj, *arg_vals) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaultfilters.py", line 784, in date + return formats.date_format(value, arg) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/utils/formats.py", line 155, in date_format + return dateformat.format( + ^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/utils/dateformat.py", line 325, in format + return df.format(format_string) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/utils/dateformat.py", line 45, in format + raise TypeError( +TypeError: The format for date objects may not contain time-related format specifiers (found 'g'). +ERROR 2025-09-06 21:00:39,385 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 500 198633 +WARNING 2025-09-06 21:00:39,399 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:00:39,399 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:01:06,361 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 200 37484 +WARNING 2025-09-06 21:01:06,378 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:01:06,378 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:01:06,451 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:01:27,610 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 21:01:27,612 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:01:27,612 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 21:01:27,627 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:01:27,627 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:01:31,347 basehttp 77344 6174437376 "GET /en/billing/payments/create/?bill=49ecf1c4-8024-4107-ad14-0d46cf66fe79 HTTP/1.1" 200 42101 +WARNING 2025-09-06 21:01:31,368 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:01:31,368 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:01:31,438 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:02:31,455 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:03:31,438 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:04:31,453 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:05:20,613 basehttp 77344 6174437376 "GET /en/billing/payments/create/?bill=49ecf1c4-8024-4107-ad14-0d46cf66fe79 HTTP/1.1" 200 42101 +WARNING 2025-09-06 21:05:20,633 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:05:20,633 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:05:20,698 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:05:22,185 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 21:05:22,187 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:05:22,187 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 21:05:22,200 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:05:22,200 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:05:22,728 basehttp 77344 6157611008 "GET /en/billing/bills/49ecf1c4-8024-4107-ad14-0d46cf66fe79/ HTTP/1.1" 200 38565 +WARNING 2025-09-06 21:05:22,744 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:05:22,744 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:05:22,787 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:06:22,791 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:07:22,802 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:07:53,414 basehttp 77344 6157611008 "GET /en/billing/payments/create/?bill=49ecf1c4-8024-4107-ad14-0d46cf66fe79 HTTP/1.1" 200 42101 +WARNING 2025-09-06 21:07:53,429 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:07:53,430 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:07:53,475 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 21:07:59,928 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:07:59,928 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 21:07:59,941 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:07:59,941 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:08:22,808 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:08:23,620 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 200 37650 +WARNING 2025-09-06 21:08:23,640 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:08:23,640 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:08:23,683 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:08:27,797 basehttp 77344 6157611008 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 200 37650 +WARNING 2025-09-06 21:08:27,815 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:08:27,816 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:08:27,853 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-06 21:08:35,506 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:08:35,506 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 21:08:35,518 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:08:35,518 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-06 21:08:35,894 log 77344 6157611008 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-06 21:08:35,894 basehttp 77344 6157611008 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-06 21:09:35,940 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:09:35,945 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:10:35,950 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:10:35,952 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:11:35,955 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:11:35,958 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:12:35,949 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:12:35,952 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:13:35,952 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:13:35,955 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:14:35,958 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:14:35,961 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:15:35,955 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:15:35,958 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:16:35,958 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:16:35,961 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:17:35,967 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:17:35,970 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:18:35,945 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:18:35,948 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:19:36,239 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:19:36,243 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:20:38,239 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:20:38,242 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:23:50,004 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:23:50,007 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:25:50,011 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:25:50,015 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:28:17,699 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:28:17,702 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:30:17,696 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:30:17,699 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:32:41,898 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:32:41,901 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:39:08,829 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:39:08,832 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:41:08,820 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:41:08,823 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:43:08,820 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:43:08,823 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:45:08,818 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:45:08,821 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:47:08,816 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:47:08,818 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:49:08,818 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:49:08,821 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:51:08,825 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:51:08,826 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:53:08,800 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:53:08,803 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:55:08,848 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:55:08,851 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:57:08,855 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:57:08,858 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 21:59:08,851 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 21:59:08,854 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:01:08,861 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:01:08,863 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:03:08,853 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:03:08,856 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:05:08,854 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:05:08,858 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:07:08,851 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:07:08,854 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:09:08,854 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:09:08,856 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:11:08,846 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:11:08,849 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:13:08,851 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:13:08,853 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:15:08,843 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:15:08,846 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:17:08,843 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:17:08,846 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:19:08,841 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:19:08,844 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:21:08,834 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:21:08,837 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:23:08,836 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:23:08,841 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:25:08,841 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:25:08,844 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:27:08,813 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:27:08,815 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:29:08,814 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:29:08,817 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:31:08,811 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:31:08,814 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:33:08,813 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:33:08,815 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:35:08,814 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:35:08,816 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:37:08,809 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:37:08,813 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:39:08,809 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:39:08,812 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:42:34,941 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:42:34,943 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:49:25,788 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:49:25,791 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:51:25,783 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:51:25,786 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:53:25,764 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:53:25,765 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:55:25,774 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:55:25,777 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:57:25,908 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:57:25,911 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 22:58:25,919 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 22:58:25,923 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:00:25,913 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:00:25,915 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:01:25,923 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:01:25,927 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:03:25,907 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:03:25,910 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:05:25,897 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:05:25,899 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:07:25,909 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:07:25,913 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:09:25,909 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:09:25,912 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:11:25,910 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:11:25,914 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:13:25,903 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:13:25,907 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:15:25,904 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:15:25,907 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:17:25,926 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:17:25,929 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:19:25,904 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:19:25,908 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:21:25,922 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:21:25,925 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:23:25,908 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:23:25,911 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:25:25,916 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:25:25,919 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:27:25,908 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:27:25,913 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:29:25,892 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:29:25,895 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:31:25,898 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:31:25,901 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:33:25,895 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:33:25,898 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:35:25,875 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:35:25,878 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:37:25,891 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:37:25,895 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:39:25,895 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:39:25,898 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:41:25,896 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:41:25,899 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:43:25,900 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:43:25,903 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:45:25,898 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:45:25,901 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:47:25,900 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:47:25,903 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:49:25,909 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:49:25,912 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-06 23:54:06,595 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-06 23:54:06,598 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:05:11,486 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:05:11,489 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:07:31,248 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:07:31,251 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:18:38,689 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:18:38,693 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:23:25,721 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:23:25,724 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:35:15,078 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:35:15,082 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:37:15,065 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:37:15,068 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:39:15,064 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:39:15,067 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:41:15,061 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:41:15,064 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:43:15,064 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:43:15,066 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:45:15,057 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:45:15,060 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:47:15,054 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:47:15,057 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:49:15,100 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:49:15,103 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:51:15,085 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:51:15,087 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:53:15,096 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:53:15,098 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:55:15,098 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:55:15,102 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:57:15,098 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:57:15,100 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 00:59:15,096 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 00:59:15,099 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:01:15,094 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:01:15,098 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:03:15,116 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:03:15,120 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:05:15,126 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:05:15,129 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:07:15,124 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:07:15,127 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:09:15,127 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:09:15,129 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:11:15,110 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:11:15,112 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:13:15,117 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:13:15,119 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:15:15,120 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:15:15,122 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:17:15,119 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:17:15,121 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:19:15,107 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:19:15,110 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:21:15,118 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:21:15,121 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:23:15,117 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:23:15,120 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:25:15,125 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:25:15,128 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:27:15,113 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:27:15,116 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:29:15,122 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:29:15,124 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:31:15,115 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:31:15,118 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:33:15,196 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:33:15,199 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:35:15,204 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:35:15,207 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:47:32,334 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:47:32,337 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 01:57:14,127 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 01:57:14,130 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:04:09,538 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:04:09,542 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:06:09,532 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:06:09,535 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:08:09,538 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:08:09,540 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:10:09,524 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:10:09,526 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:12:09,536 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:12:09,539 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:14:09,539 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:14:09,543 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:16:09,546 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:16:09,549 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:18:09,560 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:18:09,563 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:20:09,576 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:20:09,578 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:22:09,565 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:22:09,568 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:23:09,591 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:23:09,594 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:25:09,570 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:25:09,572 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:27:09,581 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:27:09,585 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:29:09,599 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:29:09,602 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:31:09,604 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:31:09,607 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:33:09,580 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:33:09,583 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:35:09,577 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:35:09,580 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:37:09,572 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:37:09,574 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:39:09,562 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:39:09,564 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:41:09,587 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:41:09,590 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:43:09,585 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:43:09,589 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:45:09,593 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:45:09,596 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:47:09,580 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:47:09,583 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:49:09,582 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:49:09,590 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:51:09,589 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:51:09,592 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:53:09,587 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:53:09,590 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:55:09,578 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:55:09,581 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:57:09,596 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:57:09,600 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 02:59:09,587 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 02:59:09,590 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4938 +INFO 2025-09-07 03:01:09,592 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:01:09,596 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:03:09,609 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:03:09,612 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:18:53,235 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:18:53,238 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:20:53,003 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:20:53,007 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:22:52,994 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:22:52,997 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:24:52,996 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:24:52,999 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:26:52,998 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:26:53,001 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:28:52,999 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:28:53,002 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:30:53,015 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:30:53,018 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:32:53,011 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:32:53,015 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:34:52,851 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:34:52,854 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:36:52,849 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:36:52,852 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:38:52,848 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:38:52,851 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:40:52,845 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:40:52,848 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:42:52,858 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:42:52,861 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:44:52,844 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:44:52,847 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:46:52,845 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:46:52,847 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:48:52,841 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:48:52,844 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:50:52,847 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:50:52,850 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:52:52,839 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:52:52,845 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:54:52,845 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:54:52,848 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:56:52,852 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:56:52,855 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 03:58:52,844 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 03:58:52,847 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:00:52,843 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:00:52,845 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:02:52,842 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:02:52,845 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:04:52,855 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:04:52,858 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:06:52,858 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:06:52,861 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:08:52,847 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:08:52,850 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:10:52,846 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:10:52,849 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:12:52,845 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:12:52,849 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:14:52,844 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:14:52,847 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:16:52,851 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:16:52,854 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:18:52,841 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:18:52,843 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:27:01,087 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:27:01,090 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:30:06,007 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:30:06,010 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:45:08,671 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:45:08,674 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:46:08,658 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:47:08,668 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:48:08,647 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:49:08,665 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:50:08,655 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:51:08,672 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:52:08,658 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:53:08,660 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:54:08,641 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:55:08,659 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:56:08,659 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:57:08,646 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 04:58:08,641 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 04:59:08,640 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:00:08,644 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:01:08,639 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:02:08,674 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:03:08,634 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:04:08,637 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:05:08,632 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:06:08,645 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:07:08,641 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:08:08,627 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:09:08,643 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:10:08,646 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:11:08,624 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:12:08,627 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:13:08,645 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:14:08,627 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:15:08,630 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:16:08,632 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:17:08,663 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:18:08,638 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:19:08,628 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:20:08,638 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:21:08,649 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:22:08,631 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:23:08,635 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:24:08,637 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:25:08,624 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:26:08,621 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:27:08,627 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:28:08,661 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:28:08,664 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:30:08,620 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:30:08,622 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:31:08,737 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:32:08,740 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:33:08,735 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:34:08,753 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:35:08,751 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:36:08,739 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:37:08,741 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:38:08,756 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:39:08,748 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:40:08,756 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:41:08,739 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:42:08,746 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:43:08,753 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:44:08,741 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:45:08,754 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:48:49,254 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:51:47,792 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:56:57,168 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:57:57,160 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 05:58:57,173 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 05:59:57,161 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:00:57,166 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:01:57,162 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:02:57,164 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:03:57,148 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:04:57,152 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:05:57,149 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:06:57,148 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:07:57,147 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:08:57,151 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:09:57,151 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:10:57,151 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:11:57,147 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:12:57,150 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:13:57,149 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:14:57,149 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:15:57,139 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:16:57,153 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:17:57,147 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:18:57,160 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:19:57,165 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:20:57,163 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:21:57,158 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:22:57,161 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:23:57,160 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:24:57,170 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:25:57,158 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:26:57,162 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:27:57,160 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:28:57,152 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:29:57,168 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:30:57,148 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:31:57,158 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:32:57,162 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:33:57,170 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:34:57,172 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:35:57,172 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:36:57,172 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:37:57,172 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:38:57,171 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:39:57,179 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:40:57,175 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:41:57,172 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:42:57,175 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:43:57,163 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:44:57,171 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:45:57,172 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:46:57,177 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:47:57,174 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:48:57,302 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:49:57,308 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:50:57,305 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:51:57,303 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:52:57,307 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:53:57,308 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 06:54:57,308 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 06:55:57,308 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:00:31,574 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:04:05,986 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:07:02,629 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:10:49,009 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:11:48,997 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:12:49,000 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:13:49,030 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:13:49,030 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:15:48,889 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:15:48,893 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:17:48,887 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:17:48,889 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:19:48,882 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:19:48,884 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:20:48,897 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:20:48,900 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:22:48,882 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:22:48,884 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:24:48,877 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:24:48,879 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:26:48,890 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:26:48,893 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:28:48,885 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:28:48,889 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:30:48,884 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:30:48,888 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:32:48,916 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:32:48,918 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:34:48,892 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:34:48,894 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:36:48,888 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:36:48,891 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:38:48,891 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:38:48,895 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:40:48,889 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:40:48,892 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:42:48,882 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:42:48,885 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:44:48,900 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:44:48,903 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:46:48,771 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:46:48,774 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:48:48,772 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:48:48,773 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:50:48,784 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:50:48,785 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:52:48,777 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:52:48,780 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:53:48,801 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:53:48,803 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:55:48,784 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:55:48,787 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:57:48,761 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:57:48,764 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 07:59:48,762 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 07:59:48,765 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:01:48,761 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:01:48,764 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:03:48,754 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:03:48,756 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:05:48,760 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:05:48,763 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:07:48,749 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:07:48,751 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:08:48,741 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:08:48,743 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:10:48,745 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:10:48,747 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:14:35,707 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:14:35,710 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:22:57,062 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:22:57,065 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:24:57,051 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:24:57,055 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:26:57,052 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:26:57,055 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:28:57,050 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:28:57,053 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:30:57,047 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:30:57,050 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:36:20,741 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:36:20,744 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:38:20,730 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:38:20,733 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:40:20,727 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:40:20,730 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:42:20,735 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:42:20,738 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:44:20,723 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:44:20,726 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:46:20,729 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:46:20,733 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:48:20,725 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:48:20,729 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:50:20,833 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:50:20,836 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:52:20,836 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:52:20,839 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:54:20,821 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:54:20,823 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:56:20,846 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:56:20,848 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 08:58:20,838 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 08:58:20,843 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:00:20,836 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:00:20,838 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:02:20,836 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:02:20,839 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:04:20,836 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:04:20,838 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:06:20,831 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:06:20,834 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:08:20,841 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:08:20,845 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:10:20,835 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:10:20,838 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:12:20,835 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:12:20,838 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:14:20,871 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:14:20,873 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:16:20,815 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:16:20,817 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:18:20,843 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:18:20,846 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:20:20,933 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:20:20,935 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:22:20,970 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:22:20,972 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:24:20,938 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:24:20,941 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:26:20,941 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:26:20,944 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:28:20,955 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:28:20,959 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:30:20,943 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:30:20,945 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:32:20,947 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:32:20,950 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:34:20,950 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:34:20,952 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:43:12,980 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:43:12,985 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:44:12,941 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:44:12,943 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:45:12,948 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:45:12,951 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:46:12,953 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:46:12,956 basehttp 77344 6174437376 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:47:13,815 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:47:13,817 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:52:52,859 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:52:52,861 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:57:54,394 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:57:54,397 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 09:59:54,393 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 09:59:54,396 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:08:09,558 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:08:09,561 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:10:09,559 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:10:09,562 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:12:09,559 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:12:09,562 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:14:09,566 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:14:09,569 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:16:09,571 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:16:09,573 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:18:09,578 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:18:09,582 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:20:09,568 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:20:09,570 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:22:09,571 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:22:09,574 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:24:09,572 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:24:09,574 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:26:09,567 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:26:09,569 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:28:09,574 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:28:09,577 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:30:09,584 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:30:09,587 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:32:09,578 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:32:09,581 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:34:09,563 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:34:09,574 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:36:09,576 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:36:09,580 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:38:09,576 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:38:09,579 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:40:09,628 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:40:09,631 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:42:09,622 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:42:09,624 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:44:09,630 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:44:09,633 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:46:09,633 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:46:09,636 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:48:09,629 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:48:09,632 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:50:09,638 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:50:09,640 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:52:09,641 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:52:09,644 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:54:09,638 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:54:09,640 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:56:09,641 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:56:09,643 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 10:58:09,649 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 10:58:09,652 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:00:09,659 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:00:09,662 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:02:09,646 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:02:09,650 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:04:09,654 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:04:09,657 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:06:09,661 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:06:09,664 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:08:09,654 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:08:09,657 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:18:47,301 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:18:47,303 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:26:17,718 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:26:17,721 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:33:46,852 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:33:46,854 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:46:00,804 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:46:00,806 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:48:00,816 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:48:00,818 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:50:00,816 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:50:00,818 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:52:00,817 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:52:00,819 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:54:00,814 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:54:00,817 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:56:00,825 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:56:00,827 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 11:58:00,832 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 11:58:00,835 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:00:00,834 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:00:00,837 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:02:00,850 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:02:00,853 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:04:00,853 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:04:00,856 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:06:00,860 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:06:00,863 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:08:00,856 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:08:00,859 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:10:00,855 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:10:00,858 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:29:03,105 basehttp 77344 6157611008 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +INFO 2025-09-07 12:29:03,107 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 12:29:05,278 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:29:05,278 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 12:29:06,347 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:29:06,347 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 12:29:07,590 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:29:07,591 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 12:29:07,602 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:29:07,602 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:30:05,385 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:31:05,382 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:32:05,383 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:33:05,384 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:34:05,402 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:34:22,538 basehttp 77344 6174437376 "GET /en/billing/bills/create/ HTTP/1.1" 200 126347 +WARNING 2025-09-07 12:34:22,558 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:34:22,558 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:34:22,607 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:35:22,623 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 12:35:40,628 log 77344 6208090112 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:35:40,629 basehttp 77344 6208090112 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:35:40,632 basehttp 77344 6157611008 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:35:40,635 basehttp 77344 6191263744 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +INFO 2025-09-07 12:35:40,638 basehttp 77344 6174437376 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +WARNING 2025-09-07 12:35:40,641 log 77344 6208090112 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:35:40,641 basehttp 77344 6208090112 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:35:46,410 basehttp 77344 6208090112 "GET /en/billing HTTP/1.1" 301 0 +INFO 2025-09-07 12:35:46,434 basehttp 77344 6174437376 "GET /en/billing/ HTTP/1.1" 200 47086 +WARNING 2025-09-07 12:35:46,448 log 77344 6174437376 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:35:46,449 basehttp 77344 6174437376 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:35:46,477 basehttp 77344 6174437376 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:35:46,480 basehttp 77344 6191263744 "GET /en/billing/htmx/stats/ HTTP/1.1" 200 4943 +ERROR 2025-09-07 12:35:53,457 log 77344 6191263744 Internal Server Error: /en/billing/claims/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'export_claims' not found. 'export_claims' is not a valid view function or pattern name. +ERROR 2025-09-07 12:35:53,458 basehttp 77344 6191263744 "GET /en/billing/claims/ HTTP/1.1" 500 207751 +WARNING 2025-09-07 12:35:53,477 log 77344 6191263744 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:35:53,477 basehttp 77344 6191263744 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:39:36,305 autoreload 77344 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 12:39:36,788 autoreload 97928 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 12:40:53,033 autoreload 97928 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 12:40:53,426 autoreload 98481 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 12:40:54,795 log 98481 6134345728 Internal Server Error: /en/billing/claims/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'export_claims' not found. 'export_claims' is not a valid view function or pattern name. +ERROR 2025-09-07 12:40:54,797 basehttp 98481 6134345728 "GET /en/billing/claims/ HTTP/1.1" 500 207888 +WARNING 2025-09-07 12:40:54,809 log 98481 6134345728 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:40:54,809 basehttp 98481 6134345728 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:44:58,267 autoreload 98481 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 12:44:58,602 autoreload 826 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 12:45:22,581 autoreload 826 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/urls.py changed, reloading. +INFO 2025-09-07 12:45:22,898 autoreload 1126 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 12:45:24,934 log 1126 6129577984 Internal Server Error: /en/billing/claims/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'batch_submit_claims' not found. 'batch_submit_claims' is not a valid view function or pattern name. +ERROR 2025-09-07 12:45:24,936 basehttp 1126 6129577984 "GET /en/billing/claims/ HTTP/1.1" 500 207934 +WARNING 2025-09-07 12:45:24,952 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:45:24,952 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 12:45:46,751 log 1126 6129577984 Internal Server Error: /en/billing/claims/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_stats' not found. 'claim_stats' is not a valid view function or pattern name. +ERROR 2025-09-07 12:45:46,753 basehttp 1126 6129577984 "GET /en/billing/claims/ HTTP/1.1" 500 207076 +WARNING 2025-09-07 12:45:46,769 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:45:46,770 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 12:46:13,557 log 1126 6129577984 Internal Server Error: /en/billing/claims/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 243, in render + nodelist.append(node.render_annotated(context)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_print' not found. 'claim_print' is not a valid view function or pattern name. +ERROR 2025-09-07 12:46:13,558 basehttp 1126 6129577984 "GET /en/billing/claims/ HTTP/1.1" 500 236107 +WARNING 2025-09-07 12:46:13,574 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:46:13,574 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 12:46:55,322 log 1126 6129577984 Internal Server Error: /en/billing/claims/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bulk_submit_claims' not found. 'bulk_submit_claims' is not a valid view function or pattern name. +ERROR 2025-09-07 12:46:55,324 basehttp 1126 6129577984 "GET /en/billing/claims/ HTTP/1.1" 500 211156 +WARNING 2025-09-07 12:46:55,339 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:46:55,339 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:47:18,798 basehttp 1126 6129577984 "GET /en/billing/claims/ HTTP/1.1" 200 144975 +WARNING 2025-09-07 12:47:18,815 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:47:18,815 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:47:18,892 basehttp 1126 6129577984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:48:05,593 basehttp 1126 6129577984 "GET /en/billing/claims/ HTTP/1.1" 200 145155 +WARNING 2025-09-07 12:48:05,607 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:48:05,608 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:48:05,660 basehttp 1126 6129577984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:48:17,864 basehttp 1126 6129577984 "GET /en/billing/claims/172084ad-de1a-44f4-b67d-f89f27dca7dc/ HTTP/1.1" 200 37650 +WARNING 2025-09-07 12:48:17,881 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:48:17,882 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:48:17,924 basehttp 1126 6129577984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 12:48:28,251 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:48:28,251 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 12:48:28,285 log 1126 6129577984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:48:28,286 basehttp 1126 6129577984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:49:05,672 basehttp 1126 6129577984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 12:49:20,467 autoreload 1126 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 12:49:20,872 autoreload 2864 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-07 12:49:21,914 log 2864 6203011072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:49:21,914 basehttp 2864 6203011072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 12:49:21,927 log 2864 6203011072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:49:21,927 basehttp 2864 6203011072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:49:22,778 basehttp 2864 6203011072 "GET /en/billing/claims/ HTTP/1.1" 200 145155 +WARNING 2025-09-07 12:49:22,799 log 2864 6203011072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:49:22,799 basehttp 2864 6203011072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 12:49:22,857 basehttp 2864 6203011072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 12:49:24,049 log 2864 6203011072 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_details_api' not found. 'bill_details_api' is not a valid view function or pattern name. +ERROR 2025-09-07 12:49:24,051 basehttp 2864 6203011072 "GET /en/billing/claims/create/ HTTP/1.1" 500 194122 +WARNING 2025-09-07 12:49:24,068 log 2864 6203011072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 12:49:24,068 basehttp 2864 6203011072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:02:57,501 autoreload 2864 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/urls.py changed, reloading. +INFO 2025-09-07 14:02:58,023 autoreload 5063 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 14:07:44,147 autoreload 5063 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/urls.py changed, reloading. +INFO 2025-09-07 14:07:44,460 autoreload 7139 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 14:07:46,904 log 7139 6202322944 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_details_api' with no arguments not found. 1 pattern(s) tried: ['en/billing/bills/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/\\Z'] +ERROR 2025-09-07 14:07:46,906 basehttp 7139 6202322944 "GET /en/billing/claims/create/ HTTP/1.1" 500 196668 +WARNING 2025-09-07 14:07:46,924 log 7139 6202322944 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:07:46,924 basehttp 7139 6202322944 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 14:09:34,737 log 7139 6202322944 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_details_api' with arguments '('',)' not found. 1 pattern(s) tried: ['en/billing/bills/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/\\Z'] +ERROR 2025-09-07 14:09:34,739 basehttp 7139 6202322944 "GET /en/billing/claims/create/ HTTP/1.1" 500 198113 +WARNING 2025-09-07 14:09:34,753 log 7139 6202322944 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:09:34,753 basehttp 7139 6202322944 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 14:10:56,880 log 7139 6202322944 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_details_api' with arguments '(0,)' not found. 1 pattern(s) tried: ['en/billing/bills/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/\\Z'] +ERROR 2025-09-07 14:10:56,881 basehttp 7139 6202322944 "GET /en/billing/claims/create/ HTTP/1.1" 500 198003 +WARNING 2025-09-07 14:10:56,895 log 7139 6202322944 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:10:56,895 basehttp 7139 6202322944 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:11:45,306 autoreload 7139 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 14:11:45,662 autoreload 8942 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 14:11:47,998 log 8942 6157873152 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_details_api' with arguments '(0,)' not found. 1 pattern(s) tried: ['en/billing/bills/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/\\Z'] +ERROR 2025-09-07 14:11:48,000 basehttp 8942 6157873152 "GET /en/billing/claims/create/ HTTP/1.1" 500 198003 +WARNING 2025-09-07 14:11:48,016 log 8942 6157873152 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:11:48,016 basehttp 8942 6157873152 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 14:13:51,092 log 8942 6157873152 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_details_api' with arguments '(0,)' not found. 1 pattern(s) tried: ['en/billing/bills/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/\\Z'] +ERROR 2025-09-07 14:13:51,093 basehttp 8942 6157873152 "GET /en/billing/claims/create/ HTTP/1.1" 500 198021 +WARNING 2025-09-07 14:13:51,107 log 8942 6157873152 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:13:51,107 basehttp 8942 6157873152 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:17:09,213 autoreload 8942 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 14:17:09,525 autoreload 11319 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 14:17:35,604 autoreload 11319 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/urls.py changed, reloading. +INFO 2025-09-07 14:17:35,925 autoreload 11481 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 14:18:02,757 log 11481 6171029504 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'insurance_details_api' not found. 'insurance_details_api' is not a valid view function or pattern name. +ERROR 2025-09-07 14:18:02,758 basehttp 11481 6171029504 "GET /en/billing/claims/create/ HTTP/1.1" 500 194751 +WARNING 2025-09-07 14:18:02,776 log 11481 6171029504 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:18:02,776 basehttp 11481 6171029504 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:21:36,134 autoreload 11481 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 14:21:36,450 autoreload 13311 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 14:30:21,471 autoreload 13311 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/patients/views.py changed, reloading. +INFO 2025-09-07 14:30:21,814 autoreload 17159 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 14:30:22,942 log 17159 6201470976 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_line_items_api' not found. 'bill_line_items_api' is not a valid view function or pattern name. +ERROR 2025-09-07 14:30:22,944 basehttp 17159 6201470976 "GET /en/billing/claims/create/ HTTP/1.1" 500 194905 +WARNING 2025-09-07 14:30:22,954 log 17159 6201470976 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:30:22,954 basehttp 17159 6201470976 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:32:17,361 autoreload 17159 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/urls.py changed, reloading. +INFO 2025-09-07 14:32:17,711 autoreload 18042 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 14:33:39,885 autoreload 18042 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/billing/views.py changed, reloading. +INFO 2025-09-07 14:33:40,189 autoreload 18669 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 14:33:48,303 log 18669 6198521856 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'bill_line_items_api' with no arguments not found. 1 pattern(s) tried: ['en/billing/bills/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/line\\-items\\Z'] +ERROR 2025-09-07 14:33:48,304 basehttp 18669 6198521856 "GET /en/billing/claims/create/ HTTP/1.1" 500 197447 +WARNING 2025-09-07 14:33:48,321 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:33:48,321 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 14:35:02,948 log 18669 6198521856 Internal Server Error: /en/billing/claims/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_preview' not found. 'claim_preview' is not a valid view function or pattern name. +ERROR 2025-09-07 14:35:02,949 basehttp 18669 6198521856 "GET /en/billing/claims/create/ HTTP/1.1" 500 194951 +WARNING 2025-09-07 14:35:02,965 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:35:02,965 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:35:25,061 basehttp 18669 6198521856 "GET /en/billing/claims/create/ HTTP/1.1" 200 66340 +WARNING 2025-09-07 14:35:25,077 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:35:25,077 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:35:25,140 basehttp 18669 6198521856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:36:20,079 basehttp 18669 6198521856 "GET /en/billing/bills/49ecf1c4-8024-4107-ad14-0d46cf66fe79/ HTTP/1.1" 200 38565 +INFO 2025-09-07 14:36:25,152 basehttp 18669 6198521856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:37:08,113 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:37:08,113 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:37:30,410 basehttp 18669 6198521856 "GET /en/billing/claims/ HTTP/1.1" 200 147205 +WARNING 2025-09-07 14:37:30,426 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:37:30,426 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:37:30,474 basehttp 18669 6198521856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:37:39,286 basehttp 18669 6198521856 "GET /en/billing/claims/ HTTP/1.1" 200 147205 +WARNING 2025-09-07 14:37:39,304 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:37:39,305 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:37:39,357 basehttp 18669 6198521856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 14:37:40,782 log 18669 6198521856 Internal Server Error: /en/billing/claims/5237a09c-9179-4f06-a247-65ce91213492/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'claim_appeal' not found. 'claim_appeal' is not a valid view function or pattern name. +ERROR 2025-09-07 14:37:40,784 basehttp 18669 6198521856 "GET /en/billing/claims/5237a09c-9179-4f06-a247-65ce91213492/ HTTP/1.1" 500 191204 +WARNING 2025-09-07 14:37:40,802 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:37:40,802 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:41:07,375 basehttp 18669 6198521856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:41:07,377 log 18669 6215348224 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:41:07,377 basehttp 18669 6215348224 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:41:07,390 log 18669 6215348224 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:41:07,391 basehttp 18669 6215348224 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:41:11,966 basehttp 18669 6215348224 "GET /en/hr HTTP/1.1" 301 0 +INFO 2025-09-07 14:41:12,005 basehttp 18669 6198521856 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 14:41:12,022 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:41:12,022 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:41:12,038 basehttp 18669 6198521856 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 14:41:32,945 log 18669 6198521856 Internal Server Error: /en/hr/departments/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 47, in select_template + raise TemplateDoesNotExist(", ".join(template_name_list), chain=chain) +django.template.exceptions.TemplateDoesNotExist: hr/department_list.html, hr/department_list.html +ERROR 2025-09-07 14:41:32,946 basehttp 18669 6198521856 "GET /en/hr/departments/ HTTP/1.1" 500 86314 +WARNING 2025-09-07 14:41:32,965 log 18669 6198521856 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:41:32,966 basehttp 18669 6198521856 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:44:30,725 autoreload 18669 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 14:44:31,100 autoreload 23535 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 14:48:28,470 basehttp 23535 6201683968 "GET /en/hr/departments/ HTTP/1.1" 200 125426 +INFO 2025-09-07 14:48:28,486 basehttp 23535 6218510336 "GET /static/plugins/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css HTTP/1.1" 200 8136 +WARNING 2025-09-07 14:48:28,488 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:48:28,488 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:48:28,490 basehttp 23535 6218510336 "GET /static/plugins/datatables.net-buttons-bs5/js/buttons.bootstrap5.min.js HTTP/1.1" 200 1627 +INFO 2025-09-07 14:48:28,492 basehttp 23535 6201683968 "GET /static/plugins/datatables.net-buttons/js/dataTables.buttons.min.js HTTP/1.1" 200 27926 +INFO 2025-09-07 14:48:28,492 basehttp 23535 6252163072 "GET /static/plugins/datatables.net-buttons/js/buttons.print.min.js HTTP/1.1" 200 3073 +INFO 2025-09-07 14:48:28,492 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-buttons/js/buttons.html5.min.js HTTP/1.1" 200 26043 +INFO 2025-09-07 14:48:28,498 basehttp 23535 6268989440 "GET /static/plugins/jszip/dist/jszip.min.js HTTP/1.1" 200 97630 +INFO 2025-09-07 14:48:28,504 basehttp 23535 6218510336 "GET /static/plugins/pdfmake/build/vfs_fonts.js HTTP/1.1" 200 828866 +INFO 2025-09-07 14:48:28,505 basehttp 23535 6285815808 "GET /static/plugins/pdfmake/build/pdfmake.min.js HTTP/1.1" 200 1400771 +INFO 2025-09-07 14:48:28,604 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:48:28,606 basehttp 23535 6285815808 "GET /static/plugins/pdfmake/build/pdfmake.min.js.map HTTP/1.1" 200 4214503 +INFO 2025-09-07 14:48:47,353 basehttp 23535 6285815808 "GET /en/hr/departments/create/ HTTP/1.1" 200 41288 +WARNING 2025-09-07 14:48:47,364 basehttp 23535 6285815808 "GET /static/plugins/select2-bootstrap5-theme/select2-bootstrap5.min.css HTTP/1.1" 404 2104 +WARNING 2025-09-07 14:48:47,373 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:48:47,373 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:48:47,444 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:49:02,684 basehttp 23535 6218510336 "GET /en/hr/departments/ HTTP/1.1" 200 125426 +WARNING 2025-09-07 14:49:02,703 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:49:02,703 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:49:02,798 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:49:04,753 basehttp 23535 6218510336 "GET /en/hr/departments/12/ HTTP/1.1" 200 35129 +WARNING 2025-09-07 14:49:04,775 basehttp 23535 6218510336 "GET /static/plugins/chart.js/dist/Chart.min.css HTTP/1.1" 404 2032 +WARNING 2025-09-07 14:49:04,775 basehttp 23535 6268989440 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 14:49:04,775 basehttp 23535 6235336704 "GET /static/plugins/chart.js/dist/Chart.min.js HTTP/1.1" 404 2029 +WARNING 2025-09-07 14:49:04,781 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:49:04,781 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:49:04,825 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:49:56,931 basehttp 23535 6252163072 "GET /en/hr/departments/12/update/ HTTP/1.1" 200 41458 +WARNING 2025-09-07 14:49:56,950 basehttp 23535 6201683968 "GET /static/plugins/select2-bootstrap5-theme/select2-bootstrap5.min.css HTTP/1.1" 404 2104 +WARNING 2025-09-07 14:49:56,954 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:49:56,954 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:49:57,005 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:03,717 basehttp 23535 6201683968 "GET /static/plugins/chart.js/dist/Chart.min.css HTTP/1.1" 404 2032 +WARNING 2025-09-07 14:50:03,721 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:03,721 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:03,732 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:03,732 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:04,847 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:10,725 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-07 14:50:10,725 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:10,725 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:10,741 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:10,741 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:13,335 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:13,338 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:13,340 basehttp 23535 6252163072 "GET /static/plugins/select2-bootstrap5-theme/select2-bootstrap5.min.css HTTP/1.1" 404 2104 +WARNING 2025-09-07 14:50:13,340 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:13,352 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:13,352 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:14,669 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:14,669 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:14,671 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:14,684 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:14,684 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:17,041 log 23535 6235336704 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:17,042 basehttp 23535 6235336704 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:17,044 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:17,051 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:17,051 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:17,057 basehttp 23535 6218510336 "GET /en/hr/htmx/stats/ HTTP/1.1" 200 4459 +INFO 2025-09-07 14:50:18,074 basehttp 23535 6218510336 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 14:50:18,091 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:18,091 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:18,143 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:50:19,416 basehttp 23535 6218510336 "GET /en/hr/employees/ HTTP/1.1" 200 130495 +WARNING 2025-09-07 14:50:19,439 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:19,439 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:19,483 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:50:32,151 basehttp 23535 6218510336 "GET /en/hr/employees/56/ HTTP/1.1" 200 34482 +WARNING 2025-09-07 14:50:32,175 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:32,175 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:32,215 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:50:39,307 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:39,307 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:39,323 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:39,323 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:40,377 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:40,377 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:40,389 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:40,389 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:41,063 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:41,063 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:41,949 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:41,949 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 14:50:42,797 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:42,797 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:55,783 basehttp 23535 6218510336 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 14:50:55,805 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:55,805 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:55,822 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:50:59,805 basehttp 23535 6218510336 "GET /en/hr/schedules/ HTTP/1.1" 200 121762 +WARNING 2025-09-07 14:50:59,829 basehttp 23535 6201683968 "GET /static/plugins/fullcalendar/main.min.css HTTP/1.1" 404 2026 +WARNING 2025-09-07 14:50:59,831 basehttp 23535 6252163072 "GET /static/plugins/fullcalendar/main.min.js HTTP/1.1" 404 2023 +WARNING 2025-09-07 14:50:59,831 basehttp 23535 6235336704 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 14:50:59,840 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:50:59,840 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:50:59,883 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:51:59,904 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:52:59,891 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:53:19,615 basehttp 23535 6218510336 "GET /en/hr/schedules/ HTTP/1.1" 200 121575 +WARNING 2025-09-07 14:53:19,625 basehttp 23535 6218510336 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 14:53:19,625 basehttp 23535 6201683968 "GET /static/plugins/fullcalendar/main.min.js HTTP/1.1" 404 2023 +WARNING 2025-09-07 14:53:19,631 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:53:19,631 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:53:19,688 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:53:21,928 basehttp 23535 6201683968 "GET /en/hr/schedules/ HTTP/1.1" 200 121575 +WARNING 2025-09-07 14:53:21,939 basehttp 23535 6201683968 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 14:53:21,939 basehttp 23535 6218510336 "GET /static/plugins/fullcalendar/main.min.js HTTP/1.1" 404 2023 +WARNING 2025-09-07 14:53:21,945 log 23535 6235336704 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:53:21,945 basehttp 23535 6235336704 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:53:21,997 basehttp 23535 6235336704 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:53:31,828 basehttp 23535 6235336704 "GET /en/hr/schedules/?page=2 HTTP/1.1" 200 122790 +WARNING 2025-09-07 14:53:31,847 basehttp 23535 6235336704 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 14:53:31,848 basehttp 23535 6201683968 "GET /static/plugins/fullcalendar/main.min.js HTTP/1.1" 404 2023 +WARNING 2025-09-07 14:53:31,854 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:53:31,854 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:53:31,896 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:54:32,350 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:55:33,351 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:56:34,352 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:57:35,360 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:58:07,336 basehttp 23535 6218510336 "GET /en/hr/schedules/?page=2 HTTP/1.1" 200 123284 +INFO 2025-09-07 14:58:07,344 basehttp 23535 6218510336 "GET /static/plugins/moment/min/moment.min.js HTTP/1.1" 200 58890 +INFO 2025-09-07 14:58:07,356 basehttp 23535 6285815808 "GET /static/plugins/%40fullcalendar/bootstrap/index.global.js HTTP/1.1" 200 2075 +INFO 2025-09-07 14:58:07,356 basehttp 23535 6235336704 "GET /static/plugins/%40fullcalendar/timegrid/index.global.js HTTP/1.1" 200 68582 +INFO 2025-09-07 14:58:07,357 basehttp 23535 6268989440 "GET /static/plugins/%40fullcalendar/list/index.global.js HTTP/1.1" 200 18635 +INFO 2025-09-07 14:58:07,357 basehttp 23535 6201683968 "GET /static/plugins/%40fullcalendar/daygrid/index.global.js HTTP/1.1" 200 58461 +INFO 2025-09-07 14:58:07,358 basehttp 23535 6252163072 "GET /static/plugins/%40fullcalendar/interaction/index.global.js HTTP/1.1" 200 99452 +INFO 2025-09-07 14:58:07,362 basehttp 23535 6218510336 "GET /static/plugins/%40fullcalendar/core/index.global.js HTTP/1.1" 200 444856 +WARNING 2025-09-07 14:58:07,366 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 14:58:07,366 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:58:07,428 basehttp 23535 6252163072 "GET /static/plugins/moment/min/moment.min.js.map HTTP/1.1" 200 98730 +INFO 2025-09-07 14:58:07,467 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 14:58:10,732 basehttp 23535 6252163072 "GET /en/hr/schedules/?page=2 HTTP/1.1" 200 123284 +INFO 2025-09-07 14:58:10,740 basehttp 23535 6201683968 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-07 14:58:10,742 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-07 14:58:10,743 basehttp 23535 6268989440 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +WARNING 2025-09-07 14:58:10,748 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-07 14:58:10,748 basehttp 23535 6285815808 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +WARNING 2025-09-07 14:58:10,749 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 14:58:10,749 basehttp 23535 6235336704 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-07 14:58:10,753 basehttp 23535 6201683968 "GET /static/plugins/moment/min/moment.min.js HTTP/1.1" 200 58890 +INFO 2025-09-07 14:58:10,755 basehttp 23535 6252163072 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-07 14:58:10,756 basehttp 23535 6201683968 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-07 14:58:10,759 basehttp 23535 6285815808 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-07 14:58:10,760 basehttp 23535 6235336704 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-07 14:58:10,760 basehttp 23535 6201683968 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-07 14:58:10,762 basehttp 23535 6252163072 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-07 14:58:10,765 basehttp 23535 6235336704 "GET /static/plugins/%40fullcalendar/timegrid/index.global.js HTTP/1.1" 200 68582 +INFO 2025-09-07 14:58:10,766 basehttp 23535 6201683968 "GET /static/plugins/%40fullcalendar/daygrid/index.global.js HTTP/1.1" 200 58461 +INFO 2025-09-07 14:58:10,768 basehttp 23535 6252163072 "GET /static/plugins/%40fullcalendar/interaction/index.global.js HTTP/1.1" 200 99452 +INFO 2025-09-07 14:58:10,769 basehttp 23535 6235336704 "GET /static/plugins/%40fullcalendar/bootstrap/index.global.js HTTP/1.1" 200 2075 +INFO 2025-09-07 14:58:10,769 basehttp 23535 6201683968 "GET /static/plugins/%40fullcalendar/list/index.global.js HTTP/1.1" 200 18635 +INFO 2025-09-07 14:58:10,770 basehttp 23535 6218510336 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-07 14:58:10,770 basehttp 23535 6285815808 "GET /static/plugins/%40fullcalendar/core/index.global.js HTTP/1.1" 200 444856 +INFO 2025-09-07 14:58:10,770 basehttp 23535 6268989440 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-07 14:58:11,753 basehttp 23535 6285815808 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-07 14:58:11,774 basehttp 23535 6268989440 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-07 14:58:11,774 basehttp 23535 6285815808 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-07 14:58:11,774 basehttp 23535 6252163072 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-07 14:58:11,775 basehttp 23535 6218510336 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-07 14:58:11,776 basehttp 23535 6201683968 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-07 14:58:11,779 basehttp 23535 6285815808 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-07 14:58:11,779 basehttp 23535 6235336704 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-07 14:58:11,780 basehttp 23535 6218510336 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-07 14:58:11,780 basehttp 23535 6252163072 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-07 14:58:11,780 basehttp 23535 6201683968 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-07 14:58:11,782 basehttp 23535 6235336704 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-07 14:58:11,782 basehttp 23535 6285815808 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-07 14:58:11,782 basehttp 23535 6252163072 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-07 14:58:11,783 basehttp 23535 6201683968 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-07 14:58:11,783 basehttp 23535 6218510336 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-07 14:58:11,785 basehttp 23535 6235336704 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-07 14:58:11,785 basehttp 23535 6268989440 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-07 14:58:11,786 basehttp 23535 6252163072 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-07 14:58:11,787 basehttp 23535 6235336704 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-07 14:58:11,787 basehttp 23535 6201683968 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-07 14:58:11,787 basehttp 23535 6218510336 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-07 14:58:11,788 basehttp 23535 6268989440 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-07 14:58:11,788 basehttp 23535 6285815808 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-07 14:58:11,790 basehttp 23535 6285815808 "GET /static/plugins/moment/min/moment.min.js.map HTTP/1.1" 200 98730 +INFO 2025-09-07 14:58:11,812 basehttp 23535 6285815808 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 14:58:11,937 log 23535 6285815808 Not Found: /favicon.ico +WARNING 2025-09-07 14:58:11,943 basehttp 23535 6285815808 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-07 14:59:11,824 basehttp 23535 6285815808 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:00:12,344 basehttp 23535 6285815808 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 15:01:02,531 log 23535 6285815808 Internal Server Error: /en/hr/schedules/21/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 243, in render + nodelist.append(node.render_annotated(context)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'schedule_assignment_delete' not found. 'schedule_assignment_delete' is not a valid view function or pattern name. +ERROR 2025-09-07 15:01:02,532 basehttp 23535 6285815808 "GET /en/hr/schedules/21/ HTTP/1.1" 500 224610 +WARNING 2025-09-07 15:01:02,554 log 23535 6285815808 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:01:02,554 basehttp 23535 6285815808 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 15:02:26,622 log 23535 6285815808 Internal Server Error: /en/hr/schedules/21/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'export_schedule' not found. 'export_schedule' is not a valid view function or pattern name. +ERROR 2025-09-07 15:02:26,623 basehttp 23535 6285815808 "GET /en/hr/schedules/21/ HTTP/1.1" 500 204110 +WARNING 2025-09-07 15:02:26,639 log 23535 6285815808 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:02:26,640 basehttp 23535 6285815808 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:03:24,515 basehttp 23535 6285815808 "GET /en/hr/schedules/21/ HTTP/1.1" 200 173472 +WARNING 2025-09-07 15:03:24,526 basehttp 23535 6285815808 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:03:24,527 basehttp 23535 6201683968 "GET /static/plugins/chart.js/dist/chart.umd.js HTTP/1.1" 200 206279 +WARNING 2025-09-07 15:03:24,532 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:03:24,532 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:03:24,566 basehttp 23535 6218510336 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:03:24,638 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:03:24,643 basehttp 23535 6201683968 "GET /static/plugins/chart.js/dist/chart.umd.js.map HTTP/1.1" 200 958364 +WARNING 2025-09-07 15:03:24,656 basehttp 23535 6201683968 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:03:49,585 basehttp 23535 6201683968 "GET /en/hr/schedules/21/ HTTP/1.1" 200 173472 +INFO 2025-09-07 15:03:49,597 basehttp 23535 6252163072 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-07 15:03:49,598 basehttp 23535 6285815808 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-07 15:03:49,599 basehttp 23535 6268989440 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-07 15:03:49,601 basehttp 23535 6252163072 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +WARNING 2025-09-07 15:03:49,602 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:03:49,602 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:03:49,603 basehttp 23535 6218510336 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-07 15:03:49,604 basehttp 23535 6235336704 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +WARNING 2025-09-07 15:03:49,685 basehttp 23535 6218510336 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:03:49,685 basehttp 23535 6235336704 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-07 15:03:49,687 basehttp 23535 6201683968 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-07 15:03:49,689 basehttp 23535 6201683968 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-07 15:03:49,690 basehttp 23535 6235336704 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-07 15:03:49,690 basehttp 23535 6201683968 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-07 15:03:49,691 basehttp 23535 6201683968 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-07 15:03:49,692 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-07 15:03:49,693 basehttp 23535 6235336704 "GET /static/plugins/%40fullcalendar/daygrid/index.global.js HTTP/1.1" 200 58461 +INFO 2025-09-07 15:03:49,694 basehttp 23535 6201683968 "GET /static/plugins/%40fullcalendar/core/index.global.js HTTP/1.1" 200 444856 +INFO 2025-09-07 15:03:49,695 basehttp 23535 6235336704 "GET /static/plugins/%40fullcalendar/timegrid/index.global.js HTTP/1.1" 200 68582 +INFO 2025-09-07 15:03:49,695 basehttp 23535 6201683968 "GET /static/plugins/%40fullcalendar/interaction/index.global.js HTTP/1.1" 200 99452 +INFO 2025-09-07 15:03:49,696 basehttp 23535 6235336704 "GET /static/plugins/%40fullcalendar/list/index.global.js HTTP/1.1" 200 18635 +INFO 2025-09-07 15:03:49,696 basehttp 23535 6201683968 "GET /static/plugins/%40fullcalendar/bootstrap/index.global.js HTTP/1.1" 200 2075 +INFO 2025-09-07 15:03:49,697 basehttp 23535 6235336704 "GET /static/plugins/chart.js/dist/chart.umd.js HTTP/1.1" 200 206279 +WARNING 2025-09-07 15:03:50,486 basehttp 23535 6201683968 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:03:50,487 basehttp 23535 6235336704 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-07 15:03:50,509 basehttp 23535 6252163072 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-07 15:03:50,510 basehttp 23535 6235336704 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-07 15:03:50,511 basehttp 23535 6201683968 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-07 15:03:50,512 basehttp 23535 6268989440 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-07 15:03:50,512 basehttp 23535 6285815808 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-07 15:03:50,514 basehttp 23535 6201683968 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-07 15:03:50,514 basehttp 23535 6218510336 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-07 15:03:50,515 basehttp 23535 6268989440 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-07 15:03:50,515 basehttp 23535 6285815808 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-07 15:03:50,517 basehttp 23535 6268989440 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-07 15:03:50,518 basehttp 23535 6218510336 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-07 15:03:50,518 basehttp 23535 6285815808 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-07 15:03:50,518 basehttp 23535 6252163072 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-07 15:03:50,518 basehttp 23535 6201683968 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-07 15:03:50,520 basehttp 23535 6285815808 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-07 15:03:50,521 basehttp 23535 6252163072 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-07 15:03:50,522 basehttp 23535 6201683968 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-07 15:03:50,523 basehttp 23535 6235336704 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-07 15:03:50,523 basehttp 23535 6268989440 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-07 15:03:50,523 basehttp 23535 6218510336 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-07 15:03:50,523 basehttp 23535 6285815808 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-07 15:03:50,524 basehttp 23535 6252163072 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-07 15:03:50,524 basehttp 23535 6201683968 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-07 15:03:50,538 basehttp 23535 6201683968 "GET /static/plugins/chart.js/dist/chart.umd.js.map HTTP/1.1" 200 958364 +INFO 2025-09-07 15:03:50,548 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:03:50,569 basehttp 23535 6201683968 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:03:50,625 log 23535 6285815808 Not Found: /favicon.ico +WARNING 2025-09-07 15:03:50,625 basehttp 23535 6285815808 "GET /favicon.ico HTTP/1.1" 404 2557 +WARNING 2025-09-07 15:03:59,502 basehttp 23535 6285815808 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:04:07,948 basehttp 23535 6252163072 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:04:15,855 basehttp 23535 6268989440 "GET /en/hr/employees/27/ HTTP/1.1" 200 34730 +WARNING 2025-09-07 15:04:15,880 log 23535 6268989440 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:04:15,880 basehttp 23535 6268989440 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:04:15,943 basehttp 23535 6268989440 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:04:22,166 log 23535 6268989440 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:04:22,166 basehttp 23535 6268989440 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:04:22,204 log 23535 6268989440 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:04:22,204 basehttp 23535 6268989440 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:04:50,563 basehttp 23535 6268989440 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:05:15,546 basehttp 23535 6268989440 "GET /en/hr/schedules/21/ HTTP/1.1" 200 173472 +WARNING 2025-09-07 15:05:15,555 basehttp 23535 6268989440 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:05:15,567 basehttp 23535 6218510336 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:05:15,571 log 23535 6235336704 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:05:15,571 basehttp 23535 6235336704 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:05:15,643 basehttp 23535 6235336704 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:05:15,665 basehttp 23535 6235336704 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:05:44,464 basehttp 23535 6201683968 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:06:02,782 basehttp 23535 6201683968 "GET /en/hr/schedules/?page=2 HTTP/1.1" 200 123257 +INFO 2025-09-07 15:06:02,791 basehttp 23535 6201683968 "GET /static/plugins/moment/min/moment.min.js HTTP/1.1" 200 58890 +WARNING 2025-09-07 15:06:02,812 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:02,812 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:06:02,819 basehttp 23535 6201683968 "GET /static/plugins/moment/min/moment.min.js.map HTTP/1.1" 200 98730 +INFO 2025-09-07 15:06:18,524 basehttp 23535 6201683968 "GET /en/hr/schedules/ HTTP/1.1" 200 122042 +WARNING 2025-09-07 15:06:18,548 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:18,548 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:06:18,986 basehttp 23535 6201683968 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 15:06:19,008 log 23535 6201683968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:19,008 basehttp 23535 6201683968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:06:21,734 basehttp 23535 6201683968 "GET /en/hr/departments/ HTTP/1.1" 200 125426 +INFO 2025-09-07 15:06:21,750 basehttp 23535 6201683968 "GET /static/plugins/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css HTTP/1.1" 200 8136 +INFO 2025-09-07 15:06:21,750 basehttp 23535 6252163072 "GET /static/plugins/datatables.net-buttons-bs5/js/buttons.bootstrap5.min.js HTTP/1.1" 200 1627 +INFO 2025-09-07 15:06:21,751 basehttp 23535 6218510336 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +INFO 2025-09-07 15:06:21,751 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-buttons/js/dataTables.buttons.min.js HTTP/1.1" 200 27926 +WARNING 2025-09-07 15:06:21,755 log 23535 6268989440 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:21,756 basehttp 23535 6268989440 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:06:21,758 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-buttons/js/buttons.print.min.js HTTP/1.1" 200 3073 +INFO 2025-09-07 15:06:21,758 basehttp 23535 6218510336 "GET /static/plugins/datatables.net-buttons/js/buttons.html5.min.js HTTP/1.1" 200 26043 +INFO 2025-09-07 15:06:21,760 basehttp 23535 6201683968 "GET /static/plugins/jszip/dist/jszip.min.js HTTP/1.1" 200 97630 +INFO 2025-09-07 15:06:21,763 basehttp 23535 6268989440 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +INFO 2025-09-07 15:06:21,768 basehttp 23535 6285815808 "GET /static/plugins/pdfmake/build/vfs_fonts.js HTTP/1.1" 200 828866 +INFO 2025-09-07 15:06:21,769 basehttp 23535 6252163072 "GET /static/plugins/pdfmake/build/pdfmake.min.js HTTP/1.1" 200 1400771 +INFO 2025-09-07 15:06:21,851 basehttp 23535 6252163072 "GET /static/plugins/pdfmake/build/pdfmake.min.js.map HTTP/1.1" 200 4214503 +INFO 2025-09-07 15:06:21,853 basehttp 23535 6285815808 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:06:24,044 log 23535 6285815808 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:24,044 basehttp 23535 6285815808 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:06:24,058 log 23535 6285815808 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:24,058 basehttp 23535 6285815808 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 15:06:25,465 log 23535 6285815808 Internal Server Error: /en/hr/time-entries/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'export_time_entries' not found. 'export_time_entries' is not a valid view function or pattern name. +ERROR 2025-09-07 15:06:25,466 basehttp 23535 6285815808 "GET /en/hr/time-entries/ HTTP/1.1" 500 202728 +WARNING 2025-09-07 15:06:25,492 log 23535 6285815808 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:06:25,492 basehttp 23535 6285815808 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:07:32,068 basehttp 23535 6285815808 "GET /en/hr/time-entries/ HTTP/1.1" 200 143885 +WARNING 2025-09-07 15:07:32,077 basehttp 23535 6268989440 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:32,078 basehttp 23535 6252163072 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.css HTTP/1.1" 200 8069 +INFO 2025-09-07 15:07:32,079 basehttp 23535 6201683968 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.js HTTP/1.1" 200 67842 +WARNING 2025-09-07 15:07:32,081 log 23535 6285815808 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:07:32,081 basehttp 23535 6285815808 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:07:32,106 basehttp 23535 6285815808 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:32,138 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:07:32,182 basehttp 23535 6201683968 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:50,766 basehttp 23535 6252163072 "GET /en/hr/time-entries/ HTTP/1.1" 200 143725 +WARNING 2025-09-07 15:07:50,774 basehttp 23535 6252163072 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:50,775 basehttp 23535 6218510336 "GET /static/img/user/user-1.jpg HTTP/1.1" 200 3528 +WARNING 2025-09-07 15:07:50,780 log 23535 6235336704 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:07:50,780 basehttp 23535 6235336704 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:07:50,837 basehttp 23535 6235336704 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:07:50,870 basehttp 23535 6235336704 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:52,889 basehttp 23535 6218510336 "GET /en/hr/time-entries/ HTTP/1.1" 200 143725 +INFO 2025-09-07 15:07:52,899 basehttp 23535 6235336704 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-07 15:07:52,899 basehttp 23535 6252163072 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-07 15:07:52,900 basehttp 23535 6268989440 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-07 15:07:52,902 basehttp 23535 6285815808 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.css HTTP/1.1" 200 8069 +INFO 2025-09-07 15:07:52,904 basehttp 23535 6268989440 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +WARNING 2025-09-07 15:07:52,906 basehttp 23535 6285815808 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:52,908 basehttp 23535 6218510336 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-07 15:07:52,909 basehttp 23535 6235336704 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-07 15:07:52,911 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +WARNING 2025-09-07 15:07:52,913 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:07:52,913 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:07:52,915 basehttp 23535 6235336704 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-07 15:07:52,916 basehttp 23535 6285815808 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-07 15:07:52,917 basehttp 23535 6252163072 - Broken pipe from ('127.0.0.1', 58254) +INFO 2025-09-07 15:07:52,918 basehttp 23535 6218510336 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-07 15:07:52,919 basehttp 23535 6302642176 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-07 15:07:52,922 basehttp 23535 6302642176 "GET /static/img/user/user-1.jpg HTTP/1.1" 200 3528 +INFO 2025-09-07 15:07:52,922 basehttp 23535 6235336704 "GET /static/plugins/moment/min/moment.min.js HTTP/1.1" 200 58890 +INFO 2025-09-07 15:07:52,922 basehttp 23535 6285815808 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.js HTTP/1.1" 200 67842 +INFO 2025-09-07 15:07:52,923 basehttp 23535 6218510336 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +INFO 2025-09-07 15:07:52,928 basehttp 23535 6201683968 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-07 15:07:52,929 basehttp 23535 6268989440 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +WARNING 2025-09-07 15:07:53,743 basehttp 23535 6268989440 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:07:53,773 basehttp 23535 6285815808 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-07 15:07:53,773 basehttp 23535 6201683968 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-07 15:07:53,773 basehttp 23535 6302642176 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-07 15:07:53,774 basehttp 23535 6235336704 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-07 15:07:53,774 basehttp 23535 6218510336 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-07 15:07:53,777 basehttp 23535 6235336704 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-07 15:07:53,778 basehttp 23535 6252163072 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-07 15:07:53,778 basehttp 23535 6218510336 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-07 15:07:53,778 basehttp 23535 6302642176 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-07 15:07:53,779 basehttp 23535 6201683968 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-07 15:07:53,781 basehttp 23535 6235336704 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-07 15:07:53,781 basehttp 23535 6252163072 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-07 15:07:53,782 basehttp 23535 6302642176 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-07 15:07:53,782 basehttp 23535 6218510336 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-07 15:07:53,782 basehttp 23535 6201683968 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-07 15:07:53,782 basehttp 23535 6285815808 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-07 15:07:53,785 basehttp 23535 6201683968 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-07 15:07:53,785 basehttp 23535 6235336704 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-07 15:07:53,785 basehttp 23535 6218510336 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-07 15:07:53,785 basehttp 23535 6302642176 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-07 15:07:53,785 basehttp 23535 6252163072 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-07 15:07:53,786 basehttp 23535 6285815808 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-07 15:07:53,786 basehttp 23535 6201683968 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-07 15:07:53,796 basehttp 23535 6201683968 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-07 15:07:53,806 basehttp 23535 6201683968 "GET /static/plugins/moment/min/moment.min.js.map HTTP/1.1" 200 98730 +INFO 2025-09-07 15:07:53,819 basehttp 23535 6201683968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:07:53,855 basehttp 23535 6201683968 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:07:54,101 log 23535 6302642176 Not Found: /favicon.ico +WARNING 2025-09-07 15:07:54,101 basehttp 23535 6302642176 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-07 15:08:41,055 basehttp 23535 6302642176 "GET /en/hr/time-entries/ HTTP/1.1" 200 138936 +WARNING 2025-09-07 15:08:41,068 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:08:41,068 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:08:41,164 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:08:54,359 basehttp 23535 6302642176 "GET /en/hr/time-entries/ HTTP/1.1" 200 138956 +INFO 2025-09-07 15:08:54,366 basehttp 23535 6302642176 "GET /static/img/user/user-10.jpg HTTP/1.1" 200 6490 +WARNING 2025-09-07 15:08:54,374 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:08:54,374 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:08:54,431 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:09:16,424 basehttp 23535 6302642176 "GET /en/hr/time-entries/ HTTP/1.1" 200 137743 +WARNING 2025-09-07 15:09:16,439 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:09:16,439 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:09:16,498 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:09:31,143 basehttp 23535 6302642176 "GET /en/hr/time-entries/ HTTP/1.1" 200 137863 +WARNING 2025-09-07 15:09:31,156 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:09:31,156 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:09:31,207 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:10:03,173 basehttp 23535 6302642176 "GET /en/hr/time-entries/ HTTP/1.1" 200 138243 +WARNING 2025-09-07 15:10:03,188 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:10:03,188 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:10:03,237 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:10:43,104 basehttp 23535 6302642176 "GET /en/hr/time-entries/ HTTP/1.1" 200 137710 +WARNING 2025-09-07 15:10:43,121 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:10:43,121 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:10:43,175 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:10:47,796 basehttp 23535 6302642176 "GET /en/hr/time-entries/45/ HTTP/1.1" 200 32196 +WARNING 2025-09-07 15:10:47,807 basehttp 23535 6285815808 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:10:47,812 log 23535 6302642176 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:10:47,812 basehttp 23535 6302642176 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:10:47,857 basehttp 23535 6302642176 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:11:17,487 basehttp 23535 6302642176 "GET /en/hr/time-entries/45/ HTTP/1.1" 200 32165 +WARNING 2025-09-07 15:11:17,500 basehttp 23535 6302642176 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:11:17,508 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:11:17,508 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:11:17,554 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:11:37,340 basehttp 23535 6252163072 "GET /en/hr/time-entries/45/ HTTP/1.1" 200 32158 +WARNING 2025-09-07 15:11:37,359 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:11:37,359 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:11:37,404 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:11:41,289 basehttp 23535 6252163072 "GET /en/hr/employees/2/ HTTP/1.1" 200 34735 +WARNING 2025-09-07 15:11:41,309 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:11:41,309 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:11:41,351 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:11:43,657 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:11:43,657 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:11:43,668 log 23535 6252163072 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:11:43,668 basehttp 23535 6252163072 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:12:25,801 basehttp 23535 6252163072 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:12:25,802 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:12:25,802 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:12:25,816 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:12:25,817 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:12:27,914 basehttp 23535 6218510336 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 15:12:27,929 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:12:27,929 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:12:30,289 basehttp 23535 6218510336 "GET /en/hr/employees/ HTTP/1.1" 200 130495 +WARNING 2025-09-07 15:12:30,308 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:12:30,308 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:12:30,330 basehttp 23535 6218510336 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 15:12:32,887 log 23535 6218510336 Internal Server Error: /en/hr/employees/56/delete/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'employee_deactivate' not found. 'employee_deactivate' is not a valid view function or pattern name. +ERROR 2025-09-07 15:12:32,888 basehttp 23535 6218510336 "GET /en/hr/employees/56/delete/ HTTP/1.1" 500 174783 +WARNING 2025-09-07 15:12:32,907 log 23535 6218510336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:12:32,907 basehttp 23535 6218510336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:14:32,943 autoreload 23535 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:14:33,479 autoreload 36795 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:14:34,155 basehttp 36795 6341865472 "GET /en/hr/employees/56/delete/ HTTP/1.1" 200 34468 +WARNING 2025-09-07 15:14:34,174 log 36795 6341865472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:14:34,174 basehttp 36795 6341865472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:14:34,222 basehttp 36795 6341865472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:15:01,587 basehttp 36795 6341865472 "GET /en/hr/employees/56/ HTTP/1.1" 200 34482 +WARNING 2025-09-07 15:15:01,601 log 36795 6341865472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:15:01,601 basehttp 36795 6341865472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:15:01,638 basehttp 36795 6341865472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:15:43,738 log 36795 6358691840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:15:43,739 basehttp 36795 6358691840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:15:43,741 basehttp 36795 6341865472 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:15:43,746 log 36795 6358691840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:15:43,746 basehttp 36795 6358691840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:15:50,386 basehttp 36795 6358691840 "GET /en/hr/employees/ HTTP/1.1" 200 130495 +WARNING 2025-09-07 15:15:50,398 log 36795 6358691840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:15:50,398 basehttp 36795 6358691840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:15:50,444 basehttp 36795 6358691840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:16:18,096 log 36795 6358691840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:18,097 basehttp 36795 6358691840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:16:18,109 log 36795 6358691840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:18,109 basehttp 36795 6358691840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:16:20,480 basehttp 36795 6358691840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:16:20,481 log 36795 6341865472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:20,481 basehttp 36795 6341865472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:16:20,490 log 36795 6341865472 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:20,490 basehttp 36795 6341865472 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:16:22,038 basehttp 36795 6341865472 "GET / HTTP/1.1" 302 0 +INFO 2025-09-07 15:16:22,063 basehttp 36795 6358691840 "GET /en/ HTTP/1.1" 200 49810 +WARNING 2025-09-07 15:16:22,083 log 36795 6358691840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:22,083 basehttp 36795 6358691840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:16:22,161 basehttp 36795 6358691840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:16:22,164 basehttp 36795 6392344576 "GET /en/htmx/tenant-info/ HTTP/1.1" 200 1043 +INFO 2025-09-07 15:16:22,165 basehttp 36795 6375518208 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +INFO 2025-09-07 15:16:22,168 basehttp 36795 6341865472 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +INFO 2025-09-07 15:16:30,883 basehttp 36795 6341865472 "GET /en/hr HTTP/1.1" 301 0 +INFO 2025-09-07 15:16:30,921 basehttp 36795 6375518208 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 15:16:30,938 log 36795 6375518208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:30,938 basehttp 36795 6375518208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:16:30,956 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 15:16:39,629 log 36795 6375518208 Internal Server Error: /en/hr/reviews/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'export_performance_reviews' not found. 'export_performance_reviews' is not a valid view function or pattern name. +ERROR 2025-09-07 15:16:39,630 basehttp 36795 6375518208 "GET /en/hr/reviews/ HTTP/1.1" 500 213690 +WARNING 2025-09-07 15:16:39,650 log 36795 6375518208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:16:39,650 basehttp 36795 6375518208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:17:34,224 basehttp 36795 6375518208 "GET /en/hr/reviews/ HTTP/1.1" 200 37449 +WARNING 2025-09-07 15:17:34,238 log 36795 6375518208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:17:34,239 basehttp 36795 6375518208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:17:34,285 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:18:34,298 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:19:34,301 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:19:34,844 basehttp 36795 6375518208 "GET /en/hr/reviews/ HTTP/1.1" 200 37356 +WARNING 2025-09-07 15:19:34,863 log 36795 6375518208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:19:34,863 basehttp 36795 6375518208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:19:34,913 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:20:00,885 basehttp 36795 6375518208 "GET /en/hr/reviews/ HTTP/1.1" 200 37346 +WARNING 2025-09-07 15:20:00,902 log 36795 6375518208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:20:00,902 basehttp 36795 6375518208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:20:00,951 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:20:15,335 basehttp 36795 6375518208 "GET /en/hr/reviews/ HTTP/1.1" 200 37343 +WARNING 2025-09-07 15:20:15,355 log 36795 6375518208 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:20:15,355 basehttp 36795 6375518208 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:20:15,406 basehttp 36795 6375518208 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:20:18,213 basehttp 36795 6375518208 "GET /en/hr/reviews/ HTTP/1.1" 200 37343 +INFO 2025-09-07 15:20:18,226 basehttp 36795 6425997312 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.css HTTP/1.1" 200 8069 +INFO 2025-09-07 15:20:18,227 basehttp 36795 6409170944 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +INFO 2025-09-07 15:20:18,227 basehttp 36795 6358691840 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-07 15:20:18,228 basehttp 36795 6341865472 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-07 15:20:18,230 basehttp 36795 6425997312 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-07 15:20:18,232 basehttp 36795 6375518208 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +WARNING 2025-09-07 15:20:18,234 log 36795 6409170944 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-07 15:20:18,235 basehttp 36795 6392344576 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +WARNING 2025-09-07 15:20:18,237 basehttp 36795 6409170944 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:20:18,419 basehttp 36795 6392344576 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-07 15:20:18,422 basehttp 36795 6392344576 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-07 15:20:18,425 basehttp 36795 6409170944 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-07 15:20:18,427 basehttp 36795 6409170944 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-07 15:20:18,429 basehttp 36795 6409170944 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-07 15:20:18,430 basehttp 36795 6392344576 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-07 15:20:18,430 basehttp 36795 6409170944 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-07 15:20:18,432 basehttp 36795 6392344576 "GET /static/plugins/moment/min/moment.min.js HTTP/1.1" 200 58890 +INFO 2025-09-07 15:20:18,432 basehttp 36795 6409170944 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.js HTTP/1.1" 200 67842 +INFO 2025-09-07 15:20:18,435 basehttp 36795 6392344576 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +INFO 2025-09-07 15:20:19,239 basehttp 36795 6409170944 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-07 15:20:19,239 basehttp 36795 6341865472 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-07 15:20:19,239 basehttp 36795 6392344576 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-07 15:20:19,239 basehttp 36795 6375518208 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-07 15:20:19,239 basehttp 36795 6425997312 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-07 15:20:19,243 basehttp 36795 6358691840 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-07 15:20:19,243 basehttp 36795 6409170944 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-07 15:20:19,244 basehttp 36795 6341865472 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-07 15:20:19,245 basehttp 36795 6392344576 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-07 15:20:19,245 basehttp 36795 6341865472 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-07 15:20:19,245 basehttp 36795 6375518208 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-07 15:20:19,246 basehttp 36795 6358691840 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-07 15:20:19,246 basehttp 36795 6425997312 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-07 15:20:19,247 basehttp 36795 6409170944 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-07 15:20:19,248 basehttp 36795 6392344576 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-07 15:20:19,249 basehttp 36795 6358691840 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-07 15:20:19,249 basehttp 36795 6375518208 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-07 15:20:19,250 basehttp 36795 6341865472 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-07 15:20:19,250 basehttp 36795 6409170944 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-07 15:20:19,250 basehttp 36795 6425997312 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-07 15:20:19,252 basehttp 36795 6341865472 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-07 15:20:19,252 basehttp 36795 6375518208 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-07 15:20:19,254 basehttp 36795 6392344576 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-07 15:20:19,261 basehttp 36795 6409170944 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-07 15:20:19,295 basehttp 36795 6409170944 "GET /static/plugins/moment/min/moment.min.js.map HTTP/1.1" 200 98730 +INFO 2025-09-07 15:20:19,307 basehttp 36795 6409170944 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:20:19,537 log 36795 6409170944 Not Found: /favicon.ico +WARNING 2025-09-07 15:20:19,537 basehttp 36795 6409170944 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-07 15:20:32,844 basehttp 36795 6409170944 "GET /en/admin/hr/performancereview/ HTTP/1.1" 200 139984 +INFO 2025-09-07 15:20:32,855 basehttp 36795 6392344576 "GET /static/admin/css/dark_mode.css HTTP/1.1" 200 2808 +INFO 2025-09-07 15:20:32,856 basehttp 36795 6341865472 "GET /static/admin/css/nav_sidebar.css HTTP/1.1" 200 2810 +INFO 2025-09-07 15:20:32,856 basehttp 36795 6375518208 "GET /static/admin/js/theme.js HTTP/1.1" 200 1653 +INFO 2025-09-07 15:20:32,856 basehttp 36795 6409170944 "GET /static/admin/css/base.css HTTP/1.1" 200 22120 +INFO 2025-09-07 15:20:32,857 basehttp 36795 6425997312 "GET /static/admin/css/changelists.css HTTP/1.1" 200 6878 +INFO 2025-09-07 15:20:32,859 basehttp 36795 6375518208 "GET /static/admin/js/jquery.init.js HTTP/1.1" 200 347 +INFO 2025-09-07 15:20:32,860 basehttp 36795 6392344576 "GET /static/admin/css/responsive.css HTTP/1.1" 200 16565 +INFO 2025-09-07 15:20:32,860 basehttp 36795 6409170944 "GET /static/admin/js/core.js HTTP/1.1" 200 6208 +INFO 2025-09-07 15:20:32,860 basehttp 36795 6425997312 "GET /static/admin/js/admin/RelatedObjectLookups.js HTTP/1.1" 200 9777 +INFO 2025-09-07 15:20:32,863 basehttp 36795 6375518208 "GET /static/admin/js/actions.js HTTP/1.1" 200 8076 +INFO 2025-09-07 15:20:32,863 basehttp 36795 6409170944 "GET /static/admin/js/urlify.js HTTP/1.1" 200 7887 +INFO 2025-09-07 15:20:32,863 basehttp 36795 6392344576 "GET /static/admin/js/prepopulate.js HTTP/1.1" 200 1531 +INFO 2025-09-07 15:20:32,866 basehttp 36795 6341865472 "GET /static/admin/js/vendor/jquery/jquery.js HTTP/1.1" 200 285314 +INFO 2025-09-07 15:20:32,867 basehttp 36795 6392344576 "GET /static/admin/img/search.svg HTTP/1.1" 200 458 +INFO 2025-09-07 15:20:32,867 basehttp 36795 6358691840 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-07 15:20:32,868 basehttp 36795 6358691840 "GET /static/admin/js/nav_sidebar.js HTTP/1.1" 200 3063 +INFO 2025-09-07 15:20:32,869 basehttp 36795 6425997312 "GET /static/admin/js/vendor/xregexp/xregexp.js HTTP/1.1" 200 325171 +INFO 2025-09-07 15:20:32,872 basehttp 36795 6425997312 "GET /static/admin/js/filters.js HTTP/1.1" 200 978 +INFO 2025-09-07 15:20:32,881 basehttp 36795 6425997312 "GET /static/admin/img/icon-addlink.svg HTTP/1.1" 200 331 +INFO 2025-09-07 15:20:32,881 basehttp 36795 6358691840 "GET /static/admin/img/tooltag-add.svg HTTP/1.1" 200 331 +INFO 2025-09-07 15:20:32,881 basehttp 36795 6392344576 "GET /static/admin/img/sorting-icons.svg HTTP/1.1" 200 1097 +INFO 2025-09-07 15:20:32,882 basehttp 36795 6392344576 "GET /static/admin/img/icon-viewlink.svg HTTP/1.1" 200 581 +INFO 2025-09-07 15:21:19,323 basehttp 36795 6392344576 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:21:56,623 autoreload 36795 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:21:57,093 autoreload 40099 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:21:57,588 basehttp 40099 6170996736 "GET /en/hr/reviews/ HTTP/1.1" 200 87097 +WARNING 2025-09-07 15:21:57,604 log 40099 6170996736 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:21:57,604 basehttp 40099 6170996736 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:21:57,691 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:22:22,149 basehttp 40099 6170996736 "GET /en/hr/reviews/ HTTP/1.1" 200 149783 +WARNING 2025-09-07 15:22:22,164 log 40099 6170996736 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:22:22,164 basehttp 40099 6170996736 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:22:22,221 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:22:39,257 basehttp 40099 6170996736 "GET /en/hr/reviews/create/ HTTP/1.1" 200 51757 +INFO 2025-09-07 15:22:39,273 basehttp 40099 6187823104 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +WARNING 2025-09-07 15:22:39,275 log 40099 6170996736 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:22:39,276 basehttp 40099 6170996736 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:22:39,276 basehttp 40099 6204649472 "GET /static/plugins/summernote/dist/summernote-lite.css HTTP/1.1" 200 38212 +INFO 2025-09-07 15:22:39,277 basehttp 40099 6221475840 "GET /static/plugins/summernote/dist/summernote-lite.min.js HTTP/1.1" 200 186367 +INFO 2025-09-07 15:22:39,321 basehttp 40099 6221475840 "GET /static/webfonts/fa-regular-400.woff2 HTTP/1.1" 200 25472 +INFO 2025-09-07 15:22:39,329 basehttp 40099 6221475840 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:22:39,331 basehttp 40099 6221475840 "GET /static/plugins/summernote/dist/summernote-lite.css.map HTTP/1.1" 200 52049 +WARNING 2025-09-07 15:22:57,227 log 40099 6221475840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:22:57,227 basehttp 40099 6221475840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:22:57,261 log 40099 6221475840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:22:57,261 basehttp 40099 6221475840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:23:03,538 basehttp 40099 6221475840 "GET /en/hr/reviews/8/ HTTP/1.1" 200 35190 +WARNING 2025-09-07 15:23:03,557 basehttp 40099 6204649472 "GET /static/plugins/chart.js/dist/Chart.min.css HTTP/1.1" 404 2032 +WARNING 2025-09-07 15:23:03,558 basehttp 40099 6170996736 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +WARNING 2025-09-07 15:23:03,559 basehttp 40099 6187823104 "GET /static/plugins/chart.js/dist/Chart.min.js HTTP/1.1" 404 2029 +WARNING 2025-09-07 15:23:03,561 log 40099 6221475840 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:23:03,561 basehttp 40099 6221475840 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 15:23:03,585 basehttp 40099 6221475840 "GET /static/img/user/default-avatar.jpg HTTP/1.1" 404 2008 +INFO 2025-09-07 15:23:03,604 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:24:03,619 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:25:03,623 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:26:03,615 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:27:03,639 basehttp 40099 6170996736 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:27:19,943 autoreload 40099 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 15:27:20,378 autoreload 42495 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:28:03,695 basehttp 42495 6169866240 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:29:03,630 basehttp 42495 6169866240 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:29:15,762 autoreload 42495 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 15:29:16,265 autoreload 43350 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:30:03,693 basehttp 43350 6196097024 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:31:03,637 basehttp 43350 6196097024 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:31:56,553 autoreload 43350 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:31:56,912 autoreload 44551 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:32:03,696 basehttp 44551 6164459520 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:33:03,629 basehttp 44551 6164459520 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:34:03,634 basehttp 44551 6164459520 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:35:03,646 basehttp 44551 6164459520 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:36:03,647 basehttp 44551 6164459520 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:37:03,650 basehttp 44551 6164459520 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 15:37:37,753 log 44551 6164459520 Internal Server Error: /en/hr/reviews/8/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 112, in get + self.object = self.get_object() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py", line 712, in get_object + return get_object_or_404(queryset, pk=self.kwargs.get(self.pk_url_kwarg, self.kwargs.get('pk'))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/shortcuts.py", line 90, in get_object_or_404 + return queryset.get(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 629, in get + num = len(clone) + ^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1949, in _fetch_all + self._result_cache = list(self._iterable_class(self)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 91, in __iter__ + results = compiler.execute_sql( + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1610, in execute_sql + sql, params = self.as_sql() + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 766, in as_sql + extra_select, order_by, group_by = self.pre_sql_setup( + ^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 85, in pre_sql_setup + self.setup_query(with_col_aliases=with_col_aliases) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 74, in setup_query + self.select, self.klass_info, self.annotation_col_map = self.get_select( + ^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 299, in get_select + related_klass_infos = self.get_related_selections(select, select_mask) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1265, in get_related_selections + next_klass_infos = self.get_related_selections( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1396, in get_related_selections + raise FieldError( +django.core.exceptions.FieldError: Invalid field name(s) given in select_related: 'manager'. Choices are: tenant, user, department, supervisor, created_by +ERROR 2025-09-07 15:37:37,756 basehttp 44551 6164459520 "GET /en/hr/reviews/8/ HTTP/1.1" 500 173140 +WARNING 2025-09-07 15:37:37,772 log 44551 6164459520 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:37:37,772 basehttp 44551 6164459520 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:38:15,889 autoreload 44551 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:38:16,260 autoreload 47337 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 15:38:16,841 log 47337 6194507776 Internal Server Error: /en/hr/reviews/8/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 112, in get + self.object = self.get_object() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py", line 712, in get_object + return get_object_or_404(queryset, pk=self.kwargs.get(self.pk_url_kwarg, self.kwargs.get('pk'))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/shortcuts.py", line 90, in get_object_or_404 + return queryset.get(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 629, in get + num = len(clone) + ^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1949, in _fetch_all + self._result_cache = list(self._iterable_class(self)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 91, in __iter__ + results = compiler.execute_sql( + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1610, in execute_sql + sql, params = self.as_sql() + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 766, in as_sql + extra_select, order_by, group_by = self.pre_sql_setup( + ^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 85, in pre_sql_setup + self.setup_query(with_col_aliases=with_col_aliases) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 74, in setup_query + self.select, self.klass_info, self.annotation_col_map = self.get_select( + ^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 299, in get_select + related_klass_infos = self.get_related_selections(select, select_mask) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1396, in get_related_selections + raise FieldError( +django.core.exceptions.FieldError: Invalid field name(s) given in select_related: 'created_by'. Choices are: employee, reviewer +ERROR 2025-09-07 15:38:16,843 basehttp 47337 6194507776 "GET /en/hr/reviews/8/ HTTP/1.1" 500 161070 +WARNING 2025-09-07 15:38:16,859 log 47337 6194507776 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:38:16,859 basehttp 47337 6194507776 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:38:38,194 autoreload 47337 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:38:38,527 autoreload 47502 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 15:38:38,784 log 47502 6138064896 Internal Server Error: /en/hr/reviews/8/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 112, in get + self.object = self.get_object() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py", line 712, in get_object + return get_object_or_404(queryset, pk=self.kwargs.get(self.pk_url_kwarg, self.kwargs.get('pk'))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/shortcuts.py", line 90, in get_object_or_404 + return queryset.get(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 629, in get + num = len(clone) + ^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1951, in _fetch_all + self._prefetch_related_objects() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1328, in _prefetch_related_objects + prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 2372, in prefetch_related_objects + raise AttributeError( +AttributeError: Cannot find 'categories' on PerformanceReview object, 'categories' is an invalid parameter to prefetch_related() +ERROR 2025-09-07 15:38:38,785 basehttp 47502 6138064896 "GET /en/hr/reviews/8/ HTTP/1.1" 500 113875 +WARNING 2025-09-07 15:38:38,798 log 47502 6138064896 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:38:38,798 basehttp 47502 6138064896 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:38:51,266 autoreload 47502 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:38:51,619 autoreload 47588 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:39:40,551 autoreload 47588 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:39:40,898 autoreload 47977 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 15:39:41,445 log 47977 6199848960 Internal Server Error: /en/hr/reviews/8/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 112, in get + self.object = self.get_object() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py", line 712, in get_object + return get_object_or_404(queryset, pk=self.kwargs.get(self.pk_url_kwarg, self.kwargs.get('pk'))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/shortcuts.py", line 90, in get_object_or_404 + return queryset.get(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 629, in get + num = len(clone) + ^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1951, in _fetch_all + self._prefetch_related_objects() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1328, in _prefetch_related_objects + prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 2386, in prefetch_related_objects + raise ValueError( +ValueError: 'review_type' does not resolve to an item that supports prefetching - this is an invalid parameter to prefetch_related(). +ERROR 2025-09-07 15:39:41,447 basehttp 47977 6199848960 "GET /en/hr/reviews/8/ HTTP/1.1" 500 113884 +WARNING 2025-09-07 15:39:41,458 log 47977 6199848960 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:39:41,458 basehttp 47977 6199848960 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:40:35,131 autoreload 47977 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:40:35,503 autoreload 48369 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 15:40:36,071 log 48369 6163918848 Internal Server Error: /en/hr/reviews/8/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 112, in get + self.object = self.get_object() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py", line 712, in get_object + return get_object_or_404(queryset, pk=self.kwargs.get(self.pk_url_kwarg, self.kwargs.get('pk'))) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/shortcuts.py", line 90, in get_object_or_404 + return queryset.get(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 629, in get + num = len(clone) + ^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1951, in _fetch_all + self._prefetch_related_objects() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1328, in _prefetch_related_objects + prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 2372, in prefetch_related_objects + raise AttributeError( +AttributeError: Cannot find 'goals' on PerformanceReview object, 'goals' is an invalid parameter to prefetch_related() +ERROR 2025-09-07 15:40:36,072 basehttp 48369 6163918848 "GET /en/hr/reviews/8/ HTTP/1.1" 500 113687 +WARNING 2025-09-07 15:40:36,088 log 48369 6163918848 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:40:36,088 basehttp 48369 6163918848 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:40:44,031 autoreload 48369 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:40:44,357 autoreload 48481 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 15:40:44,695 log 48481 6130069504 Internal Server Error: /en/hr/reviews/8/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch + return super().dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 144, in dispatch + return handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/views/generic/detail.py", line 113, in get + context = self.get_context_data(object=self.object) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py", line 780, in get_context_data + .order_by('-period_end')[:5] + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1722, in order_by + obj.query.add_ordering(*field_names) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/query.py", line 2291, in add_ordering + self.names_to_path(item.split(LOOKUP_SEP), self.model._meta) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1805, in names_to_path + raise FieldError( +django.core.exceptions.FieldError: Cannot resolve keyword 'period_end' into field. Choices are: areas_for_improvement, competency_ratings, created_at, development_plan, employee, employee_comments, employee_id, employee_signature_date, future_goals, goals_achieved, goals_not_achieved, id, notes, overall_rating, review_date, review_id, review_period_end, review_period_start, review_type, reviewer, reviewer_id, status, strengths, training_recommendations, updated_at +ERROR 2025-09-07 15:40:44,696 basehttp 48481 6130069504 "GET /en/hr/reviews/8/ HTTP/1.1" 500 104264 +WARNING 2025-09-07 15:40:44,707 log 48481 6130069504 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:40:44,707 basehttp 48481 6130069504 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:41:18,911 autoreload 48481 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:41:19,236 autoreload 48721 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:41:20,478 basehttp 48721 6122270720 "GET /en/hr/reviews/8/ HTTP/1.1" 200 35458 +WARNING 2025-09-07 15:41:20,492 log 48721 6122270720 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:41:20,492 basehttp 48721 6122270720 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:41:20,493 basehttp 48721 6139097088 "GET /static/plugins/chart.js/dist/chart.umd.js HTTP/1.1" 200 206279 +INFO 2025-09-07 15:41:20,573 basehttp 48721 6122270720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:41:20,574 basehttp 48721 6139097088 "GET /static/plugins/chart.js/dist/chart.umd.js.map HTTP/1.1" 200 958364 +INFO 2025-09-07 15:42:20,568 basehttp 48721 6139097088 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:43:20,570 basehttp 48721 6139097088 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:44:03,623 autoreload 48721 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 15:44:03,983 autoreload 49957 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 15:44:20,650 basehttp 49957 6130266112 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:44:49,174 basehttp 49957 6130266112 "GET /en/hr/reviews/8/ HTTP/1.1" 200 47214 +WARNING 2025-09-07 15:44:49,195 log 49957 6130266112 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:44:49,195 basehttp 49957 6130266112 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 15:44:49,262 basehttp 49957 6130266112 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 15:45:49,267 basehttp 49957 6130266112 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 15:46:24,712 log 49957 6130266112 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:46:24,712 basehttp 49957 6130266112 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 15:46:29,157 log 49957 6130266112 Internal Server Error: /en/hr/reviews/55/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'complete_performance_review' not found. 'complete_performance_review' is not a valid view function or pattern name. +ERROR 2025-09-07 15:46:29,159 basehttp 49957 6130266112 "GET /en/hr/reviews/55/ HTTP/1.1" 500 212138 +WARNING 2025-09-07 15:46:29,174 log 49957 6130266112 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 15:46:29,174 basehttp 49957 6130266112 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:03:50,066 autoreload 49957 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 16:03:50,557 autoreload 58605 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 16:05:14,742 autoreload 58605 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/urls.py changed, reloading. +INFO 2025-09-07 16:05:15,058 autoreload 59264 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 16:05:15,422 basehttp 59264 6191017984 "GET /en/hr/reviews/55/ HTTP/1.1" 200 47768 +WARNING 2025-09-07 16:05:15,435 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:05:15,435 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:05:15,496 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:06:15,511 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:07:15,498 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:07:47,624 basehttp 59264 6191017984 "GET /en/hr/reviews/55/ HTTP/1.1" 200 48316 +WARNING 2025-09-07 16:07:47,639 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:07:47,639 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:07:47,693 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:08:32,659 basehttp 59264 6191017984 "GET /en/hr/reviews/55/ HTTP/1.1" 200 48847 +WARNING 2025-09-07 16:08:32,673 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:08:32,674 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:08:32,728 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:08:58,962 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:08:58,962 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:09:31,141 basehttp 59264 6191017984 "GET /en/hr/reviews/ HTTP/1.1" 200 149783 +INFO 2025-09-07 16:09:31,156 basehttp 59264 6258323456 "GET /static/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css HTTP/1.1" 200 15096 +INFO 2025-09-07 16:09:31,157 basehttp 59264 6224670720 "GET /static/css/custom.css HTTP/1.1" 200 2063 +INFO 2025-09-07 16:09:31,157 basehttp 59264 6275149824 "GET /static/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css HTTP/1.1" 200 6044 +WARNING 2025-09-07 16:09:31,161 log 59264 6241497088 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-07 16:09:31,161 basehttp 59264 6258323456 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.css HTTP/1.1" 200 8069 +WARNING 2025-09-07 16:09:31,161 basehttp 59264 6241497088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:09:31,163 basehttp 59264 6191017984 "GET /static/css/vendor.min.css HTTP/1.1" 200 177466 +INFO 2025-09-07 16:09:31,164 basehttp 59264 6275149824 "GET /static/img/user/user-4.jpg HTTP/1.1" 200 5916 +INFO 2025-09-07 16:09:31,166 basehttp 59264 6224670720 "GET /static/js/htmx.min.js HTTP/1.1" 200 50917 +INFO 2025-09-07 16:09:31,168 basehttp 59264 6275149824 "GET /static/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js HTTP/1.1" 200 1470 +INFO 2025-09-07 16:09:31,170 basehttp 59264 6207844352 "GET /static/css/default/app.min.css HTTP/1.1" 200 893480 +INFO 2025-09-07 16:09:31,171 basehttp 59264 6275149824 "GET /static/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js HTTP/1.1" 200 1796 +INFO 2025-09-07 16:09:31,172 basehttp 59264 6258323456 "GET /static/js/app.min.js HTTP/1.1" 200 110394 +INFO 2025-09-07 16:09:31,173 basehttp 59264 6191017984 "GET /static/plugins/datatables.net/js/dataTables.min.js HTTP/1.1" 200 95735 +INFO 2025-09-07 16:09:31,175 basehttp 59264 6224670720 "GET /static/plugins/datatables.net-responsive/js/dataTables.responsive.min.js HTTP/1.1" 200 16086 +INFO 2025-09-07 16:09:31,181 basehttp 59264 6241497088 "GET /static/js/vendor.min.js HTTP/1.1" 200 1091361 +INFO 2025-09-07 16:09:31,184 basehttp 59264 6275149824 "GET /static/plugins/bootstrap-daterangepicker/daterangepicker.js HTTP/1.1" 200 67842 +INFO 2025-09-07 16:09:31,186 basehttp 59264 6258323456 "GET /static/plugins/select2/dist/js/select2.min.js HTTP/1.1" 200 70851 +INFO 2025-09-07 16:09:31,188 basehttp 59264 6207844352 "GET /static/plugins/moment/min/moment.min.js HTTP/1.1" 200 58890 +INFO 2025-09-07 16:09:32,003 basehttp 59264 6207844352 "GET /static/img/theme/default.jpg HTTP/1.1" 200 26964 +INFO 2025-09-07 16:09:32,003 basehttp 59264 6241497088 "GET /static/img/theme/material.jpg HTTP/1.1" 200 28774 +INFO 2025-09-07 16:09:32,003 basehttp 59264 6224670720 "GET /static/img/theme/facebook.jpg HTTP/1.1" 200 27881 +INFO 2025-09-07 16:09:32,003 basehttp 59264 6258323456 "GET /static/img/theme/transparent.jpg HTTP/1.1" 200 32747 +INFO 2025-09-07 16:09:32,004 basehttp 59264 6275149824 "GET /static/img/theme/apple.jpg HTTP/1.1" 200 28822 +INFO 2025-09-07 16:09:32,006 basehttp 59264 6191017984 "GET /static/img/theme/google.jpg HTTP/1.1" 200 86013 +INFO 2025-09-07 16:09:32,008 basehttp 59264 6241497088 "GET /static/img/version/html.jpg HTTP/1.1" 200 17325 +INFO 2025-09-07 16:09:32,008 basehttp 59264 6258323456 "GET /static/img/version/ajax.jpg HTTP/1.1" 200 20223 +INFO 2025-09-07 16:09:32,010 basehttp 59264 6191017984 "GET /static/img/version/svelte.jpg HTTP/1.1" 200 25060 +INFO 2025-09-07 16:09:32,010 basehttp 59264 6224670720 "GET /static/img/version/angular1x.jpg HTTP/1.1" 200 22869 +INFO 2025-09-07 16:09:32,010 basehttp 59264 6275149824 "GET /static/img/version/angular10x.jpg HTTP/1.1" 200 24580 +INFO 2025-09-07 16:09:32,011 basehttp 59264 6241497088 "GET /static/img/version/django.jpg HTTP/1.1" 200 20935 +INFO 2025-09-07 16:09:32,013 basehttp 59264 6191017984 "GET /static/img/version/dotnet.jpg HTTP/1.1" 200 24791 +INFO 2025-09-07 16:09:32,013 basehttp 59264 6258323456 "GET /static/img/version/laravel.jpg HTTP/1.1" 200 26040 +INFO 2025-09-07 16:09:32,013 basehttp 59264 6224670720 "GET /static/img/version/reactjs.jpg HTTP/1.1" 200 26850 +INFO 2025-09-07 16:09:32,013 basehttp 59264 6275149824 "GET /static/img/version/vuejs.jpg HTTP/1.1" 200 22518 +INFO 2025-09-07 16:09:32,015 basehttp 59264 6207844352 "GET /static/webfonts/fa-solid-900.woff2 HTTP/1.1" 200 158220 +INFO 2025-09-07 16:09:32,016 basehttp 59264 6275149824 "GET /static/img/theme/blog.jpg HTTP/1.1" 200 32334 +INFO 2025-09-07 16:09:32,016 basehttp 59264 6241497088 "GET /static/img/version/nextjs.jpg HTTP/1.1" 200 20152 +INFO 2025-09-07 16:09:32,017 basehttp 59264 6224670720 "GET /static/img/theme/e-commerce.jpg HTTP/1.1" 200 37734 +INFO 2025-09-07 16:09:32,017 basehttp 59264 6191017984 "GET /static/img/theme/forum.jpg HTTP/1.1" 200 28744 +INFO 2025-09-07 16:09:32,017 basehttp 59264 6207844352 "GET /static/img/theme/corporate.jpg HTTP/1.1" 200 38911 +INFO 2025-09-07 16:09:32,017 basehttp 59264 6258323456 "GET /static/img/theme/one-page-parallax.jpg HTTP/1.1" 200 22474 +INFO 2025-09-07 16:09:32,030 basehttp 59264 6191017984 "GET /static/css/default/app.min.css.map HTTP/1.1" 200 1957526 +INFO 2025-09-07 16:09:32,034 basehttp 59264 6207844352 "GET /static/plugins/moment/min/moment.min.js.map HTTP/1.1" 200 98730 +INFO 2025-09-07 16:09:32,046 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:09:32,133 log 59264 6207844352 Not Found: /favicon.ico +WARNING 2025-09-07 16:09:32,133 basehttp 59264 6207844352 "GET /favicon.ico HTTP/1.1" 404 2557 +INFO 2025-09-07 16:09:44,724 basehttp 59264 6207844352 "GET /en/hr/reviews/29/ HTTP/1.1" 200 54428 +INFO 2025-09-07 16:09:44,741 basehttp 59264 6191017984 "GET /static/plugins/chart.js/dist/chart.umd.js HTTP/1.1" 200 206279 +WARNING 2025-09-07 16:09:44,745 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:09:44,745 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:09:44,805 basehttp 59264 6207844352 "GET /static/webfonts/fa-regular-400.woff2 HTTP/1.1" 200 25472 +INFO 2025-09-07 16:09:44,820 basehttp 59264 6207844352 "GET /static/plugins/chart.js/dist/chart.umd.js.map HTTP/1.1" 200 958364 +INFO 2025-09-07 16:09:44,827 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:10:14,116 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:10:14,116 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:10:14,126 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:10:14,126 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:10:17,915 basehttp 59264 6207844352 "GET /en/hr/reviews/55/ HTTP/1.1" 200 48847 +WARNING 2025-09-07 16:10:17,932 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:10:17,932 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:10:18,030 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:10:22,113 basehttp 59264 6207844352 "GET /en/hr/reviews/55/complete/ HTTP/1.1" 302 0 +INFO 2025-09-07 16:10:22,127 basehttp 59264 6207844352 "GET /en/hr/reviews/55/ HTTP/1.1" 200 48707 +WARNING 2025-09-07 16:10:22,143 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:10:22,144 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:10:22,191 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:10:39,472 basehttp 59264 6207844352 "GET /en/hr/reviews/ HTTP/1.1" 200 148767 +WARNING 2025-09-07 16:10:39,493 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:10:39,493 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:10:39,562 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:10:45,577 basehttp 59264 6207844352 "GET /en/hr/reviews/86/ HTTP/1.1" 200 54386 +WARNING 2025-09-07 16:10:45,601 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:10:45,601 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:10:45,648 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:11:06,099 basehttp 59264 6207844352 "GET /en/hr/reviews/87/ HTTP/1.1" 200 46425 +WARNING 2025-09-07 16:11:06,121 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:06,121 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:11:06,171 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:11:12,234 basehttp 59264 6207844352 "GET /en/hr/reviews/86/ HTTP/1.1" 200 54386 +WARNING 2025-09-07 16:11:12,258 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:12,258 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:11:12,312 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:11:20,964 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:20,964 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:11:20,977 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:20,977 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:11:22,229 basehttp 59264 6207844352 "GET / HTTP/1.1" 302 0 +INFO 2025-09-07 16:11:22,252 basehttp 59264 6191017984 "GET /en/ HTTP/1.1" 200 49810 +WARNING 2025-09-07 16:11:22,273 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:22,273 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:11:22,342 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:11:22,346 basehttp 59264 6224670720 "GET /en/htmx/tenant-info/ HTTP/1.1" 200 1043 +INFO 2025-09-07 16:11:22,348 basehttp 59264 6275149824 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +INFO 2025-09-07 16:11:22,350 basehttp 59264 6258323456 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +INFO 2025-09-07 16:11:25,239 basehttp 59264 6258323456 "GET /en/hr HTTP/1.1" 301 0 +INFO 2025-09-07 16:11:25,273 basehttp 59264 6275149824 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 16:11:25,294 log 59264 6275149824 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:25,294 basehttp 59264 6275149824 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:11:25,309 basehttp 59264 6275149824 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:11:33,103 basehttp 59264 6275149824 "GET /en/hr/departments/ HTTP/1.1" 200 125426 +INFO 2025-09-07 16:11:33,121 basehttp 59264 6275149824 "GET /static/plugins/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css HTTP/1.1" 200 8136 +INFO 2025-09-07 16:11:33,121 basehttp 59264 6241497088 "GET /static/plugins/datatables.net-buttons-bs5/js/buttons.bootstrap5.min.js HTTP/1.1" 200 1627 +INFO 2025-09-07 16:11:33,121 basehttp 59264 6224670720 "GET /static/plugins/select2/dist/css/select2.min.css HTTP/1.1" 200 14966 +INFO 2025-09-07 16:11:33,122 basehttp 59264 6191017984 "GET /static/plugins/datatables.net-buttons/js/dataTables.buttons.min.js HTTP/1.1" 200 27926 +WARNING 2025-09-07 16:11:33,126 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:11:33,127 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:11:33,128 basehttp 59264 6224670720 "GET /static/plugins/datatables.net-buttons/js/buttons.print.min.js HTTP/1.1" 200 3073 +INFO 2025-09-07 16:11:33,131 basehttp 59264 6241497088 "GET /static/plugins/jszip/dist/jszip.min.js HTTP/1.1" 200 97630 +INFO 2025-09-07 16:11:33,131 basehttp 59264 6191017984 "GET /static/plugins/datatables.net-buttons/js/buttons.html5.min.js HTTP/1.1" 200 26043 +INFO 2025-09-07 16:11:33,138 basehttp 59264 6258323456 "GET /static/plugins/pdfmake/build/vfs_fonts.js HTTP/1.1" 200 828866 +INFO 2025-09-07 16:11:33,144 basehttp 59264 6275149824 "GET /static/plugins/pdfmake/build/pdfmake.min.js HTTP/1.1" 200 1400771 +INFO 2025-09-07 16:11:33,217 basehttp 59264 6258323456 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:11:33,228 basehttp 59264 6275149824 "GET /static/plugins/pdfmake/build/pdfmake.min.js.map HTTP/1.1" 200 4214503 +INFO 2025-09-07 16:12:34,200 basehttp 59264 6275149824 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:13:12,441 basehttp 59264 6275149824 "GET /en/hr/departments/12/delete/ HTTP/1.1" 200 30311 +WARNING 2025-09-07 16:13:12,464 log 59264 6275149824 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:13:12,464 basehttp 59264 6275149824 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:13:12,504 basehttp 59264 6275149824 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:13:21,744 basehttp 59264 6275149824 "GET /en/hr/departments/12/ HTTP/1.1" 200 35129 +WARNING 2025-09-07 16:13:21,762 basehttp 59264 6258323456 "GET /static/plugins/chart.js/dist/Chart.min.css HTTP/1.1" 404 2032 +WARNING 2025-09-07 16:13:21,765 basehttp 59264 6241497088 "GET /static/plugins/chart.js/dist/Chart.min.js HTTP/1.1" 404 2029 +WARNING 2025-09-07 16:13:21,767 basehttp 59264 6191017984 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 16:13:21,769 log 59264 6275149824 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:13:21,769 basehttp 59264 6275149824 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:13:21,800 basehttp 59264 6275149824 "GET /static/css/saudiriyalsymbol.woff2 HTTP/1.1" 200 720 +INFO 2025-09-07 16:13:21,812 basehttp 59264 6275149824 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:13:36,120 basehttp 59264 6275149824 "GET /en/hr/departments/12/update/ HTTP/1.1" 200 41458 +WARNING 2025-09-07 16:13:36,137 basehttp 59264 6275149824 "GET /static/plugins/select2-bootstrap5-theme/select2-bootstrap5.min.css HTTP/1.1" 404 2104 +WARNING 2025-09-07 16:13:36,143 log 59264 6224670720 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:13:36,143 basehttp 59264 6224670720 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:13:36,192 basehttp 59264 6224670720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:13:51,429 basehttp 59264 6224670720 "GET /en/hr/departments/ HTTP/1.1" 200 125426 +WARNING 2025-09-07 16:13:51,446 log 59264 6224670720 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:13:51,446 basehttp 59264 6224670720 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:13:51,546 basehttp 59264 6224670720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:14:15,846 basehttp 59264 6224670720 "GET /en/hr/departments/10/ HTTP/1.1" 200 52158 +WARNING 2025-09-07 16:14:15,863 basehttp 59264 6224670720 "GET /static/plugins/chart.js/dist/Chart.min.css HTTP/1.1" 404 2032 +WARNING 2025-09-07 16:14:15,867 basehttp 59264 6207844352 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 16:14:15,867 basehttp 59264 6191017984 "GET /static/plugins/chart.js/dist/Chart.min.js HTTP/1.1" 404 2029 +WARNING 2025-09-07 16:14:15,870 log 59264 6241497088 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:14:15,870 basehttp 59264 6241497088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:14:15,914 basehttp 59264 6241497088 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:14:51,664 basehttp 59264 6241497088 "GET /en/hr/employees/52/ HTTP/1.1" 200 34483 +WARNING 2025-09-07 16:14:51,686 log 59264 6241497088 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:14:51,687 basehttp 59264 6241497088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:14:51,729 basehttp 59264 6241497088 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:15:51,745 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:16:51,736 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:17:51,739 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:18:25,132 basehttp 59264 6191017984 "GET /en/hr/employees/52/ HTTP/1.1" 200 36484 +WARNING 2025-09-07 16:18:25,143 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:18:25,143 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:18:25,186 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:18:48,463 basehttp 59264 6191017984 "GET /en/hr/employees/52/ HTTP/1.1" 200 36493 +WARNING 2025-09-07 16:18:48,479 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:18:48,479 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:18:48,517 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:19:48,522 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:20:48,535 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:21:16,667 basehttp 59264 6191017984 "GET /en/hr/employees/52/ HTTP/1.1" 200 35212 +WARNING 2025-09-07 16:21:16,680 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:21:16,681 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:21:16,729 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:22:16,739 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:22:49,183 basehttp 59264 6191017984 "GET /en/hr/employees/52/ HTTP/1.1" 200 35242 +WARNING 2025-09-07 16:22:49,197 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:22:49,197 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:22:49,222 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:23:01,175 basehttp 59264 6191017984 "GET /en/hr/employees/52/ HTTP/1.1" 200 35248 +WARNING 2025-09-07 16:23:01,190 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:23:01,191 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:23:01,252 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:23:57,143 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:23:57,146 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:23:57,146 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:23:57,149 basehttp 59264 6191017984 "GET /static/plugins/chart.js/dist/Chart.min.css HTTP/1.1" 404 2032 +WARNING 2025-09-07 16:23:57,164 log 59264 6207844352 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:23:57,164 basehttp 59264 6207844352 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:24:57,138 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:25:57,152 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:26:44,382 basehttp 59264 6207844352 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:26:44,387 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:26:44,387 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:26:44,400 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:26:44,400 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:26:45,380 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:26:45,380 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:26:45,391 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:26:45,392 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:26:46,047 basehttp 59264 6191017984 "GET /en/hr/departments/10/ HTTP/1.1" 200 52071 +INFO 2025-09-07 16:26:46,058 basehttp 59264 6191017984 "GET /static/plugins/chart.js/dist/chart.js HTTP/1.1" 200 403805 +WARNING 2025-09-07 16:26:46,066 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:26:46,066 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:26:46,117 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:27:46,133 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:28:15,821 basehttp 59264 6191017984 "GET /en/hr/departments/10/ HTTP/1.1" 200 53084 +WARNING 2025-09-07 16:28:15,836 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:28:15,836 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:28:15,892 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:28:27,430 basehttp 59264 6191017984 "GET /en/hr/departments/10/ HTTP/1.1" 200 53084 +WARNING 2025-09-07 16:28:27,449 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:28:27,449 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:28:27,510 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:28:37,552 basehttp 59264 6191017984 "GET /en/hr/departments/10/ HTTP/1.1" 200 53084 +WARNING 2025-09-07 16:28:37,569 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:28:37,569 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:28:37,614 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:29:20,934 basehttp 59264 6191017984 "GET /en/hr/departments/10/ HTTP/1.1" 200 52404 +WARNING 2025-09-07 16:29:20,949 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:29:20,950 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:29:21,002 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:29:28,213 basehttp 59264 6191017984 "GET /en/hr/departments/10/ HTTP/1.1" 200 52071 +WARNING 2025-09-07 16:29:28,231 log 59264 6191017984 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:29:28,231 basehttp 59264 6191017984 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:29:28,283 basehttp 59264 6191017984 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:29:48,811 basehttp 59264 6191017984 "GET /en/admin/hr/employee/ HTTP/1.1" 200 158543 +INFO 2025-09-07 16:29:48,826 basehttp 59264 6224670720 "GET /static/admin/css/nav_sidebar.css HTTP/1.1" 200 2810 +INFO 2025-09-07 16:29:48,826 basehttp 59264 6207844352 "GET /static/admin/css/dark_mode.css HTTP/1.1" 200 2808 +INFO 2025-09-07 16:29:48,827 basehttp 59264 6191017984 "GET /static/admin/css/base.css HTTP/1.1" 200 22120 +INFO 2025-09-07 16:29:48,827 basehttp 59264 6241497088 "GET /static/admin/css/changelists.css HTTP/1.1" 200 6878 +INFO 2025-09-07 16:29:48,827 basehttp 59264 6258323456 "GET /static/admin/js/theme.js HTTP/1.1" 200 1653 +INFO 2025-09-07 16:29:48,828 basehttp 59264 6207844352 "GET /static/admin/css/responsive.css HTTP/1.1" 200 16565 +INFO 2025-09-07 16:29:48,828 basehttp 59264 6241497088 "GET /static/admin/js/core.js HTTP/1.1" 200 6208 +INFO 2025-09-07 16:29:48,828 basehttp 59264 6191017984 "GET /static/admin/js/jquery.init.js HTTP/1.1" 200 347 +INFO 2025-09-07 16:29:48,830 basehttp 59264 6258323456 "GET /static/admin/js/admin/RelatedObjectLookups.js HTTP/1.1" 200 9777 +INFO 2025-09-07 16:29:48,830 basehttp 59264 6241497088 "GET /static/admin/js/prepopulate.js HTTP/1.1" 200 1531 +INFO 2025-09-07 16:29:48,831 basehttp 59264 6207844352 "GET /static/admin/js/actions.js HTTP/1.1" 200 8076 +INFO 2025-09-07 16:29:48,832 basehttp 59264 6191017984 "GET /static/admin/js/urlify.js HTTP/1.1" 200 7887 +INFO 2025-09-07 16:29:48,833 basehttp 59264 6241497088 "GET /static/admin/img/search.svg HTTP/1.1" 200 458 +INFO 2025-09-07 16:29:48,835 basehttp 59264 6275149824 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-07 16:29:48,835 basehttp 59264 6224670720 "GET /static/admin/js/vendor/jquery/jquery.js HTTP/1.1" 200 285314 +INFO 2025-09-07 16:29:48,839 basehttp 59264 6224670720 "GET /static/admin/js/nav_sidebar.js HTTP/1.1" 200 3063 +INFO 2025-09-07 16:29:48,839 basehttp 59264 6258323456 "GET /static/admin/js/vendor/xregexp/xregexp.js HTTP/1.1" 200 325171 +INFO 2025-09-07 16:29:48,840 basehttp 59264 6258323456 "GET /static/admin/js/filters.js HTTP/1.1" 200 978 +INFO 2025-09-07 16:29:48,848 basehttp 59264 6258323456 "GET /static/admin/img/icon-addlink.svg HTTP/1.1" 200 331 +INFO 2025-09-07 16:29:48,848 basehttp 59264 6224670720 "GET /static/admin/img/tooltag-add.svg HTTP/1.1" 200 331 +INFO 2025-09-07 16:29:48,849 basehttp 59264 6224670720 "GET /static/admin/img/icon-viewlink.svg HTTP/1.1" 200 581 +INFO 2025-09-07 16:29:56,778 basehttp 59264 6224670720 "GET /en/admin/hr/employee/56/change/ HTTP/1.1" 200 156606 +INFO 2025-09-07 16:29:56,788 basehttp 59264 6224670720 "GET /static/admin/css/forms.css HTTP/1.1" 200 8525 +INFO 2025-09-07 16:29:56,790 basehttp 59264 6191017984 "GET /static/admin/js/prepopulate_init.js HTTP/1.1" 200 586 +INFO 2025-09-07 16:29:56,791 basehttp 59264 6207844352 "GET /static/admin/css/widgets.css HTTP/1.1" 200 11991 +INFO 2025-09-07 16:29:56,791 basehttp 59264 6241497088 "GET /static/admin/js/inlines.js HTTP/1.1" 200 15628 +INFO 2025-09-07 16:29:56,791 basehttp 59264 6258323456 "GET /static/admin/js/calendar.js HTTP/1.1" 200 9141 +INFO 2025-09-07 16:29:56,791 basehttp 59264 6275149824 "GET /static/admin/js/admin/DateTimeShortcuts.js HTTP/1.1" 200 19319 +INFO 2025-09-07 16:29:56,793 basehttp 59264 6275149824 "GET /static/admin/img/icon-changelink.svg HTTP/1.1" 200 380 +INFO 2025-09-07 16:29:56,794 basehttp 59264 6224670720 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-07 16:29:56,794 basehttp 59264 6275149824 "GET /static/admin/img/icon-deletelink.svg HTTP/1.1" 200 392 +INFO 2025-09-07 16:29:56,795 basehttp 59264 6275149824 "GET /static/admin/img/icon-unknown.svg HTTP/1.1" 200 655 +INFO 2025-09-07 16:29:56,795 basehttp 59264 6224670720 "GET /static/admin/js/change_form.js HTTP/1.1" 200 606 +INFO 2025-09-07 16:29:56,826 basehttp 59264 6224670720 "GET /static/admin/img/icon-calendar.svg HTTP/1.1" 200 1086 +INFO 2025-09-07 16:29:57,267 basehttp 59264 6224670720 "GET /en/admin/hr/employee/ HTTP/1.1" 200 158543 +INFO 2025-09-07 16:29:58,269 basehttp 59264 6224670720 "GET /en/admin/hr/employee/56/change/ HTTP/1.1" 200 156606 +INFO 2025-09-07 16:29:58,284 basehttp 59264 6224670720 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-07 16:30:29,184 basehttp 59264 6224670720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:31:06,779 basehttp 59264 6224670720 "GET /en/admin/hr/employee/ HTTP/1.1" 200 158543 +INFO 2025-09-07 16:31:08,868 basehttp 59264 6224670720 "GET /en/admin/hr/employee/25/change/ HTTP/1.1" 200 288687 +INFO 2025-09-07 16:31:08,887 basehttp 59264 6224670720 "GET /en/admin/jsi18n/ HTTP/1.1" 200 3342 +INFO 2025-09-07 16:31:08,932 basehttp 59264 6224670720 "GET /static/admin/img/icon-clock.svg HTTP/1.1" 200 677 +INFO 2025-09-07 16:31:30,175 basehttp 59264 6224670720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:31:32,318 basehttp 59264 6224670720 "GET /en/admin/hr/employee/ HTTP/1.1" 200 158543 +INFO 2025-09-07 16:32:31,121 basehttp 59264 6224670720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:33:32,123 basehttp 59264 6224670720 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:34:08,088 autoreload 59264 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 16:34:08,524 autoreload 71999 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-07 16:34:10,955 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:10,955 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:34:11,988 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:11,989 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:34:12,973 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:12,973 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:34:13,585 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:13,585 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:34:14,036 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:14,036 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:34:14,547 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:14,547 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:34:40,331 basehttp 71999 6157496320 "GET /en/hr/training/ HTTP/1.1" 200 117094 +WARNING 2025-09-07 16:34:40,352 basehttp 71999 6174322688 "GET /static/plugins/datatables.net/js/jquery.dataTables.min.js HTTP/1.1" 404 2077 +WARNING 2025-09-07 16:34:40,354 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:34:40,354 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:34:40,424 basehttp 71999 6157496320 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:35:24,917 basehttp 71999 6157496320 "GET /en/hr/training/ HTTP/1.1" 200 117087 +WARNING 2025-09-07 16:35:24,942 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:35:24,942 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:35:24,993 basehttp 71999 6157496320 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 16:35:36,374 log 71999 6157496320 Internal Server Error: /en/hr/training/142/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for + nodelist_loop = parser.parse( + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 489, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 487, in parse + filter_expression = self.compile_filter(token.contents) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter + return FilterExpression(token, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__ + filter_func = parser.find_filter(filter_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter + raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name) +django.template.exceptions.TemplateSyntaxError: Invalid filter: 'split' +ERROR 2025-09-07 16:35:36,376 basehttp 71999 6157496320 "GET /en/hr/training/142/ HTTP/1.1" 500 375709 +WARNING 2025-09-07 16:35:36,395 log 71999 6157496320 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:35:36,395 basehttp 71999 6157496320 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:36:29,062 autoreload 71999 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 16:36:29,463 autoreload 73004 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 16:36:29,881 log 73004 6191345664 Internal Server Error: /en/hr/training/142/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for + nodelist_loop = parser.parse( + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 489, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 487, in parse + filter_expression = self.compile_filter(token.contents) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter + return FilterExpression(token, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__ + filter_func = parser.find_filter(filter_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter + raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name) +django.template.exceptions.TemplateSyntaxError: Invalid filter: 'split' +ERROR 2025-09-07 16:36:29,883 basehttp 73004 6191345664 "GET /en/hr/training/142/ HTTP/1.1" 500 375846 +WARNING 2025-09-07 16:36:29,900 log 73004 6191345664 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:36:29,900 basehttp 73004 6191345664 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:36:35,163 basehttp 73004 6191345664 "GET /en/hr/training HTTP/1.1" 301 0 +ERROR 2025-09-07 16:36:35,261 log 73004 6208172032 Internal Server Error: /en/hr/training/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'get_program_details' not found. 'get_program_details' is not a valid view function or pattern name. +ERROR 2025-09-07 16:36:35,262 basehttp 73004 6208172032 "GET /en/hr/training/ HTTP/1.1" 500 215315 +WARNING 2025-09-07 16:36:35,282 log 73004 6208172032 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:36:35,282 basehttp 73004 6208172032 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 16:40:38,449 log 73004 6208172032 Internal Server Error: /en/hr/training/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'update_program' not found. 'update_program' is not a valid view function or pattern name. +ERROR 2025-09-07 16:40:38,450 basehttp 73004 6208172032 "GET /en/hr/training/ HTTP/1.1" 500 217002 +WARNING 2025-09-07 16:40:38,462 log 73004 6208172032 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:40:38,462 basehttp 73004 6208172032 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 16:41:03,400 log 73004 6208172032 Internal Server Error: /en/hr/training/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'program_detail' not found. 'program_detail' is not a valid view function or pattern name. +ERROR 2025-09-07 16:41:03,401 basehttp 73004 6208172032 "GET /en/hr/training/ HTTP/1.1" 500 217084 +WARNING 2025-09-07 16:41:03,420 log 73004 6208172032 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:41:03,420 basehttp 73004 6208172032 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:43:49,987 basehttp 73004 6208172032 "GET /en/hr/training/ HTTP/1.1" 200 51267 +WARNING 2025-09-07 16:43:50,002 log 73004 6208172032 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:43:50,003 basehttp 73004 6208172032 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:43:50,050 basehttp 73004 6208172032 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:44:50,053 basehttp 73004 6208172032 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:45:14,901 autoreload 73004 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 16:45:15,356 autoreload 76878 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 16:45:16,032 basehttp 76878 6132101120 "GET /en/hr/training/ HTTP/1.1" 200 117087 +WARNING 2025-09-07 16:45:16,050 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:16,050 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:45:16,113 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:45:35,524 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:35,524 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:45:40,288 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:40,289 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:45:43,734 basehttp 76878 6132101120 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 16:45:43,749 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:43,750 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:45:43,797 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:45:54,662 basehttp 76878 6132101120 "GET /en/hr/training/ HTTP/1.1" 200 117087 +WARNING 2025-09-07 16:45:54,680 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:54,680 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:45:54,737 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:45:56,841 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:56,842 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:45:56,881 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:45:56,881 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:46:43,810 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:47:43,813 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:47:44,830 basehttp 76878 6132101120 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 16:47:44,846 log 76878 6132101120 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:47:44,846 basehttp 76878 6132101120 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:47:44,893 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:48:44,905 basehttp 76878 6132101120 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:49:35,670 autoreload 76878 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 16:49:35,990 autoreload 78804 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-07 16:49:37,066 log 78804 6140686336 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:37,066 basehttp 78804 6140686336 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:49:37,106 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:49:37,137 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:37,137 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:49:38,055 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:38,055 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:49:38,064 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:38,064 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:49:38,551 basehttp 78804 6123859968 "GET /en/hr/ HTTP/1.1" 200 42394 +WARNING 2025-09-07 16:49:38,562 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:38,563 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:49:38,611 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 16:49:40,061 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:40,061 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 16:49:40,074 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:40,075 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:49:40,983 basehttp 78804 6123859968 "GET /en/hr/training/ HTTP/1.1" 200 51267 +WARNING 2025-09-07 16:49:41,003 log 78804 6123859968 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 16:49:41,003 basehttp 78804 6123859968 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 16:49:41,049 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:50:41,063 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:51:41,068 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:52:41,094 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:53:42,091 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:54:43,092 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:55:44,095 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:56:46,088 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 16:58:09,082 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:00:09,077 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:02:09,203 basehttp 78804 6123859968 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:02:22,937 autoreload 78804 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 17:02:23,361 autoreload 84426 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 17:02:36,218 basehttp 84426 6157742080 "GET /en/hr/training/ HTTP/1.1" 200 94607 +WARNING 2025-09-07 17:02:36,238 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:02:36,238 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:02:36,328 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 17:02:59,699 log 84426 6157742080 Internal Server Error: /en/hr/training/642/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for + nodelist_loop = parser.parse( + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 489, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 487, in parse + filter_expression = self.compile_filter(token.contents) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter + return FilterExpression(token, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__ + filter_func = parser.find_filter(filter_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter + raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name) +django.template.exceptions.TemplateSyntaxError: Invalid filter: 'split' +ERROR 2025-09-07 17:02:59,703 basehttp 84426 6157742080 "GET /en/hr/training/642/ HTTP/1.1" 500 375709 +WARNING 2025-09-07 17:02:59,716 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:02:59,716 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 17:03:56,329 log 84426 6325039104 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:03:56,330 basehttp 84426 6325039104 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:03:56,331 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 17:03:56,341 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:03:56,341 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:03:57,012 basehttp 84426 6157742080 "GET /en/hr/training/ HTTP/1.1" 200 94613 +WARNING 2025-09-07 17:03:57,026 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:03:57,026 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:03:57,107 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 17:04:41,775 log 84426 6157742080 Internal Server Error: /en/hr/training/313/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 510, in parse + compile_func = self.tags[command] + ~~~~~~~~~^^^^^^^^^ +KeyError: "set_badge='success'" + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 1540, in do_with + nodelist = parser.parse(("endwith",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 512, in parse + self.invalid_block_tag(token, command, parse_until) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 567, in invalid_block_tag + raise self.error( +django.template.exceptions.TemplateSyntaxError: Invalid block tag on line 48: 'set_badge='success'', expected 'elif', 'else' or 'endif'. Did you forget to register or load this tag? +ERROR 2025-09-07 17:04:41,778 basehttp 84426 6157742080 "GET /en/hr/training/313/ HTTP/1.1" 500 314845 +WARNING 2025-09-07 17:04:41,793 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:04:41,793 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 17:04:47,934 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:04:47,934 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 17:04:47,946 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:04:47,946 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:04:57,134 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 17:05:08,240 log 84426 6157742080 Internal Server Error: /en/hr/training/9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for + nodelist_loop = parser.parse( + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 489, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 487, in parse + filter_expression = self.compile_filter(token.contents) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter + return FilterExpression(token, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__ + filter_func = parser.find_filter(filter_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter + raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name) +django.template.exceptions.TemplateSyntaxError: Invalid filter: 'split' +ERROR 2025-09-07 17:05:08,242 basehttp 84426 6157742080 "GET /en/hr/training/9/ HTTP/1.1" 500 375659 +WARNING 2025-09-07 17:05:08,256 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:05:08,256 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 17:05:28,071 log 84426 6157742080 Internal Server Error: /en/hr/training/9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for + nodelist_loop = parser.parse( + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 489, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 487, in parse + filter_expression = self.compile_filter(token.contents) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter + return FilterExpression(token, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__ + filter_func = parser.find_filter(filter_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter + raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name) +django.template.exceptions.TemplateSyntaxError: Invalid filter: 'split' +ERROR 2025-09-07 17:05:28,073 basehttp 84426 6157742080 "GET /en/hr/training/9/ HTTP/1.1" 500 320532 +WARNING 2025-09-07 17:05:28,089 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:05:28,089 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 17:05:40,036 log 84426 6157742080 Internal Server Error: /en/hr/training/9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'employee_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['en/hr/employees/(?P[0-9]+)/\\Z'] +ERROR 2025-09-07 17:05:40,038 basehttp 84426 6157742080 "GET /en/hr/training/9/ HTTP/1.1" 500 179703 +WARNING 2025-09-07 17:05:40,051 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:05:40,051 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +ERROR 2025-09-07 17:06:30,036 log 84426 6157742080 Internal Server Error: /en/hr/training/9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'employee_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['en/hr/employees/(?P[0-9]+)/\\Z'] +ERROR 2025-09-07 17:06:30,037 basehttp 84426 6157742080 "GET /en/hr/training/9/ HTTP/1.1" 500 179703 +WARNING 2025-09-07 17:06:30,049 log 84426 6157742080 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:06:30,049 basehttp 84426 6157742080 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 17:13:58,575 log 84426 6325039104 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:13:58,575 basehttp 84426 6325039104 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:13:58,579 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 17:13:58,583 log 84426 6325039104 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 17:13:58,583 basehttp 84426 6325039104 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 17:14:58,570 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:15:00,153 basehttp 84426 6325039104 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 17:15:00,213 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:15:07,473 basehttp 84426 6325039104 "GET /en/blood-bank/units/38/ HTTP/1.1" 200 35788 +INFO 2025-09-07 17:15:07,484 basehttp 84426 6325039104 "GET /static/plugins/sweetalert/dist/sweetalert.min.js HTTP/1.1" 200 40808 +INFO 2025-09-07 17:15:07,520 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:15:14,164 basehttp 84426 6325039104 "GET /en/blood-bank/units/38/test/ HTTP/1.1" 200 45659 +INFO 2025-09-07 17:15:14,194 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:15:21,406 basehttp 84426 6325039104 "GET /en/blood-bank/donors/46/ HTTP/1.1" 200 29824 +INFO 2025-09-07 17:15:21,443 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:15:26,546 basehttp 84426 6325039104 "GET /en/blood-bank/donors/46/eligibility/ HTTP/1.1" 200 33976 +INFO 2025-09-07 17:15:26,582 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:16:06,428 basehttp 84426 6157742080 "GET /en/blood-bank/donors/46/eligibility/ HTTP/1.1" 200 33976 +INFO 2025-09-07 17:16:06,466 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:16:27,765 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:16:30,194 basehttp 84426 6157742080 "GET /en/blood-bank/units/13/ HTTP/1.1" 200 36506 +INFO 2025-09-07 17:16:30,234 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:16:47,814 basehttp 84426 6157742080 "GET /en/blood-bank/donors/46/eligibility/ HTTP/1.1" 200 33976 +INFO 2025-09-07 17:16:47,852 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:16:55,138 basehttp 84426 6157742080 "GET /en/blood-bank/donors/ HTTP/1.1" 200 82651 +INFO 2025-09-07 17:16:55,182 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:17:08,876 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:17:24,261 basehttp 84426 6157742080 "GET /en/blood-bank/inventory/ HTTP/1.1" 200 34369 +INFO 2025-09-07 17:17:24,299 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:17:43,987 basehttp 84426 6157742080 "GET /en/blood-bank/donors/ HTTP/1.1" 200 82651 +INFO 2025-09-07 17:17:44,028 basehttp 84426 6157742080 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:17:49,526 basehttp 84426 6157742080 "GET /en/blood-bank/units/create/ HTTP/1.1" 200 56247 +INFO 2025-09-07 17:17:49,534 basehttp 84426 6157742080 "GET /static/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css HTTP/1.1" 200 15733 +INFO 2025-09-07 17:17:49,534 basehttp 84426 6325039104 "GET /static/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js HTTP/1.1" 200 33871 +INFO 2025-09-07 17:17:49,565 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:18:49,580 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:19:49,585 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:20:49,583 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:21:17,193 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:21:17,777 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:21:23,031 basehttp 84426 6325039104 "GET /en/hr/training/ HTTP/1.1" 200 94613 +INFO 2025-09-07 17:21:23,076 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 17:21:24,288 log 84426 6325039104 Internal Server Error: /en/hr/training/9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'employee_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['en/hr/employees/(?P[0-9]+)/\\Z'] +ERROR 2025-09-07 17:21:24,291 basehttp 84426 6325039104 "GET /en/hr/training/9/ HTTP/1.1" 500 179587 +INFO 2025-09-07 17:22:23,081 basehttp 84426 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:22:49,206 autoreload 84426 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 17:22:49,647 autoreload 93365 8747049152 Watching for file changes with StatReloader +ERROR 2025-09-07 17:22:52,504 log 93365 6132805632 Internal Server Error: /en/hr/training/9/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'training_record_print' not found. 'training_record_print' is not a valid view function or pattern name. +ERROR 2025-09-07 17:22:52,506 basehttp 93365 6132805632 "GET /en/hr/training/9/ HTTP/1.1" 500 177519 +INFO 2025-09-07 17:23:43,843 basehttp 93365 6132805632 "GET /en/hr/training/9/ HTTP/1.1" 200 28657 +INFO 2025-09-07 17:23:43,879 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:24:43,895 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:24:50,025 basehttp 93365 6132805632 "GET /en/hr/training/9/ HTTP/1.1" 200 28729 +INFO 2025-09-07 17:24:50,064 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:25:18,410 basehttp 93365 6132805632 "GET /en/hr/training/9/ HTTP/1.1" 200 28765 +INFO 2025-09-07 17:25:18,451 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:26:03,810 basehttp 93365 6132805632 "GET /en/hr/training/9/ HTTP/1.1" 200 28800 +INFO 2025-09-07 17:26:03,849 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:27:03,861 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:28:03,865 basehttp 93365 6132805632 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:29:21,091 autoreload 96269 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 17:29:32,040 basehttp 96269 6134935552 "GET /en/hr/training/9/ HTTP/1.1" 200 28800 +INFO 2025-09-07 17:29:32,081 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:30:12,259 basehttp 96269 6134935552 "GET /en/hr/employees/1/ HTTP/1.1" 200 35234 +INFO 2025-09-07 17:30:12,298 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:30:32,087 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:31:32,094 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:32:16,229 basehttp 96269 6134935552 "GET /en/hr/training/9/ HTTP/1.1" 200 28824 +INFO 2025-09-07 17:32:16,268 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:32:52,240 basehttp 96269 6134935552 "GET /en/hr/training/9/ HTTP/1.1" 200 28891 +INFO 2025-09-07 17:32:52,278 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:33:52,295 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:34:52,286 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:35:52,294 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:36:52,299 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:37:52,303 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:38:52,305 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:39:52,308 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:40:52,301 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:41:52,313 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:42:52,305 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:43:52,316 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:44:52,319 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:45:52,325 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:46:52,323 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:47:52,321 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:48:52,322 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:49:52,323 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:50:52,323 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:51:52,326 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:52:52,317 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:53:52,329 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:54:52,330 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:55:52,336 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:56:52,333 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:57:52,325 basehttp 96269 6134935552 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:58:30,257 autoreload 96269 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 17:58:30,606 autoreload 9737 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 17:58:31,247 basehttp 9737 6197653504 "GET /en/hr/training/9/ HTTP/1.1" 200 28891 +INFO 2025-09-07 17:58:31,281 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 17:58:34,709 basehttp 9737 6197653504 "GET /en/hr/training/ HTTP/1.1" 200 94613 +INFO 2025-09-07 17:58:35,629 basehttp 9737 6197653504 "GET /en/hr/training/ HTTP/1.1" 200 94613 +INFO 2025-09-07 17:58:35,671 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 17:58:40,144 log 9737 6197653504 Internal Server Error: /en/hr/training/create/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 90, in rendered_content + template = self.resolve_template(self.template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 72, in resolve_template + return select_template(template, using=self.using) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader.py", line 42, in select_template + return engine.get_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 79, in get_template + return Template(self.engine.get_template(template_name), self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 177, in get_template + template, origin = self.find_template(template_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/engine.py", line 159, in find_template + template = loader.get_template(name, skip=skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/cached.py", line 57, in get_template + template = super().get_template(template_name, skip) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loaders/base.py", line 28, in get_template + return Template( + ^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 154, in __init__ + self.nodelist = self.compile_nodelist() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 196, in compile_nodelist + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 299, in do_extends + nodelist = parser.parse() + ^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 234, in do_block + nodelist = parser.parse(("endblock",)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 962, in do_if + nodelist = parser.parse(("elif", "else", "endif")) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 518, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 516, in parse + compiled_result = compile_func(self, token) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 862, in do_for + nodelist_loop = parser.parse( + ^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 489, in parse + raise self.error(token, e) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 487, in parse + filter_expression = self.compile_filter(token.contents) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 609, in compile_filter + return FilterExpression(token, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 705, in __init__ + filter_func = parser.find_filter(filter_name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 615, in find_filter + raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name) +django.template.exceptions.TemplateSyntaxError: Invalid filter: 'split' +ERROR 2025-09-07 17:58:40,147 basehttp 9737 6197653504 "GET /en/hr/training/create/ HTTP/1.1" 500 351884 +INFO 2025-09-07 18:00:40,415 basehttp 9737 6197653504 "GET /en/hr/training/create/ HTTP/1.1" 200 50385 +INFO 2025-09-07 18:00:40,425 basehttp 9737 6197653504 "GET /static/plugins/summernote/dist/summernote-lite.css HTTP/1.1" 200 38212 +INFO 2025-09-07 18:00:40,429 basehttp 9737 6197653504 "GET /static/plugins/summernote/dist/summernote-lite.min.js HTTP/1.1" 200 186367 +INFO 2025-09-07 18:00:40,458 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:00:55,121 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:01:55,122 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:02:55,113 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:03:55,114 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:04:55,114 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:05:55,118 basehttp 9737 6197653504 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:06:47,949 autoreload 9737 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 18:06:48,365 autoreload 13342 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 18:49:22,974 autoreload 31933 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 18:49:25,303 basehttp 31933 6191558656 "GET /en/hr/training/ HTTP/1.1" 200 94613 +INFO 2025-09-07 18:49:25,355 basehttp 31933 6191558656 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:49:28,905 basehttp 31933 6191558656 "GET /en/hr/training/9/ HTTP/1.1" 200 28891 +INFO 2025-09-07 18:49:28,934 basehttp 31933 6191558656 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 18:49:33,840 log 31933 6191558656 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 18:49:33,840 basehttp 31933 6191558656 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 18:49:42,876 basehttp 31933 6191558656 "GET /en/hr/training/9/update/ HTTP/1.1" 200 50484 +WARNING 2025-09-07 18:49:42,892 log 31933 6191558656 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 18:49:42,892 basehttp 31933 6191558656 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 18:49:42,964 basehttp 31933 6191558656 "GET /static/plugins/summernote/dist/summernote-lite.css.map HTTP/1.1" 200 52049 +INFO 2025-09-07 18:49:42,973 basehttp 31933 6191558656 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:50:42,989 basehttp 31933 6191558656 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:51:42,981 basehttp 31933 6191558656 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:52:35,424 autoreload 31933 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 18:52:35,775 autoreload 33342 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 18:52:43,036 basehttp 33342 6171783168 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:53:32,887 autoreload 33342 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 18:53:33,210 autoreload 33823 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 18:53:43,035 basehttp 33823 6158364672 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:54:42,988 basehttp 33823 6158364672 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:55:42,996 basehttp 33823 6158364672 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:56:42,995 basehttp 33823 6158364672 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:57:43,002 basehttp 33823 6158364672 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 18:58:14,610 autoreload 33823 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/models.py changed, reloading. +INFO 2025-09-07 18:58:14,946 autoreload 35826 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 19:01:36,616 autoreload 37400 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-07 19:01:39,903 log 37400 6165229568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:01:39,903 basehttp 37400 6165229568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:01:40,024 basehttp 37400 6165229568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:01:49,447 basehttp 37400 6165229568 "GET /en/hr/training-management HTTP/1.1" 200 54669 +WARNING 2025-09-07 19:01:49,464 log 37400 6165229568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:01:49,465 basehttp 37400 6165229568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:01:49,534 basehttp 37400 6165229568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:02:05,029 autoreload 37400 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 19:02:05,363 autoreload 37565 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 19:02:05,952 basehttp 37565 6196097024 "GET /en/hr/training-management HTTP/1.1" 200 94613 +WARNING 2025-09-07 19:02:05,971 log 37565 6196097024 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:02:05,971 basehttp 37565 6196097024 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:02:06,058 basehttp 37565 6196097024 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:02:31,038 basehttp 37565 6196097024 "GET /en/hr/training/create/ HTTP/1.1" 200 50385 +WARNING 2025-09-07 19:02:31,056 log 37565 6196097024 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:02:31,056 basehttp 37565 6196097024 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:02:31,137 basehttp 37565 6196097024 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 19:02:35,803 log 37565 6196097024 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:02:35,803 basehttp 37565 6196097024 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 19:02:35,812 log 37565 6196097024 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:02:35,813 basehttp 37565 6196097024 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:03:06,065 basehttp 37565 6196097024 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:03:56,545 autoreload 37565 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 19:03:56,902 autoreload 38419 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-07 19:03:57,860 log 38419 6159265792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:03:57,861 basehttp 38419 6159265792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 19:03:57,872 log 38419 6159265792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:03:57,872 basehttp 38419 6159265792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:03:59,887 basehttp 38419 6159265792 "GET /en/hr/training-management HTTP/1.1" 200 97400 +WARNING 2025-09-07 19:03:59,901 log 38419 6159265792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:03:59,901 basehttp 38419 6159265792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:03:59,985 basehttp 38419 6159265792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:04:02,939 basehttp 38419 6159265792 "GET /en/hr/training-management?page=2 HTTP/1.1" 200 97758 +WARNING 2025-09-07 19:04:02,962 log 38419 6159265792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:04:02,962 basehttp 38419 6159265792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:04:03,046 basehttp 38419 6159265792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:04:22,791 basehttp 38419 6159265792 "GET /en/hr/training/ HTTP/1.1" 200 36297 +WARNING 2025-09-07 19:04:22,810 log 38419 6159265792 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:04:22,810 basehttp 38419 6159265792 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:04:22,892 basehttp 38419 6159265792 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:04:40,791 autoreload 38419 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hr/views.py changed, reloading. +INFO 2025-09-07 19:04:41,117 autoreload 38736 8747049152 Watching for file changes with StatReloader +WARNING 2025-09-07 19:04:42,402 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:04:42,403 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 19:04:42,413 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:04:42,414 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:04:43,092 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117087 +WARNING 2025-09-07 19:04:43,108 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:04:43,109 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:04:43,204 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:05:43,209 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:05:59,216 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117148 +WARNING 2025-09-07 19:05:59,233 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:05:59,233 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:05:59,324 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:06:31,125 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117168 +WARNING 2025-09-07 19:06:31,138 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:06:31,138 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:06:31,232 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:07:05,391 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117193 +WARNING 2025-09-07 19:07:05,407 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:07:05,407 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:07:05,502 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:07:23,355 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117188 +WARNING 2025-09-07 19:07:23,372 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:07:23,372 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:07:23,466 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:07:59,729 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117193 +WARNING 2025-09-07 19:07:59,746 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:07:59,746 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:07:59,839 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:08:14,555 basehttp 38736 6197555200 "GET /en/hr/training/ HTTP/1.1" 200 117173 +WARNING 2025-09-07 19:08:14,570 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:08:14,570 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:08:14,664 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 19:08:30,306 log 38736 6214381568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +INFO 2025-09-07 19:08:30,307 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 19:08:30,307 basehttp 38736 6214381568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 19:08:30,316 log 38736 6214381568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:08:30,316 basehttp 38736 6214381568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:08:31,215 basehttp 38736 6214381568 "GET /en/hr/training-management?page=2 HTTP/1.1" 200 97758 +WARNING 2025-09-07 19:08:31,229 log 38736 6214381568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:08:31,230 basehttp 38736 6214381568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:08:31,318 basehttp 38736 6214381568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:08:43,991 basehttp 38736 6214381568 "GET /en/hr/training/986/ HTTP/1.1" 200 28844 +WARNING 2025-09-07 19:08:44,014 log 38736 6214381568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:08:44,014 basehttp 38736 6214381568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:08:44,086 basehttp 38736 6214381568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:09:44,092 basehttp 38736 6214381568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:10:44,103 basehttp 38736 6214381568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:11:44,106 basehttp 38736 6214381568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:12:44,111 basehttp 38736 6214381568 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:12:54,530 basehttp 38736 6214381568 "GET / HTTP/1.1" 302 0 +INFO 2025-09-07 19:12:54,555 basehttp 38736 6197555200 "GET /en/ HTTP/1.1" 200 49700 +WARNING 2025-09-07 19:12:54,573 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:12:54,573 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:12:54,664 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:12:54,674 basehttp 38736 6248034304 "GET /en/htmx/tenant-info/ HTTP/1.1" 200 1043 +INFO 2025-09-07 19:12:54,676 basehttp 38736 6231207936 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +INFO 2025-09-07 19:12:54,677 basehttp 38736 6214381568 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +WARNING 2025-09-07 19:13:04,688 log 38736 6214381568 Not Found: /en/core/departments +WARNING 2025-09-07 19:13:04,689 basehttp 38736 6214381568 "GET /en/core/departments HTTP/1.1" 404 30136 +WARNING 2025-09-07 19:13:04,710 log 38736 6214381568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:13:04,710 basehttp 38736 6214381568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 19:13:26,185 log 38736 6214381568 Not Found: /en/core/departments +WARNING 2025-09-07 19:13:26,186 basehttp 38736 6214381568 "GET /en/core/departments HTTP/1.1" 404 30136 +WARNING 2025-09-07 19:13:26,203 log 38736 6214381568 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:13:26,203 basehttp 38736 6214381568 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:13:32,301 basehttp 38736 6214381568 "GET /en/departments HTTP/1.1" 301 0 +INFO 2025-09-07 19:13:32,322 basehttp 38736 6231207936 "GET /en/departments/ HTTP/1.1" 200 134624 +WARNING 2025-09-07 19:13:32,336 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:13:32,336 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:13:32,421 basehttp 38736 6231207936 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:13:38,966 basehttp 38736 6231207936 "GET /en/departments/12/ HTTP/1.1" 200 38676 +WARNING 2025-09-07 19:13:38,987 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:13:38,987 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:13:39,308 basehttp 38736 6231207936 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:13:55,079 basehttp 38736 6231207936 "GET /en/inventory/items/?department=12 HTTP/1.1" 200 73409 +WARNING 2025-09-07 19:13:55,094 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:13:55,095 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:13:55,191 basehttp 38736 6231207936 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 19:14:06,976 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:14:06,976 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 19:14:06,988 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:14:06,988 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:14:27,071 basehttp 38736 6231207936 "GET /en/hr/departments/12/ HTTP/1.1" 200 35042 +WARNING 2025-09-07 19:14:27,093 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:14:27,093 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:14:27,168 basehttp 38736 6231207936 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:14:34,406 basehttp 38736 6231207936 "GET /en/hr/departments/ HTTP/1.1" 200 125426 +WARNING 2025-09-07 19:14:34,428 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:14:34,428 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:14:34,516 basehttp 38736 6231207936 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:15:06,152 basehttp 38736 6231207936 "GET /en/hr/departments/create/ HTTP/1.1" 200 41288 +WARNING 2025-09-07 19:15:06,169 basehttp 38736 6248034304 "GET /static/plugins/select2-bootstrap5-theme/select2-bootstrap5.min.css HTTP/1.1" 404 2104 +WARNING 2025-09-07 19:15:06,174 log 38736 6231207936 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:15:06,174 basehttp 38736 6231207936 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:15:06,248 basehttp 38736 6231207936 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:15:58,471 basehttp 38736 6197555200 "GET /en/departments/create/ HTTP/1.1" 200 43115 +WARNING 2025-09-07 19:15:58,493 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:15:58,493 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:15:58,576 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:16:23,074 basehttp 38736 6197555200 "GET /en/hr/departments/create/ HTTP/1.1" 200 41288 +WARNING 2025-09-07 19:16:23,090 basehttp 38736 6214381568 "GET /static/plugins/select2-bootstrap5-theme/select2-bootstrap5.min.css HTTP/1.1" 404 2104 +WARNING 2025-09-07 19:16:23,094 log 38736 6197555200 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 19:16:23,094 basehttp 38736 6197555200 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 19:16:23,174 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:17:23,199 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:18:23,191 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:19:23,309 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:20:23,323 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:21:23,325 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:22:23,329 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:23:23,331 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:24:23,324 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 19:25:23,331 basehttp 38736 6197555200 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:16:49,289 autoreload 70364 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:17:02,711 autoreload 70364 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/models.py changed, reloading. +INFO 2025-09-07 20:17:03,014 autoreload 70456 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:17:18,406 autoreload 70456 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/admin.py changed, reloading. +INFO 2025-09-07 20:17:18,672 autoreload 70620 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:17:27,955 autoreload 70620 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/admin.py changed, reloading. +INFO 2025-09-07 20:17:28,275 autoreload 70706 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:17:39,722 autoreload 70706 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/views.py changed, reloading. +INFO 2025-09-07 20:17:40,062 autoreload 70801 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:17:48,381 autoreload 70801 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/forms.py changed, reloading. +INFO 2025-09-07 20:17:48,674 autoreload 70896 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:18:05,260 autoreload 70896 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/forms.py changed, reloading. +INFO 2025-09-07 20:18:05,558 autoreload 70980 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:19:38,162 autoreload 71715 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:20:42,235 autoreload 72212 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:21:00,993 autoreload 72212 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/forms.py changed, reloading. +INFO 2025-09-07 20:21:01,300 autoreload 72401 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:22:50,198 autoreload 73233 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:23:06,046 autoreload 73233 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/quality/forms.py changed, reloading. +INFO 2025-09-07 20:23:06,357 autoreload 73391 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:23:16,822 autoreload 73391 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/views.py changed, reloading. +INFO 2025-09-07 20:23:17,128 autoreload 73473 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:23:22,390 autoreload 73473 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/admin.py changed, reloading. +INFO 2025-09-07 20:23:22,700 autoreload 73486 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:23:56,461 autoreload 73486 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/models.py changed, reloading. +INFO 2025-09-07 20:23:56,769 autoreload 73801 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:24:00,929 autoreload 73820 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:24:15,641 autoreload 73820 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/forms.py changed, reloading. +INFO 2025-09-07 20:24:15,992 autoreload 73904 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:24:20,396 autoreload 73904 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/blood_bank/forms.py changed, reloading. +INFO 2025-09-07 20:24:20,713 autoreload 73991 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:24:40,610 autoreload 74164 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:25:54,846 autoreload 74745 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:26:42,932 autoreload 74745 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/core/models.py changed, reloading. +INFO 2025-09-07 20:26:43,364 autoreload 75052 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:26:48,819 basehttp 75052 6202585088 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +WARNING 2025-09-07 20:26:49,726 log 75052 6202585088 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 20:26:49,726 basehttp 75052 6202585088 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 20:26:51,621 basehttp 75052 6202585088 "GET / HTTP/1.1" 302 0 +INFO 2025-09-07 20:26:51,644 basehttp 75052 6219411456 "GET /en/ HTTP/1.1" 200 49790 +INFO 2025-09-07 20:26:51,735 basehttp 75052 6219411456 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:26:51,739 basehttp 75052 6202585088 "GET /en/htmx/dashboard-stats/ HTTP/1.1" 200 2094 +INFO 2025-09-07 20:26:51,745 basehttp 75052 6253064192 "GET /en/htmx/tenant-info/ HTTP/1.1" 200 1043 +INFO 2025-09-07 20:26:51,746 basehttp 75052 6236237824 "GET /en/htmx/system-health/ HTTP/1.1" 200 1356 +WARNING 2025-09-07 20:26:53,943 log 75052 6236237824 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 20:26:53,943 basehttp 75052 6236237824 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +WARNING 2025-09-07 20:26:55,517 log 75052 6236237824 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 20:26:55,518 basehttp 75052 6236237824 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 20:26:58,151 basehttp 75052 6236237824 "GET /en/blood-bank HTTP/1.1" 301 0 +INFO 2025-09-07 20:26:58,179 basehttp 75052 6253064192 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +WARNING 2025-09-07 20:26:58,194 log 75052 6253064192 Not Found: /.well-known/appspecific/com.chrome.devtools.json +WARNING 2025-09-07 20:26:58,194 basehttp 75052 6253064192 "GET /.well-known/appspecific/com.chrome.devtools.json HTTP/1.1" 404 2668 +INFO 2025-09-07 20:26:58,280 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:27:16,483 basehttp 75052 6253064192 "GET /en/blood-bank/units/38/ HTTP/1.1" 200 35788 +INFO 2025-09-07 20:27:16,522 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:27:27,392 basehttp 75052 6253064192 "GET /en/blood-bank/units/38/test/ HTTP/1.1" 200 45659 +INFO 2025-09-07 20:27:27,427 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:27:40,160 basehttp 75052 6253064192 "GET /en/blood-bank/donors/46/ HTTP/1.1" 200 29824 +INFO 2025-09-07 20:27:40,196 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:27:46,387 basehttp 75052 6253064192 "GET /en/blood-bank/donors/46/eligibility/ HTTP/1.1" 200 33976 +INFO 2025-09-07 20:27:46,422 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:28:28,942 basehttp 75052 6253064192 "GET /en/blood-bank/donors/46/eligibility/ HTTP/1.1" 200 33976 +INFO 2025-09-07 20:28:28,979 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:28:31,872 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:28:34,119 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:28:36,679 basehttp 75052 6253064192 "GET /en/blood-bank/units/ HTTP/1.1" 200 88820 +INFO 2025-09-07 20:28:36,725 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:28:41,682 basehttp 75052 6253064192 "GET /en/blood-bank/units/48/ HTTP/1.1" 200 36489 +INFO 2025-09-07 20:28:41,718 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:29:36,734 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:29:48,297 basehttp 75052 6253064192 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +ERROR 2025-09-07 20:30:04,781 log 75052 6253064192 Internal Server Error: /en/hr/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 105, in _execute + return self.cursor.execute(sql, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/sqlite3/base.py", line 360, in execute + return super().execute(query, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +sqlite3.OperationalError: no such column: hr_employee.national_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 199, in render + len_values = len(values) + ^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1949, in _fetch_all + self._result_cache = list(self._iterable_class(self)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 91, in __iter__ + results = compiler.execute_sql( + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1623, in execute_sql + cursor.execute(sql, params) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 122, in execute + return super().execute(sql, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 79, in execute + return self._execute_with_wrappers( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers + return executor(sql, params, many, context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 100, in _execute + with self.db.wrap_database_errors: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/utils.py", line 91, in __exit__ + raise dj_exc_value.with_traceback(traceback) from exc_value + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 105, in _execute + return self.cursor.execute(sql, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/sqlite3/base.py", line 360, in execute + return super().execute(query, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +django.db.utils.OperationalError: no such column: hr_employee.national_id +ERROR 2025-09-07 20:30:04,784 basehttp 75052 6253064192 "GET /en/hr/ HTTP/1.1" 500 235599 +ERROR 2025-09-07 20:30:05,673 log 75052 6253064192 Internal Server Error: /en/hr/ +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 105, in _execute + return self.cursor.execute(sql, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/sqlite3/base.py", line 360, in execute + return super().execute(query, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +sqlite3.OperationalError: no such column: hr_employee.national_id + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + ^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/template/defaulttags.py", line 199, in render + len_values = len(values) + ^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 366, in __len__ + self._fetch_all() + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 1949, in _fetch_all + self._result_cache = list(self._iterable_class(self)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/query.py", line 91, in __iter__ + results = compiler.execute_sql( + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py", line 1623, in execute_sql + cursor.execute(sql, params) + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 122, in execute + return super().execute(sql, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 79, in execute + return self._execute_with_wrappers( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers + return executor(sql, params, many, context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 100, in _execute + with self.db.wrap_database_errors: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/utils.py", line 91, in __exit__ + raise dj_exc_value.with_traceback(traceback) from exc_value + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 105, in _execute + return self.cursor.execute(sql, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/marwanalwali/manus_project/hospital_management_system_v4/.venv/lib/python3.12/site-packages/django/db/backends/sqlite3/base.py", line 360, in execute + return super().execute(query, params) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +django.db.utils.OperationalError: no such column: hr_employee.national_id +ERROR 2025-09-07 20:30:05,674 basehttp 75052 6253064192 "GET /en/hr/ HTTP/1.1" 500 235325 +INFO 2025-09-07 20:32:25,310 autoreload 77623 8747049152 Watching for file changes with StatReloader +INFO 2025-09-07 20:32:27,794 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:32:27,802 basehttp 77623 6150778880 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 20:32:27,852 basehttp 77623 6150778880 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:32:29,943 basehttp 77623 6150778880 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 20:32:30,000 basehttp 77623 6150778880 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:32:34,727 basehttp 77623 6150778880 "GET /en/inpatients/ HTTP/1.1" 200 41725 +INFO 2025-09-07 20:32:34,781 basehttp 77623 6150778880 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:32:34,782 basehttp 77623 6133952512 "GET /en/inpatients/stats/ HTTP/1.1" 200 3000 +INFO 2025-09-07 20:32:34,805 basehttp 77623 6167605248 "GET /en/inpatients/bed-grid/ HTTP/1.1" 200 611361 +INFO 2025-09-07 20:32:59,005 basehttp 77623 6167605248 "GET /en/inpatients/beds/ HTTP/1.1" 200 2109891 +INFO 2025-09-07 20:32:59,099 basehttp 77623 6167605248 "GET /static/plugins/dropzone/dist/min/dropzone.min.js HTTP/1.1" 200 114702 +INFO 2025-09-07 20:32:59,124 basehttp 77623 6167605248 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:32:59,242 basehttp 77623 6167605248 "GET /en/inpatients/beds/ HTTP/1.1" 200 2109891 +INFO 2025-09-07 20:33:01,667 basehttp 77623 6167605248 "GET /en/inpatients/beds/1619/ HTTP/1.1" 200 31653 +INFO 2025-09-07 20:33:01,702 basehttp 77623 6167605248 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:33:25,036 basehttp 77623 6167605248 "GET /en/inpatients/stats/ HTTP/1.1" 200 3000 +INFO 2025-09-07 20:33:34,007 basehttp 77623 6167605248 "GET /en/patients/ HTTP/1.1" 200 139651 +INFO 2025-09-07 20:33:34,059 basehttp 77623 6167605248 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:33:34,063 basehttp 77623 6133952512 "GET /en/patients/patient-stats/ HTTP/1.1" 200 12305 +INFO 2025-09-07 20:33:39,047 basehttp 77623 6133952512 "GET /en/patients/patientprofile/39/details/ HTTP/1.1" 200 32460 +INFO 2025-09-07 20:33:39,082 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:34:39,100 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:35:39,416 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:36:40,417 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:37:41,413 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:38:42,412 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:39:43,413 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:40:45,399 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:42:09,408 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:43:09,410 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:45:09,404 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:46:09,397 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:48:09,395 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:49:09,402 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:51:09,395 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:52:09,397 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:53:31,269 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:53:38,787 basehttp 77623 6133952512 "GET /en/patients/insurance-info/39/ HTTP/1.1" 200 36065 +INFO 2025-09-07 20:53:38,809 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:53:51,162 basehttp 77623 6133952512 "GET /en/patients/consent-forms/39/ HTTP/1.1" 200 599 +INFO 2025-09-07 20:53:56,274 basehttp 77623 6133952512 "GET /en/patients/ HTTP/1.1" 200 139651 +INFO 2025-09-07 20:53:56,326 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 20:53:56,329 basehttp 77623 6150778880 "GET /en/patients/patient-stats/ HTTP/1.1" 200 12305 +INFO 2025-09-07 20:58:11,348 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 22:29:09,343 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 22:56:12,284 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:10:41,271 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:11:38,278 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:11:38,451 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:12:39,264 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:13:40,266 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:18:49,454 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:19:50,455 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:20:47,478 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:20:47,588 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:21:48,460 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:22:49,458 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:23:50,458 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:24:51,454 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:25:48,475 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:25:48,575 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:26:49,450 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:27:50,437 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:28:51,448 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:29:52,450 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:30:49,463 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:30:49,579 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:31:50,445 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:32:51,454 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:33:52,448 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:34:53,454 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:35:50,472 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:35:50,581 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:36:51,456 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:37:52,458 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:38:53,458 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:39:54,460 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:40:51,483 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:40:51,576 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:41:52,467 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:42:53,469 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:43:54,465 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:44:55,470 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:45:52,487 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:45:52,587 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:46:53,465 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:47:54,470 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:48:55,465 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:49:56,477 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:50:53,495 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:50:53,598 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:51:54,481 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:52:55,479 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:53:56,481 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:54:57,475 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:55:54,499 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-07 23:55:54,616 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:56:55,481 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:57:56,484 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:58:57,482 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-07 23:59:58,476 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:00:55,502 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-08 00:00:55,612 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:01:56,485 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:02:57,488 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:03:58,489 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:04:59,490 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:05:56,497 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-08 00:05:56,590 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:06:57,493 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:07:58,492 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:08:59,495 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:10:00,488 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:10:57,507 basehttp 77623 6133952512 "GET /en/blood-bank/ HTTP/1.1" 200 121063 +INFO 2025-09-08 00:10:57,573 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:11:58,483 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:12:59,487 basehttp 77623 6133952512 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:13:41,726 autoreload 77623 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/accounts/forms.py changed, reloading. +INFO 2025-09-08 00:13:42,196 autoreload 15542 8747049152 Watching for file changes with StatReloader +INFO 2025-09-08 00:14:00,567 basehttp 15542 6325039104 "GET /en/htmx/system-notifications/ HTTP/1.1" 200 3840 +INFO 2025-09-08 00:14:29,118 autoreload 15542 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/accounts/views.py changed, reloading. +INFO 2025-09-08 00:14:29,485 autoreload 15863 8747049152 Watching for file changes with StatReloader +INFO 2025-09-08 01:20:56,549 autoreload 15863 8747049152 /Users/marwanalwali/manus_project/hospital_management_system_v4/hospital_management/settings.py changed, reloading. +INFO 2025-09-08 01:20:56,938 autoreload 42555 8747049152 Watching for file changes with StatReloader +INFO 2025-09-08 02:59:34,343 autoreload 86776 8747049152 Watching for file changes with StatReloader diff --git a/operating_theatre/__pycache__/flows.cpython-312.pyc b/operating_theatre/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fe415f3ef1dcfa47f513dfb2fb49b922413c284 GIT binary patch literal 187 zcmX@j%ge<81bQ<2GUTHf7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@S({m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqMu)oT9jClnU@}4l98HNQk1HnmXlvztXEKZi^C>2KczG$)vkyYXcZ$67lRldnHd=w Ii-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc yqF<0$k_i+k)=$gHFE7?BsJz8tlbfGXnv-f*#0s>55r~UHjE~HWjEqIhKo$Uo_%KQU literal 0 HcmV?d00001 diff --git a/patients/__pycache__/views.cpython-312.pyc b/patients/__pycache__/views.cpython-312.pyc index dcddb5e33280367b12cdaeb86de65adf828f1176..9d78f15d8540c9bdfd49a92d89e3ed044de6f469 100644 GIT binary patch delta 23965 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 Jky=Yr{y(eH#$5ma delta 23604 zcmbt+33!x6(tkS1OpZw)A%UDE6Cgl1l5m595Fi`^Awp0XB?p;FGBA^bo`fR^!=Z?` z*y^hyh_dP;D;{wTtE(&Pdg1}Qegf}$?yd)}e8S?jUi|Asq2yeI}+#BJD z@J2c!1#COeWj9qsAq?d9m@O>y{BxFE)p>P>T`aXQwM?#*yycrzWDoVR&; zd$Sx_oR0Hkd+iRpH^-5~`FKwsZ(m1WN_TU1_w@7TI&!`J9sRun90R-q9Rt02jy&%m z#~{Whcm{iiIEHwKI)-}l9r@k@M}fD{?&E7+1GF#8+-HhB2vxNn=d+AZ9FK z{9(>?LS-;2A&45sjWP+-n=t0^7jStNm1k4AIsAoOZm04b?#Uc}JY)J0rY~d6;U@s& zclIMxE~CuhFXBf12{V8&=I|4_d?1zQQMoz%BrYFB<%78=bNC|03?a-=#+buTW{f|d zPz8)Kho8czLc$Cqj5+*NE+0q&EYTR@{6c^BKKqtKZ`Mw2vfuubNJbenS2$=e@cfz z<}hL^H7V{eNC}ruqw?vU2AS)!I%ixJw#U%7Fh?onXNKf2q5Q=m`FWI|)t>j0PS2-; z+3f|CFLTbhD$KEfN=rgYFQxq4ko;woFAd2rbY4QO7BQLgh|Kv+rY)$_4ys=kQvY(w zFQEAc>Ar#rE)A)$nDUo}P_-JS4w_@>hi9t0}*jYIG_s>VjUy2x76dZTreX#HE%f~bUiB1X5?y6T-SnI~kS8r%J1 zF?jY=$7h+=K7}H7P$yH>#~(qveu_ZRX5Z(xmGpFe06iL zG;2Ak*Qvd|a;?>r^l56{ougE@lp0Z~no~y5batnVA63D%&`o?rMYX5O=c{&kJQWqY zg{(&_L12>Pz6PNxKwp)fI@VgrS+#XkTI=%EWnxNjUc0R_IF}I0=b=8xr)h(3p1Uuc zQg*vBK!wUq?;E~4OnEBoDz-H!lgvbEkacn)vb_Pa0qp8fR_dI~ksL)pw|I$%b$W!e zYIRtFTffA)YT&}Eb}LdvUdJkZ%m?2jm{n*{H^8LH;ILngw3^0=LHAPQnU4Yd`n6|`=2Yk-3# z7{2IlbHu|cssFoU zDhZX>?Hr8B!AJ&$teLV&^&c>}-!3Zdnn4N}fSqc4ewI=LvJECFXsLQ`Q*mprfip$s zT2xyH0ISqV1=r;DwY>t|dH`r&n)=hsxhipxy&qIzcZBQ-%mV;Vpg=GSSWu+MYQdl} z;!Snqp#G$~humqcZw&f}5Sn^y$biH<(dI6Iodmv5>7#uVDSFM%i!*eWCk83V-vICk zysAtIz&@B_kPjmJ5CI=}9m?uUhUQog0r9kY-f35tkL;-)8G3DPB^8|)-{r$p(@;$q zYC|=jLh8)y-wQOrpNRbv4A$=@{rpngMr?fZ?0kQ^u&?bnI#>??)+M+8SU5bKSXVHj zz!t(f>+Yna_gSWyWXw{z35 zOS;wR^0=B@EvW&IGS%f#wvpY$DV09*y~UN(poBzt9*dkgnN0P0aD%7&k%a}5l>p@c z&$NSosj^XH3`RafI{cRPDqw~{DO>%cmtwttJ~mgptP;je_8%aeZmFsA_*~QU9_uL59HpOrv7TS0?m zvO>K-Zcr5MdB}hX_&zo0f@8EG?!NrL{@u|fh6Nf-t;*yQ^up$a)f}wY9b+2v5JKIk z$#%1oJzqu$AA|}L)(7k`Wn1!!Y1-uFt5;7UyIxh@G~4Y{H;nIPEg;HHdC4P=RPTz{0J?z*1?uGdWOeg|?5IkkTRZSXb z=-@l-Z01(ZZ~bA?Ffj|OiW~qtlJ0Q1>`aVkgqIXsDl(Yt?%9vlQxjhVfuNlJNtu>G zs=PQu9d7L|%GCXnhXpL>@yUCIjoEVtRg#)|aOz|~%;)z>LAlxy^pIffedK+FIfE$; zIzhu^97K0(06H0lu1qOaYsn3cr)rBct&1SiN64^_RkP9>gY)t%E% zgU>MTQl`7|BjlKDzUDq_eV(n1K?i-I!R7>W)|4ipvA{V z3&U6X>~M>+72rvL-xFwekH|ko4g0AbZkt%IHeO7Avh|Sru7ITXp@OF7%)YP+l9rzV z{DA<4QBX94L8g=JO0wrGRGM{$%?yAxsqS+g@Kj=~Un59fL@dLnf^>En#(fSnfJfO& zrWg|YoLAPg>t?ApN*)v+u)92))Kq!t5Zk>W!h*ZpT{=-D^Llv>LudqAQps7l)T2{- zsUGt(~ZKd(aTS4HC-vMi%z`l#7vgKe(Jg1CvZgaJjTNU*W&`~(eOCD+~FKx znA`|C@#k1bO;kzl0Wg;j^B;Y89UGni2H+0$ z#r%s5uAiWFvQTX)tFc}Ktl?MV7p#cj{h@pjg)alVqSV4MiEwrDbpmDb4J6-Ge_ts5 zZy~t}U^4+C-Bd~5XRxp8%Cjb+&7}aT04V_MZDYFhw%-BIBz%w5eHt37o+n@|=E! zKl}#$0z3->3n>v|zT(r@7aviJ7v~u6@tZKXNA=R;W^oOc!Wb-t4(_ol&i>N2siKNJ z@gup$xo35WT}_F#sgp~jv*9oa@D;hlB$ZLw(;(L>)JOTLt#d1viE|jt!&O6U@wDY_ zH<;KT{KCt9SUt-6DY$i)%5dgfaUUhm&#keB{9oK!AN6iks(Q>BD|)DBoKK(4_L)5D z3(|hA6SIMZ01@gV*JOizHlc=jbAiscOlmIYV&OQU?ZK* zpP#2%>&{WP%(U4?hA`joR;6mPJLB9QYpr{T7^fa~cj>K~myNoDO>1}1^9Km*yu1|) ztdoI#h+4PrKLVlbE@kx$2p=D=66TCo%RF`7N{rC8k2<@YSgX&+MtbX)HtGgTGZ3{zW*6y&30MBq(Dq;C34)7#1 z@|3|y(?2o4{=fW_hsvnnMw}koKwNEnn{VRMD_D2$6 zuKG+~WH2`ctKl+rm2a&WqSnTwwPrNk7Cwf(dI9l6k8g5$8$EP9*nT)k7e;{t#|eZl zlNS+`lL$hYEN>hRjL@AA5u zLsu?s0B8pIt(vrMfT4i{40pD9-Qn;KyRW(pWaemthSer2rsU|p>Ge5Xz9SCckAQ(H-$oZ&>vWI{iTbVi@G3)n70 z^`T%7K%4sf+P>=QP3Z=Uh8iyGxlLEm3CxtMzBG=u==!xwcU5xrVA}^IJUJK@%p=7w zuI_to$5XI5Uwo{}H@6=r?%2FeblV4tIlfO>(CAc+8+xfpTQUqEMEARA^+C*fwkOR0 zQgpQgAOYY(fG&N|hLy?cz?PokGxgDy`+q&#SqsmxL!xWxFbVJuv3-KU@{#RM=bzz) zLLDl2BL|C0o`L6tqLp*-=5)2KASA z0?b|A8IK{E+n9mgZGKr%*@F2MQ)bMaIi-01FZ~jASf}RRnJ1>H)pzb%TxpEffPoqT zmIFut=E$$`Mw7u0fB|atT>)=2Sv|aFa_e_@O%=SOBDFJT)fMOcL_nwO5#P1};tI8G z+u3(iT@hV@*>u`b%>t1CW$LHLQ&s6b3C3cdWw;>!J>}=xQGLICkj;zb{V}>XZd_*U zc&FpJVcyPR?K`TN>* z-Cc+5CbM!e(iz>j2MhPv)YSX?8SE`JY^ndA3ib4^*eH1k zn$A<--k%d*Ce*t#eCOE4KD=v??PeOKGt+0W9lZl2!a2#y(CBoSpI(Nji|~ z%GFS{7Q1?MS1(oYU~K+v80d1;twj4PkXl8l(3{b66arkWdhg3pS3ek-Xt`moq8_^3 zdOaE&5%q?LA|nh^Uqs={0Iv|xW9l2sxY|kG>D}GF3OdoMaXTsAaaVba;~z3*E{yml zHA0kq@Zmx~o3hX-+m3G8M|5S%5`pC?J8;d+tTXRcFuE~F5!LiX5immScB4iGE%v~L zR7pdV^6%*t^&})eQKd+4 zbBTuENi{FI*MItDbqP(XHW3}YSG=l@w9@Eni5dA>!>k;I#JI*l^gzZg!=TU z*UolFVn;8`xc*4}S{v91z5;xSl`xLF3OQs{h5HH&RyPW@E+(~g-M+tykyv*nauT)q zzI#anZE5POXlGMH4{V&rZb5g&07X%z8?#zeTUs0#b(Ho zfh?;SB1IWo_HYqlc@{$gph1uGxvFG!T?IcXGHzMXZ}48zSonIk_KRJkx}^J;@URqh z$uo4ls-6C;NNX+o>?#*Asn6_~)v;8Y5z(||D;K}k810EInle%8^DQ;f_$yq zgydBO^zKb{ZrQZDg5Lf3=uJ_Byc(#@LQD8mB&U^AJ3T(gcpB9wucHbhT8F(bBAiax zv){b_>9Ta zA)ace`n-&q+$lPd=q^-iRO!oUmYZncjjI0T>pN2Wiu(SQp}A+ISl$47nba-nqXQ|b z`qlIb4*btTZZ?QGe{#`X2XfziHPwcdcL#C6w;@auGsPfv`n_)I_1F8W#jjx_oc%^x z>-N{u#h~+|9Q0gATgdxnzad0FmJAF` zCv^yAuJ+S3k)ob^I$C}AW`gp)ndLYOm1*ao@(JKgeYlN=?m*?g-^{YyPKD2@Zf|WN zZsHc=v9~@Hbe6I8P)h1;)SOf`*h`t*hYmIM{Gq`e-r;<6DBJ%yP!~~WbOtjQY4!&^ zTMM$L7PD>n6Uqhx{05)|fDP#mq~J!#=#(NI9G+K3`-ynK2qw^tzk3BO{^W|ls+4yU z4TqpHZ?ndvs^|aur@-9q`kRR8b4E>RpXy8MkME4I2B!M;JNdRxLB?GGi&XyMOfg=~ zIy|~`Hs+dU%+*|{(0SeJb&>mY8e7|-0n=?hcWu4PNw$TI73QhO1WJ~ymJ`&W!@d05 zs8eH$yB(<=0G(KM5QOmhW)8E*Wh3wleu2VH{7S@t2xM_=$Imq6Z>ZJ@@QXt0)|w-W zaZw0Gc<<=yaDJ20wfA6y0CLILV=mKn3*B1X;Ptwjq!IY5Ti+crILJGCl`35{aVNO| zZ29#ljyLJKAuD*e+@X%WJJ$c(_Sxknc4ln`P&>g94h@)9%*AMm&5f6f%qr#$HU%O2 z)r2hDTxONkP_0h(lEyB;yC{l`I-ecr2~|#KyNXqyhJ2K|w70(XUK%k>TmO_uR}mi^ z%j6XhWejC1bs$m^7C0z8@o_$vIZr%Fv zKP~f@pm}sPiG@7fYGZ?2fPtC7br_g;M$FO)$Zi4lXMocH_fQ#;^%By2kR#N~|L!-= z%>PK3mbjs=RgG>5uiE4)k*leZ9#vXgGIeIjbW#Vic7f{mMUI%RrhW0$)Ea6@>#G)B z*8yY!nC^s)1LSX5ICh5DFo^&h3uLQF$J6?m!9xmaBdXA&>#BSejV|ex{ZQssYmet# zun0+ho#aJoI{JAIw04)SYOI&Qy73wDLj>^81MF9C9`7US)epzh+h1E}{O@4v(P&y# zn_Fl9Z>;D(_Hf@(hx(4%H~j6s7ahvDsI}tD<%ky!olFx4)xS@!i?Pv={HIDUNl_w8;-({iOnJ>EAta$A_wsy_Tr zu6F;e^q|{*D#{uKd0eS-KIz%*O6wjX6Myr=@}gDgsX|epHk?`*N6Zg$P#ry$KlNp* zM+Te=U&GYc#+X)|xy36FW>h|cD!k|(MD`#+ohte&y^wjyB6=Q$%vE$QS&P8mj$2uE z{a3lx;W1QvP(Ah41>=vzCEYyx+Sx}EQ?<;knMab+weefWA5Q9jD5?KfQITn}TjEc| zg~g>Ew&fhM<-Bd{dnBdb;gq~XDS3ZO8LT3|F1J?F5Y^$Ts61I+`Smp;HB8K6cp+A# zj_N~*&uk)}E{Yh( z(zr*x_v6$FCe>X@hpc!YQsj1Tqc?OEST(BrC%bq;`G3l)H`fG))Z>eqo$jXD4YkD- ztgqH1d`(gwMr)QRWZV7-o=qmWWX@5K=TmQYeXZe8*zH77o8UQx5B{#u&}%23F(g~Hk5Hdw{V`I^ z=?{_mT-#|8y(jU&9BF)k(z81GB&>M0s(chHo+=>7L{$| zqeM-_P=h^pqkj-x#*C52kY~1F2SUq;{lVwjTd`u0RVQT25M_7v(t6rNN&;^ZuEw-C z1Kg;Mw}~_>x0s||ZWCF4uu+fl(pLlY^+aA~2;X>v1HS1t_;iv&0+^lF&r$I^?Pr@vUCK=59XUG?FxBw2Mu?!t(YF%K z5+6&@&4sZX{}UYNYf5!sF$haw!d6!V8_J)k+I2Qnc_gjvmN;=S#S3kJj~AyR%0rYf z$TdB>QMwzXyJ@wdHV;zcY4RbA2_-dT!6qV;vgCUWSrFd%?uP>hy=04(m+W)ep<2AsxjHkhrf=Ee69gwxwkR-B2xps4s=xvFhvVCoj zCyCd<;VXNJ`yxje9G--+I-P!`Q#Z8Yp>ewd+wqss^ERzCU1TOtKzb4ZJ*tsD4kP0x zf6&&ai*X~bqrzjn3=zl3A*lE>%K8Ef1Q;GH^PFztA{SY~DOaa1eM5DyDYi^&v| z#9i9OnPRy3kG3{bq(*}YB#`mi_DqpA`WtF{4BNBNT?Xwf47c#mxK;*&W)<-Xhb_%r-Y#+&8Ov0UAaFaO_lw z)DVDd0(y7eeYq$uBAv&VPg}(a@o7)zbB?>r9a;LQ|u#3}?Rc9Bdv|wy2fN8!+%1nGRice$KY=9`J zt9Pxe@=zFP$d?VAru{xwjIjC!c&!yRE+{$nAxGdJ>?8%HroP;@XGionV&sS$~mN_$_sEjO`l)FNdO0 zPRJgJ-?@cIT`L+OGR37@IsV(Btr;NF{mk%KGMyZ6ljSr;mr4`YqbTgHY9i;(w6N9e zLM!y-&?)-bJr#Wm9k2tup0SE`+e~j`gKR41o93NdrK;QFNO?-N#4K@f+sgw*c67#>RbrbahKZ3QvD6LC zp!Otvf~+HDvZG2!`anG3=QPbdOcb@N!DGY3RB@5^^)OLtD?%Oml$%VJRytga&t_$c zH@?(#(o(>AC!{RdOMj>B87?OHAzV2PtxVze3lT2XFsrN{MLLAXOwyFMDMWT`d;?Bj zbBCUd&Onx}@Jytj2a>+h4jh`!@*{b6na53SaQR9anu_s)fi3_Vu`DEggiV)wAdbG@ z4wI|`EPeWFo4$VZxa#R{oUI3>pvMQD9(hZj@p&bLoFU85oH_C%dSl}EauvV~B#J6o6DO|RYGyAU0dx$mQb9m|}Oh#!Llf)mK zF_gjgT=f)R=&_Bm0Ut4vmDeL1tH{yA$n!q+m<}S@YQV_LBxJi2sIB3@PbSt%(^D>@4|fpAoWB zJ32+ow{NCaCERRxxE`KgNM8(ls@&e-7Dt;sRa_`;)3!_%OM71vtSl8JgOxzc9a{Hd zQ7CTLCKU@id9SKsF|GHOb2qp{`?^^4v1(M4{95m6;&$r*q&02dG%>M#fzhGo7(aA^ zj*yr>+%0*%RdgmX2({ZCBPfCQkiP*imr@{xWUp+lo1k};o!r<+YOPzyW0K2aPZ`x* z@Al&Z5IGzj({Ek?kEf;f&~=%+ElITpNukYyAS zn*g>DpqQ{@OZf-%0V2$X;c}vOWPupnu4KuVlI6ZjTXdc4OEF)m0 z7oru<pv>5eQxu^6`!b5QUm*MoZSf1m_?~xv9n_VLo3+u}u^+oN`S}`i~B}%s>7q4oh&-qeTxENgx9Q5;qpJIcnW|cLW@&Y)ikyAqG!2u=xv{A93yC6zqmeux9`Sw z0~5SUi(W6Xdtk3Xq%q%lE(f%6>qSO?W&%f)%pee?$8zt+cIsJ-`JC3Wo;Cm-b>(RK^Byb4?Q1X=pP}chfFCkhQS>7y zyupapdT$W@{cPgQz%zI-qbE9-lKXAQ=cBOds_HtIJdGYAr~}>NZ1y(#LX00YS&v-O z(BP4sOkhfg+M0%sb;=qMHj3N}C^Z^&3}i;PxzANZmf?eq)9$3v$SAu}z7${?fCs<}P*1@9 za2kO(t0{{Wp-0Rqp5qSt=xdAn^s9GYNQ%8kdrK3&6Aps%2xr3*!+*c3{iuoAwsdrp z0g$Q9zf+9$2iKY&L-%3z#%HA8qXG^y==RXnw6Z}iBdVbD$M7u6{jP<;!6*WMp=g-H z^gN4upDmDf&n6AwLELW_(u6EVn2(5?V}0{1C(n{)WD)r0AGWVx6vMz?oQCj%j;?E*Od+}~@bOx{2m(UQBVuMF4$Oen;0674C2vBJkY^4wj ze3F0AKG`O=rca}adJo>z2jT}>W^Ot?&eXQvBkmC~TK;yiG~Q3+=@Ijar;+h0(;nC^ zMv$XAx?Plr_q2gK#EeW1rXhP8mCXw421nF=wHtPb+)f6h{cx58>);;MFbeNua-E`B zJ|7we#Bcz_)*MVrMBMU001l8oLh3SL!{81~r!0Mki@20W%lcP2t> zx>roe3o4MYV>nAZ^WnWB-BLw^-q3dXUJ(%`O4`C764zVOUj!X&E3QEbQ7AtEldH6c zekZmMVD1&Ou{3@lif(wYeKAgjP7{KB#A%@|dqfoVgq76e=^V@hcjM)Af@`$>kBFpX zMD%oiM6Z}U6-EWQUHj}2k(s&<>{-ntG~%#4PVNFnTC~i)Vpw(~(JYq(Z064CSACkA z@lKV_AbfI$=GiOe`Ii81#tqD1j$2+u-yC`J?wF4i5^0KhOjT{Ibk&mEGOkfw=%EJS z8Z_Ag&rXvFoA9Ve&F47PARVpOptCCh)&g{#hg_#^ zdQ|k!;!DDAG)~6|)HoaJsol3%^t8z>)P6z&g{q6ROLWnz?Wae@betH{!=SeEC&W)8 z!Ia+-3~kkxJt+#Kv2+^+3p zOoAEdHK1oGm~JhZJ8w?WY`IbU;CZn{G;4MH#boi7wr9VXN89zE_lrzx8ERjr+5as1 zi6dI^pGEmJkV~;N&h6~vvgqW)&Z>KX-S{YP4o!_;<&c%+Sq((jUxekt{JJKu#|SubjB8eAs>#Yu<|70BvB$P*GhPsxc?ck64EpACNhealc){5I zlALkucH;{oWj^zQEyE-b#b;FJJr49yZbBDV0nk7EFjyx+aVQWBI^{Lmw=alcBe$c$ zRuGef6zm2+kTwJf5<2Q5pIKk=7cwEcss2N4YyKjpS#72i@6%p?O^mmKi7g`xh7CO+ zG8cBmo(C}Ee$3LCDpKUr0uu;45;ZlAtFwNg5|c&SGt#b1%O2_}UHkI^aU&^K>FZ)` z#9-*uwC}sktmn5f_P`sZFEKx+maQ49$|~)xcGN-<s#apeFQ%Db2lXf@j9XALwRm2|yy8n|YM&hu ziP3FTN~UVFCXNb+*r{D{R17_{YuErHa6==zvia;u}45v)JHqSG!%lX_7Zg(0h7^z-EZe4EsORT(QT$31qR; zW5woKVFN;{&$D6+!u)@gYIb;QmldY>?D#G#aE~lsqpI86zItD5wj}bJl#gH-UWoT- z*Z)flEqV#G2ksOCdMsJH_o5~d5Z2ObGM$xoT$Naq5{p)*YybV1$g&zcN3HkA;-6xT zCO)B`c`;XMa7D@mP(EI-U4;oxp+jT2g1hGG{D|1DM^yV(=(fOSuCA%6Q68lFx^*Sp zV7sIqZT#P`(ol;BlF=D6>_Z5R4?1tv9{xmR&fEu7aG|wdE8K%IUk8dc$XMc_mz~ld zfOs1KqsrZ={EpWBQ_(Z4oYHy^zECh$I_@gz-J?88HJ@sm{HYip9#=_~@aiwr-W`Oy20 z<|YK_9NG>7x&=T1>;-rR;01tp0Nw-m9N+}NHvssB5&n$~{s9L5eE|NfoWIlNuaWuN zSpGDVzwqNP==}Wc7k>oBpTO|vCHyS}J`tce006JRCEixcTLEy(%nxVzH7GxA4L~;<50QX%S+!IGCA#uyFb-nO}u*_QcZUwoktl?}$ir{r>>T C#iRKE diff --git a/patients/flows.py b/patients/flows.py new file mode 100644 index 00000000..b7455331 --- /dev/null +++ b/patients/flows.py @@ -0,0 +1,761 @@ +# """ +# Viewflow workflows for patients app. +# Provides patient registration, consent management, and record management 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 PatientProfile, ConsentForm, ConsentTemplate, PatientNote +# from .views import ( +# PatientRegistrationView, IdentityVerificationView, InsuranceVerificationView, +# ConsentCollectionView, MedicalHistoryView, EmergencyContactView, +# ConsentPresentationView, ConsentSigningView, ConsentWitnessView, +# ConsentVerificationView +# ) +# +# +# class PatientRegistrationProcess(Process): +# """ +# Viewflow process model for patient registration +# """ +# patient = ModelField(PatientProfile, help_text='Associated patient') +# +# # Process status tracking +# patient_created = models.BooleanField(default=False) +# identity_verified = models.BooleanField(default=False) +# insurance_verified = models.BooleanField(default=False) +# consents_collected = models.BooleanField(default=False) +# medical_history_collected = models.BooleanField(default=False) +# emergency_contacts_added = models.BooleanField(default=False) +# registration_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Patient Registration Process' +# verbose_name_plural = 'Patient Registration Processes' +# +# +# class PatientRegistrationFlow(Flow): +# """ +# Patient Registration Workflow +# +# This flow manages the complete patient registration process including +# identity verification, insurance verification, and consent collection. +# """ +# +# process_class = PatientRegistrationProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_registration) +# .Next(this.create_patient_record) +# ) +# +# create_patient_record = ( +# flow_view(PatientRegistrationView) +# .Permission('patients.can_register_patients') +# .Next(this.verify_identity) +# ) +# +# verify_identity = ( +# flow_view(IdentityVerificationView) +# .Permission('patients.can_verify_identity') +# .Next(this.verify_insurance) +# ) +# +# verify_insurance = ( +# flow_view(InsuranceVerificationView) +# .Permission('patients.can_verify_insurance') +# .Next(this.parallel_data_collection) +# ) +# +# parallel_data_collection = ( +# flow_func(this.start_parallel_collection) +# .Next(this.collect_consents) +# .Next(this.collect_medical_history) +# .Next(this.collect_emergency_contacts) +# ) +# +# collect_consents = ( +# flow_view(ConsentCollectionView) +# .Permission('patients.can_collect_consents') +# .Next(this.join_data_collection) +# ) +# +# collect_medical_history = ( +# flow_view(MedicalHistoryView) +# .Permission('patients.can_collect_medical_history') +# .Next(this.join_data_collection) +# ) +# +# collect_emergency_contacts = ( +# flow_view(EmergencyContactView) +# .Permission('patients.can_collect_emergency_contacts') +# .Next(this.join_data_collection) +# ) +# +# join_data_collection = ( +# flow_func(this.join_parallel_collection) +# .Next(this.finalize_registration) +# ) +# +# finalize_registration = ( +# flow_func(this.complete_registration) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_registration) +# +# # Flow functions +# def start_registration(self, activation): +# """Initialize the registration process""" +# process = activation.process +# +# # Log registration start +# self.log_registration_start(process.patient) +# +# # Notify registration staff +# self.notify_registration_staff(process.patient) +# +# def start_parallel_collection(self, activation): +# """Start parallel data collection tasks""" +# process = activation.process +# +# # Create parallel collection tasks +# self.create_collection_tasks(process.patient) +# +# def join_parallel_collection(self, activation): +# """Wait for all data collection to complete""" +# process = activation.process +# +# # Check if all collection is completed +# if (process.consents_collected and +# process.medical_history_collected and +# process.emergency_contacts_added): +# +# # Proceed to finalization +# self.notify_registration_ready(process.patient) +# +# def complete_registration(self, activation): +# """Finalize the registration process""" +# process = activation.process +# patient = process.patient +# +# # Update patient status +# patient.registration_status = 'COMPLETED' +# patient.save() +# +# # Generate MRN if not already assigned +# if not patient.mrn: +# patient.mrn = self.generate_mrn() +# patient.save() +# +# # Mark process as completed +# process.registration_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_registration_completion(patient) +# +# # Create patient chart +# self.create_patient_chart(patient) +# +# def end_registration(self, activation): +# """End the registration workflow""" +# process = activation.process +# +# # Generate registration summary report +# self.generate_registration_summary(process.patient) +# +# # Update registration metrics +# self.update_registration_metrics(process.patient) +# +# # Helper methods +# def log_registration_start(self, patient): +# """Log registration start""" +# # This would log the registration start +# pass +# +# def notify_registration_staff(self, patient): +# """Notify registration staff of new patient""" +# from django.contrib.auth.models import Group +# +# registration_staff = User.objects.filter( +# groups__name='Registration Staff' +# ) +# +# for staff in registration_staff: +# send_mail( +# subject=f'New Patient Registration: {patient.get_full_name()}', +# message=f'New patient registration started for {patient.get_full_name()}.', +# from_email='registration@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def create_collection_tasks(self, patient): +# """Create data collection tasks""" +# # This would create tasks in a task management system +# pass +# +# def notify_registration_ready(self, patient): +# """Notify that registration is ready for completion""" +# registration_staff = User.objects.filter( +# groups__name='Registration Staff' +# ) +# +# for staff in registration_staff: +# send_mail( +# subject=f'Registration Ready: {patient.get_full_name()}', +# message=f'Patient registration for {patient.get_full_name()} is ready for completion.', +# from_email='registration@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_mrn(self): +# """Generate unique Medical Record Number""" +# from django.utils.crypto import get_random_string +# return f"MRN{timezone.now().strftime('%Y%m%d')}{get_random_string(6, '0123456789')}" +# +# def notify_registration_completion(self, patient): +# """Notify relevant parties of registration completion""" +# # Notify patient if email available +# if patient.email: +# send_mail( +# subject='Registration Complete', +# message=f'Welcome {patient.first_name}! Your registration is complete. Your MRN is: {patient.mrn}', +# from_email='registration@hospital.com', +# recipient_list=[patient.email], +# fail_silently=True +# ) +# +# def create_patient_chart(self, patient): +# """Create initial patient chart""" +# # This would create the initial patient chart +# pass +# +# def generate_registration_summary(self, patient): +# """Generate registration summary report""" +# # This would generate a comprehensive registration report +# pass +# +# def update_registration_metrics(self, patient): +# """Update registration metrics""" +# # This would update registration performance metrics +# pass +# +# +# class ConsentManagementProcess(Process): +# """ +# Viewflow process model for consent management +# """ +# consent_form = ModelField(ConsentForm, help_text='Associated consent form') +# +# # Process status tracking +# consent_presented = models.BooleanField(default=False) +# patient_reviewed = models.BooleanField(default=False) +# questions_answered = models.BooleanField(default=False) +# consent_signed = models.BooleanField(default=False) +# witness_signed = models.BooleanField(default=False) +# consent_verified = models.BooleanField(default=False) +# consent_filed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Consent Management Process' +# verbose_name_plural = 'Consent Management Processes' +# +# +# class ConsentManagementFlow(Flow): +# """ +# Consent Management Workflow +# +# This flow manages the consent collection process including presentation, +# review, signing, witnessing, and verification. +# """ +# +# process_class = ConsentManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_consent_process) +# .Next(this.present_consent) +# ) +# +# present_consent = ( +# flow_view(ConsentPresentationView) +# .Permission('patients.can_present_consents') +# .Next(this.patient_review) +# ) +# +# patient_review = ( +# flow_view(PatientConsentReviewView) +# .Permission('patients.can_review_consents') +# .Next(this.answer_questions) +# ) +# +# answer_questions = ( +# flow_view(ConsentQuestionView) +# .Permission('patients.can_answer_consent_questions') +# .Next(this.sign_consent) +# ) +# +# sign_consent = ( +# flow_view(ConsentSigningView) +# .Permission('patients.can_sign_consents') +# .Next(this.witness_consent) +# ) +# +# witness_consent = ( +# flow_view(ConsentWitnessView) +# .Permission('patients.can_witness_consents') +# .Next(this.verify_consent) +# ) +# +# verify_consent = ( +# flow_view(ConsentVerificationView) +# .Permission('patients.can_verify_consents') +# .Next(this.file_consent) +# ) +# +# file_consent = ( +# flow_func(this.complete_consent_process) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_consent_process) +# +# # Flow functions +# def start_consent_process(self, activation): +# """Initialize the consent process""" +# process = activation.process +# consent = process.consent_form +# +# # Update consent status +# consent.status = 'PENDING' +# consent.save() +# +# # Notify relevant staff +# self.notify_consent_required(consent) +# +# def complete_consent_process(self, activation): +# """Finalize the consent process""" +# process = activation.process +# consent = process.consent_form +# +# # Update consent status +# if consent.is_fully_signed: +# consent.status = 'SIGNED' +# else: +# consent.status = 'DECLINED' +# +# consent.save() +# +# # Mark process as completed +# process.consent_filed = True +# process.save() +# +# # Send completion notifications +# self.notify_consent_completion(consent) +# +# # File consent in patient record +# self.file_consent_in_record(consent) +# +# def end_consent_process(self, activation): +# """End the consent workflow""" +# process = activation.process +# +# # Generate consent summary report +# self.generate_consent_summary(process.consent_form) +# +# # Helper methods +# def notify_consent_required(self, consent): +# """Notify staff that consent is required""" +# nursing_staff = User.objects.filter( +# groups__name='Nursing Staff' +# ) +# +# for staff in nursing_staff: +# send_mail( +# subject=f'Consent Required: {consent.patient.get_full_name()}', +# message=f'Consent form "{consent.template.name}" required for {consent.patient.get_full_name()}.', +# from_email='consents@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_consent_completion(self, consent): +# """Notify relevant parties of consent completion""" +# # Notify ordering physician if applicable +# if hasattr(consent, 'ordering_physician') and consent.ordering_physician: +# if consent.ordering_physician.email: +# send_mail( +# subject=f'Consent {consent.status}: {consent.patient.get_full_name()}', +# message=f'Consent form "{consent.template.name}" has been {consent.status.lower()}.', +# from_email='consents@hospital.com', +# recipient_list=[consent.ordering_physician.email], +# fail_silently=True +# ) +# +# def file_consent_in_record(self, consent): +# """File consent in patient record""" +# # This would file the consent in the patient's medical record +# pass +# +# def generate_consent_summary(self, consent): +# """Generate consent summary report""" +# # This would generate a comprehensive consent report +# pass +# +# +# class PatientRecordManagementProcess(Process): +# """ +# Viewflow process model for patient record management +# """ +# patient_id = CharField(max_length=50, help_text='Patient identifier') +# record_action = CharField(max_length=20, help_text='Record management action') +# +# # Process status tracking +# record_requested = models.BooleanField(default=False) +# authorization_verified = models.BooleanField(default=False) +# record_prepared = models.BooleanField(default=False) +# quality_checked = models.BooleanField(default=False) +# record_delivered = models.BooleanField(default=False) +# delivery_confirmed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Patient Record Management Process' +# verbose_name_plural = 'Patient Record Management Processes' +# +# +# class PatientRecordManagementFlow(Flow): +# """ +# Patient Record Management Workflow +# +# This flow manages patient record requests including authorization, +# preparation, quality checking, and delivery. +# """ +# +# process_class = PatientRecordManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_record_management) +# .Next(this.verify_authorization) +# ) +# +# verify_authorization = ( +# flow_view(RecordAuthorizationView) +# .Permission('patients.can_verify_record_authorization') +# .Next(this.prepare_record) +# ) +# +# prepare_record = ( +# flow_view(RecordPreparationView) +# .Permission('patients.can_prepare_records') +# .Next(this.quality_check) +# ) +# +# quality_check = ( +# flow_view(RecordQualityCheckView) +# .Permission('patients.can_quality_check_records') +# .Next(this.deliver_record) +# ) +# +# deliver_record = ( +# flow_view(RecordDeliveryView) +# .Permission('patients.can_deliver_records') +# .Next(this.confirm_delivery) +# ) +# +# confirm_delivery = ( +# flow_func(this.complete_record_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_record_management) +# +# # Flow functions +# def start_record_management(self, activation): +# """Initialize the record management process""" +# process = activation.process +# +# # Log record request +# self.log_record_request(process.patient_id, process.record_action) +# +# # Notify records staff +# self.notify_records_staff(process.patient_id, process.record_action) +# +# def complete_record_management(self, activation): +# """Finalize the record management process""" +# process = activation.process +# +# # Mark delivery as confirmed +# process.delivery_confirmed = True +# process.save() +# +# # Generate delivery confirmation +# self.generate_delivery_confirmation(process.patient_id, process.record_action) +# +# def end_record_management(self, activation): +# """End the record management workflow""" +# process = activation.process +# +# # Generate record management summary +# self.generate_record_summary(process.patient_id, process.record_action) +# +# # Helper methods +# def log_record_request(self, patient_id, action): +# """Log record request""" +# # This would log the record request +# pass +# +# def notify_records_staff(self, patient_id, action): +# """Notify records staff""" +# records_staff = User.objects.filter( +# groups__name='Medical Records' +# ) +# +# for staff in records_staff: +# send_mail( +# subject=f'Record Request: {patient_id}', +# message=f'Record {action} requested for patient {patient_id}.', +# from_email='records@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def generate_delivery_confirmation(self, patient_id, action): +# """Generate delivery confirmation""" +# # This would generate delivery confirmation +# pass +# +# def generate_record_summary(self, patient_id, action): +# """Generate record management summary""" +# # This would generate record management summary +# pass +# +# +# class PatientTransferProcess(Process): +# """ +# Viewflow process model for patient transfers between facilities +# """ +# patient_id = CharField(max_length=50, help_text='Patient identifier') +# transfer_type = CharField(max_length=20, help_text='Type of transfer') +# +# # Process status tracking +# transfer_requested = models.BooleanField(default=False) +# receiving_facility_contacted = models.BooleanField(default=False) +# transfer_approved = models.BooleanField(default=False) +# records_prepared = models.BooleanField(default=False) +# transport_arranged = models.BooleanField(default=False) +# patient_transferred = models.BooleanField(default=False) +# transfer_confirmed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Patient Transfer Process' +# verbose_name_plural = 'Patient Transfer Processes' +# +# +# class PatientTransferFlow(Flow): +# """ +# Patient Transfer Workflow +# +# This flow manages patient transfers between facilities including +# coordination, approval, preparation, and execution. +# """ +# +# process_class = PatientTransferProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_transfer) +# .Next(this.contact_receiving_facility) +# ) +# +# contact_receiving_facility = ( +# flow_view(FacilityContactView) +# .Permission('patients.can_contact_facilities') +# .Next(this.approve_transfer) +# ) +# +# approve_transfer = ( +# flow_view(TransferApprovalView) +# .Permission('patients.can_approve_transfers') +# .Next(this.parallel_preparation) +# ) +# +# parallel_preparation = ( +# flow_func(this.start_parallel_preparation) +# .Next(this.prepare_records) +# .Next(this.arrange_transport) +# ) +# +# prepare_records = ( +# flow_view(TransferRecordPreparationView) +# .Permission('patients.can_prepare_transfer_records') +# .Next(this.join_preparation) +# ) +# +# arrange_transport = ( +# flow_view(TransportArrangementView) +# .Permission('patients.can_arrange_transport') +# .Next(this.join_preparation) +# ) +# +# join_preparation = ( +# flow_func(this.join_parallel_preparation) +# .Next(this.execute_transfer) +# ) +# +# execute_transfer = ( +# flow_view(TransferExecutionView) +# .Permission('patients.can_execute_transfers') +# .Next(this.confirm_transfer) +# ) +# +# confirm_transfer = ( +# flow_func(this.complete_transfer) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_transfer) +# +# # Flow functions +# def start_transfer(self, activation): +# """Initialize the transfer process""" +# process = activation.process +# +# # Log transfer request +# self.log_transfer_request(process.patient_id, process.transfer_type) +# +# # Notify transfer coordinator +# self.notify_transfer_coordinator(process.patient_id, process.transfer_type) +# +# def start_parallel_preparation(self, activation): +# """Start parallel preparation tasks""" +# process = activation.process +# +# # Create preparation tasks +# self.create_preparation_tasks(process.patient_id) +# +# def join_parallel_preparation(self, activation): +# """Wait for all preparation to complete""" +# process = activation.process +# +# # Check if all preparation is completed +# if process.records_prepared and process.transport_arranged: +# # Proceed to transfer execution +# self.notify_transfer_ready(process.patient_id) +# +# def complete_transfer(self, activation): +# """Finalize the transfer process""" +# process = activation.process +# +# # Mark transfer as confirmed +# process.transfer_confirmed = True +# process.save() +# +# # Send confirmation notifications +# self.notify_transfer_completion(process.patient_id) +# +# def end_transfer(self, activation): +# """End the transfer workflow""" +# process = activation.process +# +# # Generate transfer summary report +# self.generate_transfer_summary(process.patient_id, process.transfer_type) +# +# # Helper methods +# def log_transfer_request(self, patient_id, transfer_type): +# """Log transfer request""" +# # This would log the transfer request +# pass +# +# def notify_transfer_coordinator(self, patient_id, transfer_type): +# """Notify transfer coordinator""" +# coordinators = User.objects.filter( +# groups__name='Transfer Coordinators' +# ) +# +# for coordinator in coordinators: +# send_mail( +# subject=f'Patient Transfer Request: {patient_id}', +# message=f'{transfer_type} transfer requested for patient {patient_id}.', +# from_email='transfers@hospital.com', +# recipient_list=[coordinator.email], +# fail_silently=True +# ) +# +# def create_preparation_tasks(self, patient_id): +# """Create preparation tasks""" +# # This would create preparation tasks +# pass +# +# def notify_transfer_ready(self, patient_id): +# """Notify that transfer is ready""" +# # This would notify that transfer is ready +# pass +# +# def notify_transfer_completion(self, patient_id): +# """Notify transfer completion""" +# # This would notify transfer completion +# pass +# +# def generate_transfer_summary(self, patient_id, transfer_type): +# """Generate transfer summary""" +# # This would generate transfer summary +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_verify_insurance(patient_id): +# """Background task to automatically verify insurance""" +# try: +# # This would perform automated insurance verification +# return True +# except Exception: +# return False +# +# +# @celery.job +# def monitor_consent_expiry(): +# """Background task to monitor consent expiry""" +# try: +# # This would monitor expiring consents +# return True +# except Exception: +# return False +# +# +# @celery.job +# def generate_patient_reports(): +# """Background task to generate patient reports""" +# try: +# # This would generate patient reports +# return True +# except Exception: +# return False +# +# +# @celery.job +# def auto_schedule_follow_ups(patient_id): +# """Background task to automatically schedule follow-ups""" +# try: +# # This would schedule follow-up appointments +# return True +# except Exception: +# return False +# diff --git a/patients/views.py b/patients/views.py index f6983794..7f40554b 100644 --- a/patients/views.py +++ b/patients/views.py @@ -1,6 +1,7 @@ """ Patients app views for hospital management system with comprehensive CRUD operations. """ +import uuid from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import login_required @@ -17,6 +18,7 @@ from django.core.paginator import Paginator from datetime import timedelta, date from appointments.models import AppointmentRequest +from core.models import AuditLogEntry from .models import ( PatientProfile, EmergencyContact, InsuranceInfo, ConsentTemplate, ConsentForm, PatientNote @@ -2288,7 +2290,7 @@ class ConsentManagementView(LoginRequiredMixin, PermissionRequiredMixin, Templat # Get expired/expiring consents today = timezone.now().date() - expiry_threshold = today + timezone.timedelta(days=30) + expiry_threshold = today + timedelta(days=30) expiring_consents = ConsentForm.objects.filter( patient__tenant=self.request.user.tenant, @@ -2359,14 +2361,10 @@ class ConsentManagementView(LoginRequiredMixin, PermissionRequiredMixin, Templat return redirect('patients:consent_management') # Process template form - template_form = ConsentTemplateForm( - request.POST, - user=request.user, - tenant=request.user.tenant - ) + template_form = ConsentTemplateForm - if template_form.is_valid(): - template = template_form.save() + if template_form.is_valid: + template = template_form.save messages.success( request, f"Consent template '{template.name}' created successfully." @@ -2718,7 +2716,14 @@ class ConsentManagementView(LoginRequiredMixin, PermissionRequiredMixin, Templat # 'patient': patient # }) # -# + +@login_required +def insurance_details_api(request, insurance_id): + insurance_info = get_object_or_404(InsuranceInfo, pk=insurance_id) + return JsonResponse({'insurance_info': insurance_info}) + + + # @login_required # def insurance_info_list(request, patient_id): # """ diff --git a/pharmacy/__pycache__/flows.cpython-312.pyc b/pharmacy/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c113189398f1abcf4c6960fee6149e48fc07e2a8 GIT binary patch literal 178 zcmX@j%ge<81bQ<2GQLMJFgylv(7|UGpvZKFN(N0vzm*I{OhDdekeXkC`k}?CMaBBL ziACj!d5JmYi8+}-PF`tod_hruR%&vIenx(AL1sx}PCQUJF+DXmHLoPTxU#q;H8;M@ zM86;-u_!k&xl%tZC%?Q{ub}c4hfQvNN@-52T@fqL21Xz*1~EP|Gcqz3F#}lu>1r_4 literal 0 HcmV?d00001 diff --git a/pharmacy/flows.py b/pharmacy/flows.py new file mode 100644 index 00000000..a315a720 --- /dev/null +++ b/pharmacy/flows.py @@ -0,0 +1,672 @@ +# """ +# 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 +# diff --git a/pyproject.toml b/pyproject.toml index 36ef7027..04669975 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,45 +4,61 @@ version = "0.1.0" description = "Add your description here" requires-python = ">=3.12" dependencies = [ + "base>=0.0.0", "black>=25.1.0", - "boto3>=1.40.1", + "boto3==1.40.25", + "botocore==1.40.25", "celery>=5.5.3", - "coverage>=7.10.2", + "charset-normalizer==3.4.3", + "coverage==7.10.6", "crispy-bootstrap5>=2025.6", - "django>=5.2.4", - "django-allauth>=65.10.0", - "django-anymail>=13.0.1", + "cron-descriptor==2.0.6", + "decorators>=2.0.7", + "django==5.2.6", + "django-allauth==65.11.1", + "django-anymail==13.1", "django-celery-beat>=2.8.1", "django-cors-headers>=4.7.0", "django-crispy-forms>=2.4", "django-debug-toolbar>=6.0.0", "django-extensions>=4.1", "django-filter>=25.1", - "django-guardian>=3.0.3", + "django-guardian==3.1.0", "django-health-check>=3.20.0", "django-otp>=1.6.1", "django-redis>=6.0.0", "django-storages>=1.14.6", - "djangorestframework>=3.16.0", + "django-viewflow>=2.2.12", + "djangorestframework==3.16.1", "drf-spectacular>=0.28.0", "factory-boy>=3.3.3", + "faker==37.6.0", + "filelock==3.19.1", "flake8>=7.3.0", "gunicorn>=23.0.0", + "identify==2.6.14", + "jsonschema==4.25.1", "mysqlclient>=2.2.7", "openpyxl>=3.1.5", - "pandas>=2.3.1", + "pandas==2.3.2", "pillow>=11.3.0", - "pre-commit>=4.2.0", + "platformdirs==4.4.0", + "pre-commit==4.3.0", + "prompt-toolkit==3.0.52", "psutil>=7.0.0", "psycopg2-binary>=2.9.10", + "pytest==8.4.2", "pytest-django>=4.11.1", "python-dateutil>=2.9.0.post0", "python-decouple>=3.8", "pytz>=2025.2", - "redis>=6.2.0", + "redis==6.4.0", "reportlab>=4.4.3", - "requests>=2.32.4", - "sentry-sdk>=2.34.1", + "requests==2.32.5", + "rpds-py==0.27.1", + "sentry-sdk==2.37.0", + "typing-extensions==4.15.0", "urllib3>=2.5.0", + "virtualenv==20.34.0", "whitenoise>=6.9.0", ] diff --git a/quality/__pycache__/flows.cpython-312.pyc b/quality/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65ccec611f16642b074039d05a66b17e18b269df GIT binary patch literal 177 zcmX@j%ge<81bQ<2GTIv$7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@SR{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc xqF-1F)KOBYpO%wfUaVJ8d5gm)H$SB`C)KWq6=(q?5Ep|OADI~$8H<>KEC7b$HE diff --git a/quality/flows.py b/quality/flows.py new file mode 100644 index 00000000..501e6a13 --- /dev/null +++ b/quality/flows.py @@ -0,0 +1,983 @@ +# """ +# Viewflow workflows for quality app. +# Provides quality assurance, incident management, and improvement 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 ( +# QualityIndicator, QualityMeasurement, IncidentReport, RiskAssessment, +# AuditPlan, AuditFinding, ImprovementProject +# ) +# from .views import ( +# IncidentReportingView, IncidentInvestigationView, RootCauseAnalysisView, +# CorrectiveActionView, IncidentClosureView, QualityMeasurementView, +# IndicatorAnalysisView, AuditPlanningView, AuditExecutionView, +# FindingManagementView, ImprovementProjectView, RiskAssessmentView +# ) +# +# +# class IncidentManagementProcess(Process): +# """ +# Viewflow process model for incident management +# """ +# incident_report = ModelField(IncidentReport, help_text='Associated incident report') +# +# # Process status tracking +# incident_reported = models.BooleanField(default=False) +# initial_assessment_completed = models.BooleanField(default=False) +# investigation_assigned = models.BooleanField(default=False) +# investigation_completed = models.BooleanField(default=False) +# root_cause_identified = models.BooleanField(default=False) +# corrective_actions_planned = models.BooleanField(default=False) +# actions_implemented = models.BooleanField(default=False) +# effectiveness_verified = models.BooleanField(default=False) +# incident_closed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Incident Management Process' +# verbose_name_plural = 'Incident Management Processes' +# +# +# class IncidentManagementFlow(Flow): +# """ +# Incident Management Workflow +# +# This flow manages patient safety incidents from reporting through +# investigation, corrective action, and closure. +# """ +# +# process_class = IncidentManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_incident_management) +# .Next(this.report_incident) +# ) +# +# report_incident = ( +# flow_view(IncidentReportingView) +# .Permission('quality.can_report_incidents') +# .Next(this.assess_incident) +# ) +# +# assess_incident = ( +# flow_func(this.perform_initial_assessment) +# .Next(this.assign_investigation) +# ) +# +# assign_investigation = ( +# flow_view(InvestigationAssignmentView) +# .Permission('quality.can_assign_investigations') +# .Next(this.investigate_incident) +# ) +# +# investigate_incident = ( +# flow_view(IncidentInvestigationView) +# .Permission('quality.can_investigate_incidents') +# .Next(this.analyze_root_cause) +# ) +# +# analyze_root_cause = ( +# flow_view(RootCauseAnalysisView) +# .Permission('quality.can_analyze_root_causes') +# .Next(this.plan_corrective_actions) +# ) +# +# plan_corrective_actions = ( +# flow_view(CorrectiveActionView) +# .Permission('quality.can_plan_corrective_actions') +# .Next(this.implement_actions) +# ) +# +# implement_actions = ( +# flow_view(ActionImplementationView) +# .Permission('quality.can_implement_actions') +# .Next(this.verify_effectiveness) +# ) +# +# verify_effectiveness = ( +# flow_view(EffectivenessVerificationView) +# .Permission('quality.can_verify_effectiveness') +# .Next(this.close_incident) +# ) +# +# close_incident = ( +# flow_func(this.complete_incident_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_incident_management) +# +# # Flow functions +# def start_incident_management(self, activation): +# """Initialize the incident management process""" +# process = activation.process +# incident = process.incident_report +# +# # Update incident status +# incident.status = 'reported' +# incident.save() +# +# # Send immediate notifications +# self.notify_incident_reported(incident) +# +# # Check for high-severity incidents +# if incident.severity in ['severe_harm', 'death']: +# self.notify_critical_incident(incident) +# self.notify_regulatory_bodies(incident) +# +# def perform_initial_assessment(self, activation): +# """Perform initial incident assessment""" +# process = activation.process +# incident = process.incident_report +# +# # Update incident status +# incident.status = 'under_investigation' +# incident.save() +# +# # Mark assessment completed +# process.initial_assessment_completed = True +# process.save() +# +# # Determine investigation priority +# self.determine_investigation_priority(incident) +# +# # Send assessment notifications +# self.notify_assessment_completed(incident) +# +# def complete_incident_management(self, activation): +# """Finalize the incident management process""" +# process = activation.process +# incident = process.incident_report +# +# # Update incident status +# incident.status = 'closed' +# incident.closed_date = timezone.now() +# incident.save() +# +# # Mark process as completed +# process.incident_closed = True +# process.save() +# +# # Send completion notifications +# self.notify_incident_closure(incident) +# +# # Update quality metrics +# self.update_incident_metrics(incident) +# +# # Generate lessons learned +# self.generate_lessons_learned(incident) +# +# def end_incident_management(self, activation): +# """End the incident management workflow""" +# process = activation.process +# +# # Generate incident summary report +# self.generate_incident_summary(process.incident_report) +# +# # Helper methods +# def notify_incident_reported(self, incident): +# """Notify quality staff of incident report""" +# from django.contrib.auth.models import Group +# +# quality_staff = User.objects.filter( +# groups__name='Quality Staff' +# ) +# +# for staff in quality_staff: +# send_mail( +# subject=f'Incident Reported: {incident.incident_number}', +# message=f'New {incident.get_severity_display()} incident reported: {incident.title}', +# from_email='quality@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def notify_critical_incident(self, incident): +# """Notify of critical incident""" +# quality_managers = User.objects.filter( +# groups__name='Quality Managers' +# ) +# +# for manager in quality_managers: +# send_mail( +# subject=f'CRITICAL INCIDENT: {incident.incident_number}', +# message=f'Critical incident requiring immediate attention: {incident.title}', +# from_email='quality@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def notify_regulatory_bodies(self, incident): +# """Notify regulatory bodies if required""" +# if incident.regulatory_notification: +# # This would implement regulatory notification logic +# pass +# +# def determine_investigation_priority(self, incident): +# """Determine investigation priority based on severity""" +# severity_priority_map = { +# 'death': 'urgent', +# 'severe_harm': 'high', +# 'moderate_harm': 'medium', +# 'minor_harm': 'low', +# 'no_harm': 'low' +# } +# +# incident.priority = severity_priority_map.get(incident.severity, 'medium') +# incident.save() +# +# def notify_assessment_completed(self, incident): +# """Notify assessment completion""" +# if incident.assigned_to and incident.assigned_to.email: +# send_mail( +# subject=f'Investigation Assignment: {incident.incident_number}', +# message=f'You have been assigned to investigate incident: {incident.title}', +# from_email='quality@hospital.com', +# recipient_list=[incident.assigned_to.email], +# fail_silently=True +# ) +# +# def notify_incident_closure(self, incident): +# """Notify incident closure""" +# # Notify reporter +# if incident.reported_by and incident.reported_by.email: +# send_mail( +# subject=f'Incident Closed: {incident.incident_number}', +# message=f'The incident you reported has been investigated and closed.', +# from_email='quality@hospital.com', +# recipient_list=[incident.reported_by.email], +# fail_silently=True +# ) +# +# def update_incident_metrics(self, incident): +# """Update incident quality metrics""" +# # This would update incident reporting metrics +# pass +# +# def generate_lessons_learned(self, incident): +# """Generate lessons learned from incident""" +# # This would create lessons learned documentation +# pass +# +# def generate_incident_summary(self, incident): +# """Generate incident summary report""" +# # This would generate comprehensive incident report +# pass +# +# +# class QualityMonitoringProcess(Process): +# """ +# Viewflow process model for quality monitoring +# """ +# quality_indicator = ModelField(QualityIndicator, help_text='Associated quality indicator') +# +# # Process status tracking +# data_collected = models.BooleanField(default=False) +# measurement_calculated = models.BooleanField(default=False) +# analysis_completed = models.BooleanField(default=False) +# trends_identified = models.BooleanField(default=False) +# actions_recommended = models.BooleanField(default=False) +# report_generated = models.BooleanField(default=False) +# monitoring_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Quality Monitoring Process' +# verbose_name_plural = 'Quality Monitoring Processes' +# +# +# class QualityMonitoringFlow(Flow): +# """ +# Quality Monitoring Workflow +# +# This flow manages quality indicator monitoring including data +# collection, analysis, and reporting. +# """ +# +# process_class = QualityMonitoringProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_quality_monitoring) +# .Next(this.collect_data) +# ) +# +# collect_data = ( +# flow_view(DataCollectionView) +# .Permission('quality.can_collect_data') +# .Next(this.calculate_measurement) +# ) +# +# calculate_measurement = ( +# flow_view(QualityMeasurementView) +# .Permission('quality.can_calculate_measurements') +# .Next(this.analyze_results) +# ) +# +# analyze_results = ( +# flow_view(IndicatorAnalysisView) +# .Permission('quality.can_analyze_indicators') +# .Next(this.identify_trends) +# ) +# +# identify_trends = ( +# flow_func(this.perform_trend_analysis) +# .Next(this.recommend_actions) +# ) +# +# recommend_actions = ( +# flow_view(ActionRecommendationView) +# .Permission('quality.can_recommend_actions') +# .Next(this.generate_report) +# ) +# +# generate_report = ( +# flow_view(QualityReportView) +# .Permission('quality.can_generate_reports') +# .Next(this.complete_monitoring) +# ) +# +# complete_monitoring = ( +# flow_func(this.finalize_quality_monitoring) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_quality_monitoring) +# +# # Flow functions +# def start_quality_monitoring(self, activation): +# """Initialize the quality monitoring process""" +# process = activation.process +# indicator = process.quality_indicator +# +# # Send notification to responsible staff +# self.notify_monitoring_due(indicator) +# +# def perform_trend_analysis(self, activation): +# """Perform trend analysis on quality data""" +# process = activation.process +# indicator = process.quality_indicator +# +# # Analyze trends in measurements +# trends = self.analyze_indicator_trends(indicator) +# +# if trends: +# process.trends_identified = True +# process.save() +# +# # Alert if concerning trends identified +# if self.is_concerning_trend(trends): +# self.alert_quality_managers(indicator, trends) +# +# def finalize_quality_monitoring(self, activation): +# """Finalize the quality monitoring process""" +# process = activation.process +# indicator = process.quality_indicator +# +# # Mark monitoring as completed +# process.monitoring_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_monitoring_completion(indicator) +# +# # Schedule next monitoring cycle +# self.schedule_next_monitoring(indicator) +# +# def end_quality_monitoring(self, activation): +# """End the quality monitoring workflow""" +# process = activation.process +# +# # Generate monitoring summary +# self.generate_monitoring_summary(process.quality_indicator) +# +# # Helper methods +# def notify_monitoring_due(self, indicator): +# """Notify responsible staff of monitoring due""" +# if indicator.responsible_user and indicator.responsible_user.email: +# send_mail( +# subject=f'Quality Monitoring Due: {indicator.name}', +# message=f'Quality indicator monitoring is due for: {indicator.name}', +# from_email='quality@hospital.com', +# recipient_list=[indicator.responsible_user.email], +# fail_silently=True +# ) +# +# def analyze_indicator_trends(self, indicator): +# """Analyze trends in quality indicator""" +# # This would implement trend analysis logic +# return {} +# +# def is_concerning_trend(self, trends): +# """Check if trends are concerning""" +# # This would implement trend evaluation logic +# return False +# +# def alert_quality_managers(self, indicator, trends): +# """Alert quality managers of concerning trends""" +# quality_managers = User.objects.filter( +# groups__name='Quality Managers' +# ) +# +# for manager in quality_managers: +# send_mail( +# subject=f'Quality Alert: {indicator.name}', +# message=f'Concerning trend identified in quality indicator: {indicator.name}', +# from_email='quality@hospital.com', +# recipient_list=[manager.email], +# fail_silently=True +# ) +# +# def notify_monitoring_completion(self, indicator): +# """Notify monitoring completion""" +# # This would notify relevant parties +# pass +# +# def schedule_next_monitoring(self, indicator): +# """Schedule next monitoring cycle""" +# # This would schedule the next monitoring cycle +# pass +# +# def generate_monitoring_summary(self, indicator): +# """Generate monitoring summary""" +# # This would generate monitoring summary +# pass +# +# +# class AuditManagementProcess(Process): +# """ +# Viewflow process model for audit management +# """ +# audit_plan = ModelField(AuditPlan, help_text='Associated audit plan') +# +# # Process status tracking +# audit_planned = models.BooleanField(default=False) +# team_assigned = models.BooleanField(default=False) +# audit_conducted = models.BooleanField(default=False) +# findings_documented = models.BooleanField(default=False) +# corrective_actions_planned = models.BooleanField(default=False) +# actions_implemented = models.BooleanField(default=False) +# follow_up_completed = models.BooleanField(default=False) +# audit_closed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Audit Management Process' +# verbose_name_plural = 'Audit Management Processes' +# +# +# class AuditManagementFlow(Flow): +# """ +# Audit Management Workflow +# +# This flow manages quality audits from planning through +# execution, finding management, and closure. +# """ +# +# process_class = AuditManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_audit_management) +# .Next(this.plan_audit) +# ) +# +# plan_audit = ( +# flow_view(AuditPlanningView) +# .Permission('quality.can_plan_audits') +# .Next(this.assign_team) +# ) +# +# assign_team = ( +# flow_view(AuditTeamAssignmentView) +# .Permission('quality.can_assign_audit_teams') +# .Next(this.conduct_audit) +# ) +# +# conduct_audit = ( +# flow_view(AuditExecutionView) +# .Permission('quality.can_conduct_audits') +# .Next(this.document_findings) +# ) +# +# document_findings = ( +# flow_view(FindingManagementView) +# .Permission('quality.can_document_findings') +# .Next(this.plan_corrective_actions) +# ) +# +# plan_corrective_actions = ( +# flow_view(CorrectiveActionPlanningView) +# .Permission('quality.can_plan_corrective_actions') +# .Next(this.implement_actions) +# ) +# +# implement_actions = ( +# flow_view(ActionImplementationView) +# .Permission('quality.can_implement_actions') +# .Next(this.follow_up) +# ) +# +# follow_up = ( +# flow_view(AuditFollowUpView) +# .Permission('quality.can_follow_up_audits') +# .Next(this.close_audit) +# ) +# +# close_audit = ( +# flow_func(this.complete_audit_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_audit_management) +# +# # Flow functions +# def start_audit_management(self, activation): +# """Initialize the audit management process""" +# process = activation.process +# audit = process.audit_plan +# +# # Update audit status +# audit.status = 'planned' +# audit.save() +# +# # Send notification to audit team +# self.notify_audit_planned(audit) +# +# def complete_audit_management(self, activation): +# """Finalize the audit management process""" +# process = activation.process +# audit = process.audit_plan +# +# # Update audit status +# audit.status = 'completed' +# audit.actual_end_date = timezone.now().date() +# audit.save() +# +# # Mark process as completed +# process.audit_closed = True +# process.save() +# +# # Send completion notifications +# self.notify_audit_completion(audit) +# +# # Update audit metrics +# self.update_audit_metrics(audit) +# +# def end_audit_management(self, activation): +# """End the audit management workflow""" +# process = activation.process +# +# # Generate audit summary report +# self.generate_audit_summary(process.audit_plan) +# +# # Helper methods +# def notify_audit_planned(self, audit): +# """Notify audit team of planned audit""" +# audit_team = audit.audit_team.all() +# for member in audit_team: +# if member.email: +# send_mail( +# subject=f'Audit Planned: {audit.title}', +# message=f'You have been assigned to audit: {audit.title}', +# from_email='quality@hospital.com', +# recipient_list=[member.email], +# fail_silently=True +# ) +# +# def notify_audit_completion(self, audit): +# """Notify audit completion""" +# # Notify department being audited +# if audit.department: +# department_staff = User.objects.filter( +# department=audit.department +# ) +# for staff in department_staff: +# if staff.email: +# send_mail( +# subject=f'Audit Completed: {audit.title}', +# message=f'The audit of your department has been completed.', +# from_email='quality@hospital.com', +# recipient_list=[staff.email], +# fail_silently=True +# ) +# +# def update_audit_metrics(self, audit): +# """Update audit performance metrics""" +# # This would update audit metrics +# pass +# +# def generate_audit_summary(self, audit): +# """Generate audit summary report""" +# # This would generate comprehensive audit report +# pass +# +# +# class ImprovementProjectProcess(Process): +# """ +# Viewflow process model for improvement projects +# """ +# improvement_project = ModelField(ImprovementProject, help_text='Associated improvement project') +# +# # Process status tracking +# project_initiated = models.BooleanField(default=False) +# team_assembled = models.BooleanField(default=False) +# baseline_established = models.BooleanField(default=False) +# improvements_implemented = models.BooleanField(default=False) +# results_measured = models.BooleanField(default=False) +# sustainability_ensured = models.BooleanField(default=False) +# project_completed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Improvement Project Process' +# verbose_name_plural = 'Improvement Project Processes' +# +# +# class ImprovementProjectFlow(Flow): +# """ +# Improvement Project Workflow +# +# This flow manages quality improvement projects using +# structured methodologies like PDSA and Lean. +# """ +# +# process_class = ImprovementProjectProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_improvement_project) +# .Next(this.initiate_project) +# ) +# +# initiate_project = ( +# flow_view(ProjectInitiationView) +# .Permission('quality.can_initiate_projects') +# .Next(this.assemble_team) +# ) +# +# assemble_team = ( +# flow_view(TeamAssemblyView) +# .Permission('quality.can_assemble_teams') +# .Next(this.establish_baseline) +# ) +# +# establish_baseline = ( +# flow_view(BaselineEstablishmentView) +# .Permission('quality.can_establish_baseline') +# .Next(this.implement_improvements) +# ) +# +# implement_improvements = ( +# flow_view(ImprovementImplementationView) +# .Permission('quality.can_implement_improvements') +# .Next(this.measure_results) +# ) +# +# measure_results = ( +# flow_view(ResultsMeasurementView) +# .Permission('quality.can_measure_results') +# .Next(this.ensure_sustainability) +# ) +# +# ensure_sustainability = ( +# flow_view(SustainabilityView) +# .Permission('quality.can_ensure_sustainability') +# .Next(this.complete_project) +# ) +# +# complete_project = ( +# flow_func(this.finalize_improvement_project) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_improvement_project) +# +# # Flow functions +# def start_improvement_project(self, activation): +# """Initialize the improvement project process""" +# process = activation.process +# project = process.improvement_project +# +# # Update project status +# project.status = 'planned' +# project.save() +# +# # Send notification to project team +# self.notify_project_initiated(project) +# +# def finalize_improvement_project(self, activation): +# """Finalize the improvement project process""" +# process = activation.process +# project = process.improvement_project +# +# # Update project status +# project.status = 'completed' +# project.actual_end_date = timezone.now().date() +# project.save() +# +# # Mark process as completed +# process.project_completed = True +# process.save() +# +# # Send completion notifications +# self.notify_project_completion(project) +# +# # Calculate ROI +# self.calculate_project_roi(project) +# +# def end_improvement_project(self, activation): +# """End the improvement project workflow""" +# process = activation.process +# +# # Generate project summary report +# self.generate_project_summary(process.improvement_project) +# +# # Helper methods +# def notify_project_initiated(self, project): +# """Notify project team of project initiation""" +# project_team = project.project_team.all() +# for member in project_team: +# if member.email: +# send_mail( +# subject=f'Improvement Project Started: {project.title}', +# message=f'You have been assigned to improvement project: {project.title}', +# from_email='quality@hospital.com', +# recipient_list=[member.email], +# fail_silently=True +# ) +# +# def notify_project_completion(self, project): +# """Notify project completion""" +# # Notify sponsor +# if project.sponsor and project.sponsor.email: +# send_mail( +# subject=f'Project Completed: {project.title}', +# message=f'The improvement project you sponsored has been completed.', +# from_email='quality@hospital.com', +# recipient_list=[project.sponsor.email], +# fail_silently=True +# ) +# +# def calculate_project_roi(self, project): +# """Calculate project return on investment""" +# # This would implement ROI calculation logic +# pass +# +# def generate_project_summary(self, project): +# """Generate project summary report""" +# # This would generate comprehensive project report +# pass +# +# +# class RiskManagementProcess(Process): +# """ +# Viewflow process model for risk management +# """ +# risk_assessment = ModelField(RiskAssessment, help_text='Associated risk assessment') +# +# # Process status tracking +# risk_identified = models.BooleanField(default=False) +# risk_assessed = models.BooleanField(default=False) +# controls_evaluated = models.BooleanField(default=False) +# mitigation_planned = models.BooleanField(default=False) +# controls_implemented = models.BooleanField(default=False) +# effectiveness_monitored = models.BooleanField(default=False) +# risk_managed = models.BooleanField(default=False) +# +# class Meta: +# verbose_name = 'Risk Management Process' +# verbose_name_plural = 'Risk Management Processes' +# +# +# class RiskManagementFlow(Flow): +# """ +# Risk Management Workflow +# +# This flow manages risk identification, assessment, +# mitigation, and monitoring activities. +# """ +# +# process_class = RiskManagementProcess +# +# # Flow definition +# start = ( +# flow_func(this.start_risk_management) +# .Next(this.identify_risk) +# ) +# +# identify_risk = ( +# flow_view(RiskIdentificationView) +# .Permission('quality.can_identify_risks') +# .Next(this.assess_risk) +# ) +# +# assess_risk = ( +# flow_view(RiskAssessmentView) +# .Permission('quality.can_assess_risks') +# .Next(this.evaluate_controls) +# ) +# +# evaluate_controls = ( +# flow_view(ControlEvaluationView) +# .Permission('quality.can_evaluate_controls') +# .Next(this.plan_mitigation) +# ) +# +# plan_mitigation = ( +# flow_view(MitigationPlanningView) +# .Permission('quality.can_plan_mitigation') +# .Next(this.implement_controls) +# ) +# +# implement_controls = ( +# flow_view(ControlImplementationView) +# .Permission('quality.can_implement_controls') +# .Next(this.monitor_effectiveness) +# ) +# +# monitor_effectiveness = ( +# flow_view(EffectivenessMonitoringView) +# .Permission('quality.can_monitor_effectiveness') +# .Next(this.manage_risk) +# ) +# +# manage_risk = ( +# flow_func(this.complete_risk_management) +# .Next(this.end) +# ) +# +# end = flow_func(this.end_risk_management) +# +# # Flow functions +# def start_risk_management(self, activation): +# """Initialize the risk management process""" +# process = activation.process +# risk = process.risk_assessment +# +# # Update risk status +# risk.status = 'active' +# risk.save() +# +# # Send notification to risk owner +# self.notify_risk_identified(risk) +# +# def complete_risk_management(self, activation): +# """Finalize the risk management process""" +# process = activation.process +# risk = process.risk_assessment +# +# # Update risk status based on residual risk level +# if risk.residual_risk_level in ['low', 'medium']: +# risk.status = 'active' +# else: +# risk.status = 'under_review' +# +# risk.save() +# +# # Mark process as completed +# process.risk_managed = True +# process.save() +# +# # Send completion notifications +# self.notify_risk_management_completion(risk) +# +# # Schedule risk review +# self.schedule_risk_review(risk) +# +# def end_risk_management(self, activation): +# """End the risk management workflow""" +# process = activation.process +# +# # Generate risk management summary +# self.generate_risk_summary(process.risk_assessment) +# +# # Helper methods +# def notify_risk_identified(self, risk): +# """Notify risk owner of identified risk""" +# if risk.responsible_person and risk.responsible_person.email: +# send_mail( +# subject=f'Risk Assignment: {risk.title}', +# message=f'You have been assigned responsibility for risk: {risk.title}', +# from_email='quality@hospital.com', +# recipient_list=[risk.responsible_person.email], +# fail_silently=True +# ) +# +# def notify_risk_management_completion(self, risk): +# """Notify risk management completion""" +# # This would notify relevant parties +# pass +# +# def schedule_risk_review(self, risk): +# """Schedule risk review""" +# # This would schedule periodic risk reviews +# pass +# +# def generate_risk_summary(self, risk): +# """Generate risk management summary""" +# # This would generate risk summary +# pass +# +# +# # Celery tasks for background processing +# @celery.job +# def auto_generate_quality_reports(): +# """Background task to automatically generate quality reports""" +# try: +# # This would generate scheduled quality reports +# return True +# except Exception: +# return False +# +# +# @celery.job +# def monitor_quality_indicators(): +# """Background task to monitor quality indicators""" +# try: +# # This would check quality indicators for threshold breaches +# return True +# except Exception: +# return False +# +# +# @celery.job +# def schedule_audits(): +# """Background task to schedule audits""" +# try: +# # This would schedule regular audits +# return True +# except Exception: +# return False +# +# +# @celery.job +# def track_corrective_actions(): +# """Background task to track corrective action progress""" +# try: +# # This would monitor corrective action due dates +# return True +# except Exception: +# return False +# +# +# @celery.job +# def risk_monitoring(): +# """Background task to monitor risks""" +# try: +# # This would monitor risk levels and control effectiveness +# return True +# except Exception: +# return False +# diff --git a/radiology/__pycache__/flows.cpython-312.pyc b/radiology/__pycache__/flows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b105d99a4adf25cd7752c0310f85bc1856d946fa GIT binary patch literal 179 zcmX@j%ge<81bQ<2GU^i<7#@Q-=-@L8P-HqoC4(lT-%5reCLr%KNX@Sx{m|mnqGJ8r z#G>-Vyu_UH#GFhZC$F?PzMv>SD>b=9KO?`mAhRSfCmtxAn4X%OnpYBETv=R_nj2qc zqF2KczG$)vkyYXayq>7lRldnHd=wibUGmMCgD6@@-C7~y&ho-$eNH5LH@c(A!oA3YocMYLy2)#a( zj#fOdz$rA{Q2D%6f2DtG6&EAARTS#2!cmamG-&pMdObeLv@dpMuUxaXXhWHAV!oDO z(Yck2NxckQI1N`W_qR75Xi&5oHF&z5XK{a1V@tiNwTCJ$o|9VHTvOZ7tZMa2@X{(S zdJRK1xMT<=@~0T|Bz35yP#WcshrCoxZFG>j=?q<QG+_vV-MQUj(ymV4jjXAoWM!+<17X+i1WCN8yLk+ z-1p--Uf?BO;VnL33Lo(e-|+*}_{E}G42xyS%+3}v2g_w{R>(?OIjag8UBd>?6aHZ@#xi$D@pN0iC)1jolDfd;jzx+jsKrc#r07{^ zdbydiLY45fs9=?wS#Bv258gHZ0}RK%8sF_6Mvyq2vGn delta 121 zcmZo!z}T{Yae_ai*T#VTLYtRsYcVmYF--nz96nh~Z`; diff --git a/templates/billing/bills/bill_detail.html b/templates/billing/bills/bill_detail.html index df025b37..cf32a32a 100644 --- a/templates/billing/bills/bill_detail.html +++ b/templates/billing/bills/bill_detail.html @@ -435,7 +435,7 @@ - + diff --git a/templates/billing/bills/bill_form.html b/templates/billing/bills/bill_form.html index 86077449..1f3e072a 100644 --- a/templates/billing/bills/bill_form.html +++ b/templates/billing/bills/bill_form.html @@ -5,479 +5,541 @@ {% block content %}
- -
-
-

{% if object %}Edit Medical Bill{% else %}Create Medical Bill{% endif %}

- -
-
- - Back to List - - {% if object %} - - View Details - - {% endif %} -
+ +
+
+

{% if object %}Edit Medical Bill{% else %}Create Medical Bill{% endif %}

+
+
+ + Back to List + + {% if object %} + + View Details + + {% endif %} +
+
-
- {% csrf_token %} - -
- -
-
- -
-
-
- Patient Information -
-
-
-
-
-
- {{ form.patient }} - - {% if form.patient.errors %} -
- {{ form.patient.errors.0 }} -
- {% endif %} -
-
-
-
- {{ form.encounter }} - - {% if form.encounter.errors %} -
- {{ form.encounter.errors.0 }} -
- {% endif %} -
-
-
-
-
+ + {% csrf_token %} - -
-
-
- Bill Details -
-
-
-
-
-
- {{ form.bill_number }} - - {% if form.bill_number.errors %} -
- {{ form.bill_number.errors.0 }} -
- {% endif %} -
-
-
-
- {{ form.bill_date }} - - {% if form.bill_date.errors %} -
- {{ form.bill_date.errors.0 }} -
- {% endif %} -
-
-
-
- {{ form.due_date }} - - {% if form.due_date.errors %} -
- {{ form.due_date.errors.0 }} -
- {% endif %} -
-
-
-
- {{ form.status }} - - {% if form.status.errors %} -
- {{ form.status.errors.0 }} -
- {% endif %} -
-
-
-
- {{ form.billing_provider }} - - {% if form.billing_provider.errors %} -
- {{ form.billing_provider.errors.0 }} -
- {% endif %} -
-
-
-
- {{ form.notes }} - - {% if form.notes.errors %} -
- {{ form.notes.errors.0 }} -
- {% endif %} -
-
-
-
-
+
+ +
+
- -
-
-
- Line Items -
- -
-
-
- - {% if object.billlineitem_set.all %} - {% for line_item in object.billlineitem_set.all %} -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
- -
-
-
- {% endfor %} - {% else %} -
- -

No line items added yet. Click "Add Item" to get started.

-
- {% endif %} -
-
-
- - -
-
-
- -
- - - {% if not object %} - - {% endif %} -
-
-
-
+ +
+
+

Patient & Context

+
+ +
+
+
+ {% if object %} +
+
+ Bill # {{ object.bill_number }}
+
Created: {{ object.created_at|date:"M d, Y H:i" }}
+
+ {% endif %} + +
+
+
+ {{ form.patient }} + + {% if form.patient.errors %}
{{ form.patient.errors.0 }}
{% endif %} +
+
+
+
+ {{ form.bill_type }} + + {% if form.bill_type.errors %}
{{ form.bill_type.errors.0 }}
{% endif %} +
+
+
+ +
+
+
+ {{ form.encounter }} + + {% if form.encounter.errors %}
{{ form.encounter.errors.0 }}
{% endif %} +
+
+
+
+ {{ form.admission }} + + {% if form.admission.errors %}
{{ form.admission.errors.0 }}
{% endif %} +
+
+
+ +
+
+
+ {{ form.payment_terms }} + + {% if form.payment_terms.errors %}
{{ form.payment_terms.errors.0 }}
{% endif %} +
+
+
+
+
+ + +
+
+

Service & Dates

+
+ +
+
+
+
+
+
+ {{ form.service_date_from }} + + {% if form.service_date_from.errors %}
{{ form.service_date_from.errors.0 }}
{% endif %} +
+
+
+
+ {{ form.service_date_to }} + + {% if form.service_date_to.errors %}
{{ form.service_date_to.errors.0 }}
{% endif %} +
+
+
+
+ {{ form.bill_date }} + + {% if form.bill_date.errors %}
{{ form.bill_date.errors.0 }}
{% endif %} +
+
+
+
+
+
+ {{ form.due_date }} + + {% if form.due_date.errors %}
{{ form.due_date.errors.0 }}
{% endif %} +
+
+
+
+
+ + +
+
+

Providers & Insurance

+
+ +
+
+
+
+
+
+ {{ form.attending_provider }} + + {% if form.attending_provider.errors %}
{{ form.attending_provider.errors.0 }}
{% endif %} +
+
+
+
+ {{ form.billing_provider }} + + {% if form.billing_provider.errors %}
{{ form.billing_provider.errors.0 }}
{% endif %} +
+
+
+
+
+
+ {{ form.primary_insurance }} + + {% if form.primary_insurance.errors %}
{{ form.primary_insurance.errors.0 }}
{% endif %} +
+
+
+
+ {{ form.secondary_insurance }} + + {% if form.secondary_insurance.errors %}
{{ form.secondary_insurance.errors.0 }}
{% endif %} +
+
+
+
+
+ + +
+
+

Notes

+
+ +
+
+
+
+ {{ form.notes }} + {% if form.notes.errors %}
{{ form.notes.errors.0 }}
{% endif %} +
+
+
+ + +
+
+

Line Items

+
+ + +
+
+
+
+ {% if object and object.billlineitem_set.all %} + {% for line_item in object.billlineitem_set.all %} +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+ {% endfor %} + {% else %} +
+ +

No line items added yet. Click "Add Item" to get started.

+
+ {% endif %} +
+
+
+ + +
+
+
+ +
+ + + {% if not object %} + + {% endif %} +
+
+
+
+ +
+
+ + +
+ +
+
+

Bill Summary

+
+ +
+
+
+ +
+ Subtotal: $0.00 +
+
+ Tax: $0.00 +
+
+ Discount: $0.00 +
+
+
+ Total: $0.00
- -
- -
-
-
- Bill Summary -
-
-
-
- Subtotal: - $0.00 -
-
- Tax: - $0.00 -
-
- Discount: - $0.00 -
-
-
- Total: - $0.00 -
-
-
- - -
-
-
- Help & Guidelines -
-
-
-
-
-

- -

-
-
-
    -
  • Select the patient for this bill
  • -
  • Link to a specific encounter if applicable
  • -
  • Verify patient insurance information
  • -
-
-
-
-
-

- -

-
-
-
    -
  • Use standard CPT/HCPCS codes
  • -
  • Include modifier codes when applicable
  • -
  • Verify codes with current fee schedule
  • -
-
-
-
-
-

- -

-
-
-
    -
  • Draft: Bill is being prepared
  • -
  • Pending: Ready for review
  • -
  • Submitted: Sent to patient/insurance
  • -
  • Paid: Payment received in full
  • -
-
-
-
-
-
-
+ +
+ {{ form.subtotal }} + {{ form.tax_amount }} + {{ form.discount_amount }} + {{ form.adjustment_amount }}
+
- + + +
+
+

Help & Guidelines

+
+ +
+
+
+
+
+

+ +

+
+
+
    +
  • Select the patient for this bill
  • +
  • Link to a specific encounter if applicable
  • +
  • Verify patient insurance information
  • +
+
+
+
+
+

+ +

+
+
+
    +
  • Use standard CPT/HCPCS codes
  • +
  • Include modifier codes when applicable
  • +
  • Verify codes with current fee schedule
  • +
+
+
+
+
+

+ +

+
+
+
    +
  • Draft: Bill is being prepared
  • +
  • Pending: Ready for review
  • +
  • Submitted: Sent to patient/insurance
  • +
  • Paid: Payment received in full
  • +
+
+
+
+
+
+
+
+
+
-{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/templates/billing/bills/bill_list.html b/templates/billing/bills/bill_list.html index 980986f4..82634ec9 100644 --- a/templates/billing/bills/bill_list.html +++ b/templates/billing/bills/bill_list.html @@ -5,405 +5,395 @@ {% block content %}
- -
-
-

Medical Bills

- -
-
- - Create Bill - - - -
+ +
+
+

Medical Bills

+
- - -
-
-
-
-
-
-
Total Bills
-

{{ stats.total_bills }}

-
-
- -
-
-
-
-
-
-
-
-
-
-
Total Amount
-

ê{{ stats.total_amount|default:0|floatformat:'2g' }}

-
-
- -
-
-
-
-
-
-
-
-
-
-
Total Paid
-

ê{{ stats.total_paid|default:0|floatformat:'2g' }}

-
-
- -
-
-
-
-
-
-
-
-
-
-
Outstanding
-

ê{{ stats.outstanding_amount|default:0|floatformat:'2g' }}

-
-
- -
-
-
-
-
+
+ + Create Bill + + +
+
- -
-
-
- Search & Filter -
-
+ +
+
+
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
- -
-
+
+
+
Total Bills
+

{{ stats.total_bills|default:0 }}

+
+
+ +
+
+
+
+
+
+
+
+
Total Amount
+

ê{{ stats.total_amount|default:0|floatformat:'2g' }}

+
+
+ +
+
+
+
+
+
+
+
+
+
+
Total Paid
+

ê{{ stats.total_paid|default:0|floatformat:'2g' }}

+
+
+ +
+
+
+
+
+
+
+
+
+
+
Outstanding
+

ê{{ stats.outstanding_amount|default:0|floatformat:'2g' }}

+
+
+ +
+
+
+
+
+
- -
-
-
- Medical Bills - {{ page_obj.paginator.count }} total -
-
- - - -
-
-
-
-
- - - - - - - - - - - - - - - - - {% for bill in page_obj %} - - - - - - - - - - - - - {% empty %} - - - - {% endfor %} - -
-
- -
-
Bill NumberPatientDateTotal AmountPaid AmountBalanceStatusDue DateActions
-
- -
-
- - {{ bill.bill_number }} - - -
- {{ bill.patient.get_full_name }} -
MRN: {{ bill.patient.mrn }} -
-
{{ bill.bill_date|date:"M d, Y" }}ê{{ bill.total_amount|floatformat:2 }}ê{{ bill.paid_amount|floatformat:2 }} - - ê{{ bill.balance_amount|floatformat:2 }} - - - {% if bill.status == 'DRAFT' %} - Draft - {% elif bill.status == 'PENDING' %} - Pending - {% elif bill.status == 'SUBMITTED' %} - Submitted - {% elif bill.status == 'PARTIAL_PAID' %} - Partially Paid - {% elif bill.status == 'PAID' %} - Paid - {% elif bill.status == 'OVERDUE' %} - Overdue - {% elif bill.status == 'COLLECTIONS' %} - Collections - {% elif bill.status == 'WRITTEN_OFF' %} - Written Off - {% elif bill.status == 'CANCELLED' %} - Cancelled - {% endif %} - - {% if bill.due_date %} - - {{ bill.due_date|date:"M d, Y" }} - - {% else %} - - - {% endif %} - -
- - - - {% if bill.status == 'DRAFT' %} - - - - {% endif %} -
- - -
-
-
-
- -
No bills found
-

No medical bills match your current filters.

- - Create First Bill - -
-
-
-
-
- - - {% if is_paginated %} - {% include 'partial/pagination.html' %} - {% endif %} + +
+
+

Search & Filter

+
+ +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+
+ + +
+
+

+ Medical Bills + {{ page_obj.paginator.count }} total +

+
+ + + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + {% for bill in page_obj %} + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
+
+ +
+
Bill NumberPatientDateTotal AmountPaid AmountBalanceStatusDue DateActions
+
+ +
+
+ + {{ bill.bill_number }} + + +
+ {{ bill.patient.get_full_name }} +
MRN: {{ bill.patient.mrn }} +
+
{{ bill.bill_date|date:"M d, Y" }}ê{{ bill.total_amount|floatformat:2 }}ê{{ bill.paid_amount|floatformat:2 }} + + ê{{ bill.balance_amount|floatformat:2 }} + + + {% if bill.status == 'DRAFT' %} + Draft + {% elif bill.status == 'PENDING' %} + Pending + {% elif bill.status == 'SUBMITTED' %} + Submitted + {% elif bill.status == 'PARTIAL_PAID' %} + Partially Paid + {% elif bill.status == 'PAID' %} + Paid + {% elif bill.status == 'OVERDUE' %} + Overdue + {% elif bill.status == 'COLLECTIONS' %} + Collections + {% elif bill.status == 'WRITTEN_OFF' %} + Written Off + {% elif bill.status == 'CANCELLED' %} + Cancelled + {% endif %} + + {% if bill.due_date %} + + {{ bill.due_date|date:"M d, Y" }} + + {% else %} + - + {% endif %} + +
+ + + + {% if bill.status == 'DRAFT' %} + + + + {% endif %} +
+ + +
+
+
+
+ +
No bills found
+

No medical bills match your current filters.

+ + Create First Bill + +
+
+
+
+
+
+ + + {% if is_paginated %} + {% include 'partial/pagination.html' %} + {% endif %}
-{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/templates/billing/claims/claim_detail.html b/templates/billing/claims/claim_detail.html index eff12889..5071be1b 100644 --- a/templates/billing/claims/claim_detail.html +++ b/templates/billing/claims/claim_detail.html @@ -31,13 +31,13 @@ Actions