#!/usr/bin/env python3 """ Verification script for test-sample relationships in LIMS This script checks that the relationships between analyses and sample types are correctly configured after Issue #44 implementation. """ import odoo import json from datetime import datetime def verify_sample_relationships(cr): """Verify that analyses have proper sample type relationships""" env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {}) print("\n" + "="*60) print("LIMS TEST-SAMPLE RELATIONSHIPS VERIFICATION") print("="*60) print(f"Execution time: {datetime.now()}") print("="*60 + "\n") # 1. Check analyses with sample types print("1. ANALYSES WITH SAMPLE TYPE REQUIREMENTS:") print("-" * 60) analyses = env['product.template'].search([('is_analysis', '=', True)]) if not analyses: print("WARNING: No analyses found in the system!") return missing_sample_type = [] for analysis in analyses: if analysis.required_sample_type_id: print(f"✓ {analysis.name}") print(f" → Sample Type: {analysis.required_sample_type_id.name}") print(f" → Volume Required: {analysis.sample_volume_ml} ml") else: missing_sample_type.append(analysis.name) print(f"✗ {analysis.name} - NO SAMPLE TYPE ASSIGNED") print(f"\nTotal analyses: {len(analyses)}") print(f"With sample type: {len(analyses) - len(missing_sample_type)}") print(f"Missing sample type: {len(missing_sample_type)}") # 2. Check available sample types print("\n2. AVAILABLE SAMPLE TYPES:") print("-" * 60) sample_types = env['product.template'].search([('is_sample_type', '=', True)]) if not sample_types: print("WARNING: No sample types found in the system!") return for sample_type in sample_types: # Count how many analyses use this sample type usage_count = env['product.template'].search_count([ ('is_analysis', '=', True), ('required_sample_type_id', '=', sample_type.id) ]) print(f"• {sample_type.name} - Used by {usage_count} analyses") print(f"\nTotal sample types: {len(sample_types)}") # 3. Check stock.lot samples print("\n3. LABORATORY SAMPLES (stock.lot):") print("-" * 60) lab_samples = env['stock.lot'].search([('is_lab_sample', '=', True)]) if not lab_samples: print("No laboratory samples found in stock.lot") return sync_issues = [] for sample in lab_samples: has_new_field = bool(sample.sample_type_product_id) has_legacy_field = bool(sample.container_type) print(f"\n{sample.name}:") print(f" Patient: {sample.patient_id.name if sample.patient_id else 'None'}") print(f" State: {sample.state}") if has_new_field: print(f" ✓ Sample Type Product: {sample.sample_type_product_id.name}") else: print(f" ✗ Sample Type Product: NOT SET") if has_legacy_field: print(f" Legacy Container Type: {sample.container_type}") # Check synchronization if has_new_field and has_legacy_field: expected_type = _get_expected_container_type(sample.sample_type_product_id.name) if expected_type != sample.container_type: sync_issues.append((sample.name, expected_type, sample.container_type)) print(f"\nTotal lab samples: {len(lab_samples)}") print(f"With new sample_type_product_id: {len([s for s in lab_samples if s.sample_type_product_id])}") print(f"Synchronization issues: {len(sync_issues)}") if sync_issues: print("\nSYNCHRONIZATION ISSUES FOUND:") for name, expected, actual in sync_issues: print(f" {name}: Expected '{expected}', got '{actual}'") # 4. Summary and recommendations print("\n" + "="*60) print("SUMMARY:") print("="*60) if missing_sample_type: print("\n⚠️ ATTENTION REQUIRED:") print(f" - {len(missing_sample_type)} analyses need sample type assignment") print(" - Affected analyses:", ', '.join(missing_sample_type)) if sync_issues: print(f" - {len(sync_issues)} samples have field synchronization issues") if not missing_sample_type and not sync_issues: print("\n✅ All test-sample relationships are properly configured!") print("\n" + "="*60) def _get_expected_container_type(product_name): """Map product name to expected legacy container type""" name_lower = product_name.lower() if 'suero' in name_lower or 'serum' in name_lower: return 'serum_tube' elif 'edta' in name_lower: return 'edta_tube' elif 'hisopo' in name_lower or 'swab' in name_lower: return 'swab' elif 'orina' in name_lower or 'urine' in name_lower: return 'urine' else: return 'other' if __name__ == '__main__': db_name = 'lims_demo' try: registry = odoo.registry(db_name) with registry.cursor() as cr: verify_sample_relationships(cr) except Exception as e: print(f"ERROR: {str(e)}") print("\nMake sure:") print("1. The Odoo instance is running") print("2. The database 'lims_demo' exists") print("3. The LIMS module is installed")