HH/apps/accounts/signals.py

164 lines
5.7 KiB
Python

"""
Accounts signals - Handle onboarding events
"""
from django.db.models.signals import post_save, post_delete, pre_save
from django.dispatch import receiver
from .models import User, UserAcknowledgement, UserProvisionalLog, AcknowledgementContent, AcknowledgementChecklistItem
from .services import EmailService
# ==================== Version Control Signals ====================
@receiver(post_save, sender=AcknowledgementContent)
def create_content_version(sender, instance, created, **kwargs):
"""
Automatically create a version record when content is saved.
"""
from .version_models import ContentVersion
# Get the next version number
last_version = ContentVersion.objects.filter(
content=instance
).order_by('-version_number').first()
version_number = 1 if not last_version else last_version.version_number + 1
# Create version
ContentVersion.objects.create(
content=instance,
version_number=version_number,
title_en=instance.title_en,
title_ar=instance.title_ar,
description_en=instance.description_en,
description_ar=instance.description_ar,
content_en=instance.content_en,
content_ar=instance.content_ar,
role=instance.role,
order=instance.order,
is_active=instance.is_active,
# changed_by will be set via view
)
@receiver(post_save, sender=AcknowledgementChecklistItem)
def create_checklist_version(sender, instance, created, **kwargs):
"""
Automatically create a version record when checklist item is saved.
"""
from .version_models import ChecklistItemVersion
# Get the next version number
last_version = ChecklistItemVersion.objects.filter(
checklist_item=instance
).order_by('-version_number').first()
version_number = 1 if not last_version else last_version.version_number + 1
# Create version
ChecklistItemVersion.objects.create(
checklist_item=instance,
version_number=version_number,
text_en=instance.text_en,
text_ar=instance.text_ar,
description_en=instance.description_en,
description_ar=instance.description_ar,
is_required=instance.is_required,
is_active=instance.is_active,
order=instance.order,
content=instance.content,
role=instance.role,
# changed_by will be set via view
)
@receiver(post_save, sender=User)
def log_provisional_user_creation(sender, instance, created, **kwargs):
"""
Log when a provisional user is created
"""
if created and instance.is_provisional:
UserProvisionalLog.objects.create(
user=instance,
event_type='created',
description=f"Provisional user {instance.email} created",
metadata={
'email': instance.email,
'first_name': instance.first_name,
'last_name': instance.last_name
}
)
@receiver(post_save, sender=UserAcknowledgement)
def log_acknowledgement(sender, instance, created, **kwargs):
"""
Log when a user acknowledges an item
"""
if created and instance.is_acknowledged:
UserProvisionalLog.objects.create(
user=instance.user,
event_type='step_completed',
description=f"Acknowledged: {instance.checklist_item.text_en}",
metadata={
'checklist_item_id': str(instance.checklist_item.id),
'checklist_item_code': instance.checklist_item.code
}
)
@receiver(post_save, sender=User)
def check_onboarding_completion(sender, instance, **kwargs):
"""
Check if all required acknowledgements are completed
"""
if instance.is_provisional and not instance.acknowledgement_completed:
from .services import OnboardingService
required_items = OnboardingService.get_checklist_items(instance).filter(is_required=True)
acknowledged_items = UserAcknowledgement.objects.filter(
user=instance,
checklist_item__in=required_items,
is_acknowledged=True
)
# All required items acknowledged
if required_items.count() > 0 and acknowledged_items.count() == required_items.count():
UserProvisionalLog.objects.create(
user=instance,
event_type='wizard_completed',
description="All required acknowledgements completed",
metadata={
'total_items': required_items.count(),
'acknowledged_items': acknowledged_items.count()
}
)
@receiver(post_save, sender=User)
def log_account_activation(sender, instance, **kwargs):
"""
Log when a user account is activated
"""
if not instance.is_provisional and instance.acknowledgement_completed:
# Check if this is a recent activation (within last minute)
from django.utils import timezone
if instance.acknowledgement_completed_at and \
(timezone.now() - instance.acknowledgement_completed_at).total_seconds() < 60:
UserProvisionalLog.objects.create(
user=instance,
event_type='user_activated',
description=f"User {instance.email} account activated",
metadata={
'username': instance.username,
'email': instance.email
}
)
# Send notification to PX Admins
from django.contrib.auth import get_user_model
User = get_user_model()
admin_users = User.objects.filter(groups__name='PX Admin')
EmailService.send_completion_notification(instance, admin_users)