#!/usr/bin/env python3 """ Final validation test for custom task status support in optimized queries. Validates all requirements from task 4. """ import requests import json BASE_URL = 'http://localhost:8000' def login(): """Login and get access token""" response = requests.post(f'{BASE_URL}/auth/login', json={'email': 'admin@vfx.com', 'password': 'admin123'}) if response.status_code != 200: print("❌ Login failed") return None return response.json()['access_token'] def validate_requirement_1_4_2_4(): """ Validate Requirements 1.4 and 2.4: - WHEN custom task statuses exist for a project, THE system SHALL include both default and custom status information in the aggregated data """ print("=" * 80) print("VALIDATING REQUIREMENTS 1.4 & 2.4: Custom Status Support") print("=" * 80) token = login() if not token: return False headers = {'Authorization': f'Bearer {token}'} project_id = 10 # Project with custom statuses # Test 1: Verify project has custom statuses response = requests.get(f'{BASE_URL}/projects/{project_id}/task-statuses', headers=headers) if response.status_code != 200: print("❌ Failed to get project task statuses") return False all_statuses = response.json() system_statuses = [s['id'] for s in all_statuses['system_statuses']] custom_statuses = [s['id'] for s in all_statuses['statuses']] print(f"✅ Project {project_id} has {len(system_statuses)} system statuses and {len(custom_statuses)} custom statuses") if not custom_statuses: print("❌ No custom statuses found - cannot validate requirement") return False # Test 2: Verify shot optimization includes both default and custom statuses response = requests.get(f'{BASE_URL}/shots/?project_id={project_id}', headers=headers) if response.status_code != 200: print("❌ Failed to get shots") return False shots = response.json() if not shots: print("❌ No shots found") return False shot = shots[0] task_status = shot.get('task_status', {}) task_details = shot.get('task_details', []) # Check for both system and custom statuses in task_status found_system_in_status = any(status in system_statuses for status in task_status.values()) found_custom_in_status = any(status in custom_statuses for status in task_status.values()) # Check for both system and custom statuses in task_details detail_statuses = [td['status'] for td in task_details] found_system_in_details = any(status in system_statuses for status in detail_statuses) found_custom_in_details = any(status in custom_statuses for status in detail_statuses) print(f"Shot '{shot['name']}':") print(f" ✅ task_status includes system statuses: {found_system_in_status}") print(f" ✅ task_status includes custom statuses: {found_custom_in_status}") print(f" ✅ task_details includes system statuses: {found_system_in_details}") print(f" ✅ task_details includes custom statuses: {found_custom_in_details}") shot_success = found_system_in_status and found_custom_in_status and found_system_in_details and found_custom_in_details # Test 3: Verify asset optimization includes both default and custom statuses response = requests.get(f'{BASE_URL}/assets/?project_id={project_id}', headers=headers) if response.status_code != 200: print("❌ Failed to get assets") return False assets = response.json() if not assets: print("❌ No assets found") return False asset = assets[0] task_status = asset.get('task_status', {}) task_details = asset.get('task_details', []) # Check for both system and custom statuses in task_status found_system_in_status = any(status in system_statuses for status in task_status.values()) found_custom_in_status = any(status in custom_statuses for status in task_status.values()) # Check for both system and custom statuses in task_details detail_statuses = [td['status'] for td in task_details] found_system_in_details = any(status in system_statuses for status in detail_statuses) found_custom_in_details = any(status in custom_statuses for status in detail_statuses) print(f"Asset '{asset['name']}':") print(f" ✅ task_status includes system statuses: {found_system_in_status}") print(f" ✅ task_status includes custom statuses: {found_custom_in_status}") print(f" ✅ task_details includes system statuses: {found_system_in_details}") print(f" ✅ task_details includes custom statuses: {found_custom_in_details}") asset_success = found_system_in_status and found_custom_in_status and found_system_in_details and found_custom_in_details # Test 4: Verify aggregated data structure is correct required_fields = ['task_type', 'status', 'task_id', 'assigned_user_id'] shot_fields_valid = all(all(field in td for field in required_fields) for td in shot.get('task_details', [])) asset_fields_valid = all(all(field in td for field in required_fields) for td in asset.get('task_details', [])) print(f"Data structure validation:") print(f" ✅ Shot task_details has all required fields: {shot_fields_valid}") print(f" ✅ Asset task_details has all required fields: {asset_fields_valid}") overall_success = shot_success and asset_success and shot_fields_valid and asset_fields_valid if overall_success: print("\n🎉 REQUIREMENTS 1.4 & 2.4 VALIDATION: PASSED") print("✅ Optimized queries successfully include both default and custom status information") else: print("\n❌ REQUIREMENTS 1.4 & 2.4 VALIDATION: FAILED") return overall_success def validate_filtering_and_sorting(): """ Additional validation: Verify that filtering and sorting work with custom statuses """ print("\n" + "=" * 80) print("ADDITIONAL VALIDATION: Filtering and Sorting with Custom Statuses") print("=" * 80) token = login() if not token: return False headers = {'Authorization': f'Bearer {token}'} project_id = 10 # Test filtering with custom status response = requests.get(f'{BASE_URL}/shots/?project_id={project_id}&task_status_filter=layout:custom_9441a740', headers=headers) if response.status_code == 200: filtered_shots = response.json() print(f"✅ Custom status filtering works: {len(filtered_shots)} shots with custom status") else: print(f"❌ Custom status filtering failed: {response.status_code}") return False # Test sorting with custom status response = requests.get(f'{BASE_URL}/assets/?project_id={project_id}&sort_by=modeling_status&sort_direction=asc', headers=headers) if response.status_code == 200: sorted_assets = response.json() print(f"✅ Custom status sorting works: {len(sorted_assets)} assets sorted") else: print(f"❌ Custom status sorting failed: {response.status_code}") return False print("\n🎉 ADDITIONAL VALIDATION: PASSED") return True def main(): print("FINAL VALIDATION: Custom Task Status Support in Optimized Queries") print("Testing Requirements 1.4 and 2.4 from the specification") # Run validation tests req_validation = validate_requirement_1_4_2_4() additional_validation = validate_filtering_and_sorting() # Final summary print("\n" + "=" * 80) print("FINAL VALIDATION SUMMARY") print("=" * 80) if req_validation: print("✅ Requirements 1.4 & 2.4: PASSED") print(" - Optimized queries include both default and custom task statuses") print(" - Aggregated data contains all required information") else: print("❌ Requirements 1.4 & 2.4: FAILED") if additional_validation: print("✅ Additional Features: PASSED") print(" - Filtering with custom statuses works correctly") print(" - Sorting with custom statuses works correctly") else: print("❌ Additional Features: FAILED") overall_success = req_validation and additional_validation if overall_success: print("\n🎉 TASK 4 VALIDATION: COMPLETE SUCCESS") print("Backend Custom Status Support is fully implemented and working!") else: print("\n❌ TASK 4 VALIDATION: NEEDS ATTENTION") return overall_success if __name__ == "__main__": main()