clinical_laboratory/CLAUDE.md
Luis Ernesto Portillo Zaldivar ddbc829103 feat: Reorganización de scripts y actualización automática de logo
- 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>
2025-07-15 03:50:46 -06:00

8.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a Laboratory Information Management System (LIMS) module for Odoo 18 ERP, specifically designed for clinical laboratories. The module manages patients, samples, analyses, and test results.

Key Technologies

  • Odoo 18: ERP framework (Python-based)
  • PostgreSQL 15: Database
  • Docker & Docker Compose: Containerization
  • Gitea: Version control and issue tracking

Development Commands

Starting the Environment

# Start all services
docker-compose up -d

# MANDATORY: View initialization logs to check for errors
docker-compose logs odoo_init

# Stop and clean everything (removes volumes)
docker-compose down -v

IMPORTANT: Odoo initialization takes approximately 5 minutes. When using docker-compose commands, set timeout to 5 minutes (300000ms) to avoid premature timeouts.

Instance Persistence Policy

After successful installation/update, the instance must remain active for user validation. Do NOT stop the instance until user explicitly confirms testing is complete.

MANDATORY Testing Rule

CRITICAL: After EVERY task that modifies code, models, views, or data:

  1. Restart the ephemeral instance: docker-compose down -v && docker-compose up -d
  2. Check initialization logs for errors: docker-compose logs odoo_init | grep -i "error\|traceback\|exception"
  3. Verify successful completion: docker-compose logs odoo_init | tail -30
  4. Only proceed to next task if no errors are found
  5. If errors are found, fix them before continuing

Development Workflow per Task

When implementing issues with multiple tasks, follow this workflow for EACH task:

  1. Stop instance: docker-compose down -v
  2. Implement the task: Make code changes
  3. Start instance: docker-compose up -d (timeout: 300000ms)
  4. Validate logs: Check for errors in initialization
  5. Commit & Push: git add -A && git commit -m "feat(#X): Task description" && git push
  6. Comment on issue: Update issue with task completion
  7. Mark task completed: Update todo list
  8. Proceed to next task: Only if no errors found

Database Operations

Direct PostgreSQL Access

# Connect to PostgreSQL
docker exec -it lims_db psql -U odoo -d odoo

For complex queries, use Python scripts with Odoo ORM:

  1. Create script (e.g., test/verify_products.py):
import odoo
import json

def verify_lab_order_products(cr):
    cr.execute("""SELECT ... FROM sale_order ...""")
    return cr.fetchall()

if __name__ == '__main__':
    db_name = 'lims_demo'
    registry = odoo.registry(db_name)
    with registry.cursor() as cr:
        results = verify_lab_order_products(cr)
        print(json.dumps(results, indent=4))
  1. Copy to container:
docker cp test/verify_products.py lims_odoo:/tmp/verify_products.py
  1. Execute:
docker-compose exec odoo python3 /tmp/verify_products.py

Gitea Integration

# Create issue
python utils/gitea_cli_helper.py create-issue --title "Title" --body "Description\nSupports multiple lines"

# Create PR with inline description
python utils/gitea_cli_helper.py create-pr --head "feature-branch" --base "dev" --title "Title" --body "Description"

# Create PR with description from file
python utils/gitea_cli_helper.py create-pr dev --title "feat(#31): Sample lifecycle" --description-file pr_description.txt

# Comment on issue
python utils/gitea_cli_helper.py comment-issue --issue-number 123 --body "Comment text"

# Close issue
python utils/gitea_cli_helper.py close-issue --issue-number 123

# Get issue details and comments
python utils/gitea_cli_helper.py get-issue --issue-number 8

# List all open issues
python utils/gitea_cli_helper.py list-open-issues

Mandatory Reading

At the start of each work session, read these documents to understand requirements and technical design:

  • documents/requirements/RequerimientoInicial.md
  • documents/requirements/ToBeDesing.md

Code Architecture

Module Structure

  • lims_management/models/: Core business logic
    • partner.py: Patient and healthcare provider management
    • product.py: Analysis types and categories
    • sale_order.py: Analysis orders and sample management
    • stock_lot.py: Sample tracking and lifecycle
    • analysis_range.py: Normal ranges for test results

