diff --git a/.env b/.env new file mode 100644 index 0000000..ca51609 --- /dev/null +++ b/.env @@ -0,0 +1,11 @@ +# Variables de entorno para el entorno de Docker de Odoo + +# PostgreSQL +POSTGRES_DB=postgres +POSTGRES_USER=odoo +POSTGRES_PASSWORD=supersegura + +# Odoo +ODOO_DB_NAME=lims_demo +ODOO_MASTER_PASSWORD=admin +ODOO_WEB_PORT=8069 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..813c087 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +# Usa la imagen oficial de Odoo 18 +FROM odoo:18.0 + +# Establece la variable de entorno para el archivo de configuración +ENV ODOO_RC /etc/odoo/odoo.conf + +# Copia el archivo de configuración de Odoo al contenedor +COPY odoo.conf /etc/odoo/odoo.conf + +# Opcional: Cambia los permisos del archivo de configuración +USER root +RUN chown odoo:odoo /etc/odoo/odoo.conf +USER odoo + +# El CMD por defecto de la imagen de Odoo usará ODOO_RC +# y los parámetros del docker-compose para iniciar. +# No es necesario sobreescribir el CMD si pasamos las variables correctas. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3538b1c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,63 @@ + +services: + # ──────────────────────────────────────────── + # PostgreSQL + # ──────────────────────────────────────────── + db: + image: postgres:15 + container_name: lims_db + environment: + POSTGRES_DB: postgres # BD catálogo + POSTGRES_USER: odoo # rol que usará Odoo + POSTGRES_PASSWORD: supersegura # contraseña del rol + volumes: + - db_data:/var/lib/postgresql/data + restart: unless-stopped + + # ──────────────────────────────────────────── + # Job de inicialización (se ejecuta una vez) + # ──────────────────────────────────────────── + odoo_init: + image: odoo:18.0 + depends_on: [db] + volumes: + - ./lims_management:/mnt/extra-addons/lims_management + - ./odoo.conf:/etc/odoo/odoo.conf + - ./init_odoo.py:/app/init_odoo.py + command: ["/usr/bin/python3", "/app/init_odoo.py"] + environment: + HOST: db + PORT: "5432" + USER: odoo + PASSWORD: supersegura + restart: "no" + + + # ──────────────────────────────────────────── + # Odoo (servicio de larga vida) + # ──────────────────────────────────────────── + odoo: + image: odoo:18.0 + container_name: lims_odoo + depends_on: + db: + condition: service_started + odoo_init: + condition: service_completed_successfully + environment: + HOST: db + PORT: "5432" + USER: odoo + PASSWORD: supersegura + MASTER_PASSWORD: admin123 + command: ["/usr/bin/python3", "/app/wait_and_start_odoo.py"] + ports: + - "8069:8069" + volumes: + - ./lims_management:/mnt/extra-addons/lims_management + - ./odoo.conf:/etc/odoo/odoo.conf + - ./wait_and_start_odoo.py:/app/wait_and_start_odoo.py + restart: unless-stopped + +volumes: + db_data: {} diff --git a/init_odoo.py b/init_odoo.py new file mode 100644 index 0000000..ba8762c --- /dev/null +++ b/init_odoo.py @@ -0,0 +1,68 @@ +import socket +import time +import subprocess +import sys +import os + +# --- Configuración --- +DB_HOST = os.environ.get("HOST", "db") +DB_PORT = int(os.environ.get("PORT", 5432)) +ODOO_CONF = "/etc/odoo/odoo.conf" +DB_NAME = "lims_demo" +MODULES_TO_INSTALL = "base,sale_management,stock,account,lims_management" + +# --- Lógica de espera de PostgreSQL --- +print(f"Esperando a PostgreSQL en {DB_HOST}:{DB_PORT}...") +sys.stdout.flush() + +while True: + try: + with socket.create_connection((DB_HOST, DB_PORT), timeout=2): + print("PostgreSQL está listo.") + sys.stdout.flush() + break + except (socket.timeout, ConnectionRefusedError, OSError) as e: + print(f"PostgreSQL no está listo todavía ({e}), esperando...") + sys.stdout.flush() + time.sleep(2) + +# --- Lógica de inicialización de Odoo --- +print(f"Creando base de datos '{DB_NAME}' e instalando módulos...") +sys.stdout.flush() + +odoo_command = [ + "odoo", + "-c", ODOO_CONF, + "-d", DB_NAME, + "-i", MODULES_TO_INSTALL, + "--stop-after-init" +] + +# Usamos subprocess.run para tener mejor control sobre la salida +try: + result = subprocess.run( + odoo_command, + capture_output=True, + text=True, + check=False + ) + + print("--- Odoo stdout ---") + print(result.stdout) + print("--- Odoo stderr ---") + print(result.stderr) + sys.stdout.flush() + + if result.returncode != 0: + print(f"Odoo falló con código de salida {result.returncode}") + sys.exit(result.returncode) + + print("Inicialización de Odoo completada exitosamente.") + sys.exit(0) + +except FileNotFoundError: + print("Error: El comando 'odoo' no se encontró. Asegúrate de que la imagen del contenedor es correcta y odoo está en el PATH.") + sys.exit(1) +except Exception as e: + print(f"Ocurrió un error inesperado al ejecutar Odoo: {e}") + sys.exit(1) diff --git a/lims_management/__pycache__/__init__.cpython-312.pyc b/lims_management/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..52b6a3e Binary files /dev/null and b/lims_management/__pycache__/__init__.cpython-312.pyc differ diff --git a/lims_management/models/__pycache__/__init__.cpython-312.pyc b/lims_management/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..6650407 Binary files /dev/null and b/lims_management/models/__pycache__/__init__.cpython-312.pyc differ diff --git a/odoo.conf b/odoo.conf new file mode 100644 index 0000000..b4a8c54 --- /dev/null +++ b/odoo.conf @@ -0,0 +1,10 @@ +[options] +admin_passwd = admin123 +db_host = db +db_port = 5432 +db_user = odoo +db_password = supersegura +addons_path = /mnt/extra-addons,/usr/lib/python3/dist-packages/odoo/addons +demo = True +dbfilter = ^lims_demo$ +log_level = info diff --git a/wait_and_start_odoo.py b/wait_and_start_odoo.py new file mode 100644 index 0000000..b2f9edb --- /dev/null +++ b/wait_and_start_odoo.py @@ -0,0 +1,46 @@ +import socket +import time +import os +import sys + +# --- Configuración de la base de datos (leída desde el entorno) --- +DB_HOST = os.environ.get("HOST", "db") +DB_PORT = int(os.environ.get("PORT", 5432)) + +# --- Lógica de espera de PostgreSQL --- +print(f"Servicio Odoo: Esperando a PostgreSQL en {DB_HOST}:{DB_PORT}...") +sys.stdout.flush() + +# Usamos un bucle para intentar la conexión hasta que tenga éxito +while True: + try: + # Intenta crear una conexión de socket + with socket.create_connection((DB_HOST, DB_PORT), timeout=5): + print("Servicio Odoo: PostgreSQL está listo y aceptando conexiones.") + sys.stdout.flush() + break # Sale del bucle si la conexión es exitosa + except (socket.timeout, ConnectionRefusedError, OSError) as e: + print(f"Servicio Odoo: PostgreSQL no está listo todavía ({e}). Reintentando en 2 segundos...") + sys.stdout.flush() + time.sleep(2) + +# --- Iniciar Odoo --- +print("Servicio Odoo: PostgreSQL listo. Iniciando Odoo...") +sys.stdout.flush() + +# Argumentos para Odoo. Odoo leerá la configuración principal +# desde /etc/odoo/odoo.conf y las variables de entorno. +# El db-filter se pasa como argumento explícito. +odoo_args = ["odoo", "--db-filter=^lims_demo$"] + +# Reemplaza el proceso actual con Odoo. +# Esto es crucial para que Odoo sea el proceso principal (PID 1) +# y reciba las señales del sistema (ej. para detenerse). +try: + os.execvp("odoo", odoo_args) +except FileNotFoundError: + print("Error fatal: El comando 'odoo' no se encontró en el PATH del contenedor.", file=sys.stderr) + sys.exit(127) +except Exception as e: + print(f"Error fatal al intentar ejecutar Odoo: {e}", file=sys.stderr) + sys.exit(1)