
- Movidos scripts Python a carpetas organizadas (test/ y utils/)
- Agregado logo del laboratorio (lab_logo.png)
- Implementado sistema de actualización automática de logo y nombre de empresa
- Creado script de validación para verificar estado del logo
- Actualizada documentación CLAUDE.md con nuevas rutas
- Eliminados intentos fallidos de cambio de tema CSS
- Ajustado docker-compose.yml para mapear carpetas de scripts
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
153 lines
5.3 KiB
Python
153 lines
5.3 KiB
Python
#!/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") |