Odoo 18 Specific Conventions

View Definitions

  • CRITICAL: Use <list> instead of <tree> - using <tree> causes ValueError: Wrong value for ir.ui.view.type: 'tree'
  • View mode in actions must be list,form not tree,form

Visibility Attributes

  • Use invisible attribute directly instead of attrs:
    <!-- Wrong (Odoo < 17) -->
    <field name="field" attrs="{'invisible': [('condition', '=', False)]}"/>
    
    <!-- Correct (Odoo 18) -->
    <field name="field" invisible="not condition"/>
    <field name="field" invisible="condition == False"/>
    

Context with ref()

  • Use eval attribute when using ref() in action contexts:
    <!-- Wrong - ref() undefined in client -->
    <field name="context">{'default_categ_id': ref('module.xml_id')}</field>
    
    <!-- Correct - evaluated on server -->
    <field name="context" eval="{'default_categ_id': ref('module.xml_id')}"/>
    

XPath in View Inheritance

  • Use flexible XPath expressions for robustness:
    <!-- More robust - works with list or tree -->
    <xpath expr="//field[@name='order_line']//field[@name='product_id']" position="attributes">
        <attribute name="domain">[('is_analysis', '=', True)]</attribute>
    </xpath>
    

Data Management

  • Initial Data: lims_management/data/ - Sequences, categories, basic configuration
  • Demo Data:
    • XML files in lims_management/demo/
    • Python scripts in test/ directory for complex demo data creation
    • Use noupdate="1" for demo data to prevent reloading

Security Model

  • Access rights defined in security/ir.model.access.csv
  • Field-level security in security/security.xml
  • Group-based permissions: Laboratory Technician, Manager, etc.

Environment Variables

Required in .env file:

  • GITEA_API_KEY: Personal Access Token for Gitea
  • GITEA_API_KEY_URL: Gitea API base URL (e.g., https://gitea.grupoconsiti.com/api/v1/)
  • GITEA_USERNAME: Gitea username (repository owner)
  • GITEA_REPO_NAME: Repository name (e.g., clinical_laboratory)

Important Patterns

Sample Lifecycle States

STATE_PENDING_COLLECTION = 'pending_collection'
STATE_COLLECTED = 'collected'
STATE_IN_ANALYSIS = 'in_analysis'
STATE_COMPLETED = 'completed'
STATE_CANCELLED = 'cancelled'

Barcode Generation

  • 13-digit format: YYMMDDNNNNNNC
  • Uses barcode Python library for Code-128 generation
  • Stored as PDF with human-readable text

Demo Data Creation

XML Files (Simple Data)

  • Use for basic records without complex dependencies
  • Place in lims_management/demo/
  • Use noupdate="1" to prevent reloading
  • IMPORTANT: Do NOT create sale.order records in XML demo files - use Python scripts instead

Python Scripts (Complex Data)

For data with dependencies or business logic:

Test Scripts

  • IMPORTANT: Always create test scripts inside the test/ folder within the project directory
  • Example: test/test_sample_generation.py
  • This ensures scripts are properly organized and accessible
  1. Create script:
import odoo

def create_lab_requests(cr):
    env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
    
    # Use ref() to get existing records
    patient1 = env.ref('lims_management.demo_patient_1')
    hemograma = env.ref('lims_management.analysis_hemograma')
    
    # Create records with business logic
    env['sale.order'].create({
        'partner_id': patient1.id,
        'is_lab_request': True,
        'order_line': [(0, 0, {
            'product_id': hemograma.product_variant_id.id,
            'product_uom_qty': 1
        })]
    })

if __name__ == '__main__':
    db_name = 'lims_demo'
    registry = odoo.registry(db_name)
    with registry.cursor() as cr:
        create_lab_requests(cr)
        cr.commit()
  1. Integrate in initialization or run separately

Git Workflow

Pre-commit Hook

Automatically installed via scripts/install_hooks.sh:

  • Prevents commits to 'main' or 'dev' branches
  • Enforces feature branch workflow

Branch Naming

  • Feature branches: feature/XX-description (where XX is issue number)
  • Always create PRs to 'dev' branch, not 'main'