HH/test_appreciation_conversion.py
2026-01-24 15:27:27 +03:00

461 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
"""
Test script for Complaint to Appreciation Conversion Feature
This script tests the conversion of appreciation-type complaints to Appreciation records.
"""
import os
import sys
import django
# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'PX360.settings')
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
django.setup()
from django.contrib.auth import get_user_model
from apps.complaints.models import Complaint, ComplaintUpdate
from apps.organizations.models import Hospital, Department, Staff
from app.models import Patient
from apps.appreciation.models import Appreciation, AppreciationCategory
from apps.accounts.models import User
from django.utils import timezone
from django.urls import reverse
from django.test import TestCase, Client
from rest_framework.test import APIClient
import json
User = get_user_model()
def print_section(title):
"""Print a formatted section header"""
print(f"\n{'='*60}")
print(f" {title}")
print(f"{'='*60}\n")
def print_success(message):
"""Print success message"""
print(f"{message}")
def print_error(message):
"""Print error message"""
print(f"{message}")
def print_info(message):
"""Print info message"""
print(f" {message}")
def test_default_category():
"""Test that default category exists"""
print_section("Test 1: Default Category Check")
try:
category = AppreciationCategory.objects.get(code='patient_feedback')
print_success(f"Default category exists: {category.name_en}")
print_info(f"Category ID: {category.id}")
print_info(f"Name (AR): {category.name_ar}")
return True
except AppreciationCategory.DoesNotExist:
print_error("Default category 'patient_feedback' not found!")
print_info("Run: python manage.py create_patient_feedback_category")
return False
def create_test_data():
"""Create test data for conversion tests"""
print_section("Test 2: Create Test Data")
# Create PX Admin user
try:
px_admin = User.objects.get(email='test_px_admin@example.com')
except User.DoesNotExist:
px_admin = User.objects.create_user(
email='test_px_admin@example.com',
password='testpass123',
first_name='Test',
last_name='PX Admin',
is_px_admin=True
)
print_success("Created PX Admin user")
# Create Hospital
try:
hospital = Hospital.objects.get(code='TEST_HOSPITAL')
except Hospital.DoesNotExist:
hospital = Hospital.objects.create(
code='TEST_HOSPITAL',
name_en='Test Hospital',
name_ar='مستشفى تجريبي',
city='Riyadh'
)
print_success("Created Hospital")
# Create Department
try:
department = Department.objects.get(code='TEST_DEPT')
except Department.DoesNotExist:
department = Department.objects.create(
code='TEST_DEPT',
hospital=hospital,
name_en='Test Department',
name_ar='قسم تجريبي'
)
print_success("Created Department")
# Create Staff
try:
staff = Staff.objects.get(email='test_staff@example.com')
except Staff.DoesNotExist:
staff = Staff.objects.create(
email='test_staff@example.com',
hospital=hospital,
department=department,
first_name='Test',
last_name='Staff',
first_name_ar='تجريبي',
last_name_ar='موظف',
job_title='Test Employee',
job_title_ar='موظف تجريبي'
)
# Create user account for staff
staff.user = User.objects.create_user(
email='test_staff@example.com',
password='staffpass123',
first_name='Test',
last_name='Staff'
)
staff.save()
print_success("Created Staff with user account")
# Create Patient
try:
patient = Patient.objects.get(mrn='TEST_PATIENT_001')
except Patient.DoesNotExist:
patient = Patient.objects.create(
mrn='TEST_PATIENT_001',
hospital=hospital,
first_name='Test',
last_name='Patient',
first_name_ar='تجريبي',
last_name_ar='مريض'
)
print_success("Created Patient")
return {
'px_admin': px_admin,
'hospital': hospital,
'department': department,
'staff': staff,
'patient': patient
}
def test_appreciation_type_complaint(test_data):
"""Test creating an appreciation-type complaint"""
print_section("Test 3: Create Appreciation-Type Complaint")
complaint = Complaint.objects.create(
patient=test_data['patient'],
hospital=test_data['hospital'],
department=test_data['department'],
staff=test_data['staff'],
complaint_type='appreciation',
category='quality_of_care',
subcategory='Positive Feedback',
severity='low',
priority='medium',
source='web',
title='Excellent Service by Test Staff',
description='I want to appreciate the excellent service provided by Test Staff. They were very helpful and professional.',
short_description='Positive feedback about excellent service',
short_description_ar='تغذية راجعة إيجابية عن خدمة ممتازة',
status='open',
created_by=test_data['px_admin']
)
print_success(f"Created appreciation-type complaint: {complaint.id}")
print_info(f"Complaint type: {complaint.complaint_type}")
print_info(f"Title: {complaint.title}")
return complaint
def test_api_endpoint(test_data, complaint):
"""Test the conversion API endpoint"""
print_section("Test 4: Test Conversion API Endpoint")
# Get default category
category = AppreciationCategory.objects.get(code='patient_feedback')
# Prepare request data
data = {
'recipient_type': 'user',
'recipient_id': str(test_data['staff'].user.id),
'category_id': str(category.id),
'message_en': complaint.description,
'message_ar': complaint.short_description_ar,
'visibility': 'department',
'is_anonymous': True,
'close_complaint': True
}
# Create API client
client = APIClient()
client.force_authenticate(user=test_data['px_admin'])
# Make API request
url = reverse('complaints:convert_to_appreciation', kwargs={'pk': complaint.id})
print_info(f"API URL: {url}")
print_info(f"Request data: {json.dumps(data, indent=2)}")
response = client.post(url, data, format='json')
print_info(f"Response status: {response.status_code}")
if response.status_code == 201:
print_success("Conversion API call successful!")
result = response.json()
print_info(f"Response: {json.dumps(result, indent=2)}")
# Verify appreciation was created
appreciation_id = result.get('appreciation_id')
if appreciation_id:
try:
appreciation = Appreciation.objects.get(id=appreciation_id)
print_success(f"Appreciation record created: {appreciation.id}")
print_info(f"Appreciation message: {appreciation.message_en[:50]}...")
# Verify complaint metadata
complaint.refresh_from_db()
if complaint.metadata.get('appreciation_id'):
print_success("Complaint metadata updated with appreciation link")
else:
print_error("Complaint metadata not updated!")
# Verify complaint status changed
if complaint.status == 'closed':
print_success("Complaint status changed to 'closed'")
else:
print_error(f"Complaint status is '{complaint.status}', expected 'closed'")
# Verify timeline entry
timeline_entries = ComplaintUpdate.objects.filter(
complaint=complaint,
update_type='note'
).count()
if timeline_entries > 0:
print_success(f"Timeline entry created ({timeline_entries} entries)")
else:
print_error("No timeline entry created!")
return appreciation
except Appreciation.DoesNotExist:
print_error("Appreciation record not found in database!")
else:
print_error("No appreciation_id in response!")
else:
print_error(f"API call failed with status {response.status_code}")
print_info(f"Response: {response.json()}")
return None
def test_prevention_of_duplicate_conversion(test_data, complaint):
"""Test that duplicate conversions are prevented"""
print_section("Test 5: Prevent Duplicate Conversion")
# Create API client
client = APIClient()
client.force_authenticate(user=test_data['px_admin'])
# Get default category
category = AppreciationCategory.objects.get(code='patient_feedback')
# Prepare request data
data = {
'recipient_type': 'user',
'recipient_id': str(test_data['staff'].user.id),
'category_id': str(category.id),
'message_en': 'Duplicate test',
'message_ar': 'اختبار مكرر',
'visibility': 'private',
'is_anonymous': True,
'close_complaint': False
}
# Make API request (should fail)
url = reverse('complaints:convert_to_appreciation', kwargs={'pk': complaint.id})
response = client.post(url, data, format='json')
print_info(f"Response status: {response.status_code}")
if response.status_code == 400:
print_success("Duplicate conversion prevented as expected!")
result = response.json()
print_info(f"Error message: {result.get('error')}")
return True
else:
print_error("Duplicate conversion was not prevented!")
print_info(f"Response: {response.json()}")
return False
def test_non_appreciation_type(test_data):
"""Test that non-appreciation complaints cannot be converted"""
print_section("Test 6: Non-Appreciation Type Prevention")
# Create regular complaint type
complaint = Complaint.objects.create(
patient=test_data['patient'],
hospital=test_data['hospital'],
department=test_data['department'],
staff=test_data['staff'],
complaint_type='complaint', # Not appreciation
category='quality_of_care',
subcategory='Wait Time',
severity='medium',
priority='high',
source='web',
title='Long Wait Time',
description='I waited too long for my appointment.',
status='open',
created_by=test_data['px_admin']
)
print_success("Created regular complaint-type complaint")
# Try to convert
client = APIClient()
client.force_authenticate(user=test_data['px_admin'])
category = AppreciationCategory.objects.get(code='patient_feedback')
data = {
'recipient_type': 'user',
'recipient_id': str(test_data['staff'].user.id),
'category_id': str(category.id),
'message_en': 'Test',
'message_ar': 'اختبار',
'visibility': 'private',
'is_anonymous': True,
'close_complaint': False
}
url = reverse('complaints:convert_to_appreciation', kwargs={'pk': complaint.id})
response = client.post(url, data, format='json')
print_info(f"Response status: {response.status_code}")
if response.status_code == 400:
print_success("Non-appreciation conversion prevented as expected!")
result = response.json()
print_info(f"Error message: {result.get('error')}")
return True
else:
print_error("Non-appreciation conversion was not prevented!")
return False
def cleanup_test_data():
"""Clean up test data"""
print_section("Cleanup: Remove Test Data")
# Delete test appreciations
Appreciation.objects.filter(
recipient=test_data['staff']
).delete()
print_success("Deleted test appreciations")
# Delete test complaints
Complaint.objects.filter(
patient=test_data['patient']
).delete()
print_success("Deleted test complaints")
# Delete test patient
test_data['patient'].delete()
print_success("Deleted test patient")
# Delete test staff user
if test_data['staff'].user:
test_data['staff'].user.delete()
test_data['staff'].delete()
print_success("Deleted test staff")
# Delete test department
test_data['department'].delete()
print_success("Deleted test department")
# Delete test hospital
test_data['hospital'].delete()
print_success("Deleted test hospital")
# Delete test px admin
test_data['px_admin'].delete()
print_success("Deleted test PX admin")
def main():
"""Main test runner"""
print_section("Complaint to Appreciation Conversion - Test Suite")
print_info("This test suite validates the conversion feature functionality\n")
all_passed = True
# Test 1: Check default category
if not test_default_category():
print_error("Cannot proceed without default category!")
return False
# Test 2: Create test data
global test_data
test_data = create_test_data()
# Test 3: Create appreciation-type complaint
complaint = test_appreciation_type_complaint(test_data)
# Test 4: Test API endpoint
appreciation = test_api_endpoint(test_data, complaint)
if not appreciation:
all_passed = False
# Test 5: Prevent duplicate conversion
if complaint.metadata.get('appreciation_id'):
if not test_prevention_of_duplicate_conversion(test_data, complaint):
all_passed = False
# Test 6: Prevent non-appreciation conversion
if not test_non_appreciation_type(test_data):
all_passed = False
# Cleanup
cleanup_test_data()
# Summary
print_section("Test Summary")
if all_passed:
print_success("All tests passed! ✓")
print_info("\nThe Complaint to Appreciation Conversion feature is working correctly.")
else:
print_error("Some tests failed! ✗")
print_info("\nPlease review the error messages above and fix any issues.")
return all_passed
if __name__ == '__main__':
try:
success = main()
sys.exit(0 if success else 1)
except Exception as e:
print_error(f"Unexpected error: {e}")
import traceback
traceback.print_exc()
sys.exit(1)