Files
Autoparts-DB/docs/METABASE_ACTIONS.md
consultoria-as 2c6b6e0160 fix(console): fix PostgreSQL connection + add Metabase Actions guide
- Fix console/main.py: import DB_URL instead of missing DB_PATH
- Add sqlalchemy text() import for connection test
- Replace file-exists check with actual PostgreSQL connection test
- Mask password in startup banner
- Add docs/METABASE_ACTIONS.md: complete guide for data entry via
  Metabase Actions (models, forms, dashboard layout, workflows)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 05:52:12 +00:00

13 KiB

Metabase Actions — Alta de Piezas e Intercambios

Requisitos

  • Metabase v0.44+ (Open Source o Pro)
  • Actions habilitadas en Admin → Settings
  • Database con "Model actions" activado

1. Configuración Inicial

1.1 Habilitar Actions

  1. Ir a AdminSettings
  2. Buscar "Enable Actions" → Activar
  3. Ir a AdminDatabases → Click en nexus_autoparts
  4. Activar "Model actions"

1.2 Crear Modelos Base

En Metabase, un Modelo es una pregunta (query) guardada como tabla virtual. Los Actions se vinculan a Modelos.

Modelo 1: Piezas OEM → New → SQL Query:

SELECT
    p.id_part,
    p.oem_part_number,
    p.name_part,
    p.name_es,
    pg.name_part_group AS grupo,
    pc.name_part_category AS categoria,
    p.description,
    p.description_es,
    p.weight_kg,
    mat.name_material AS material
FROM parts p
JOIN part_groups pg ON p.group_id = pg.id_part_group
JOIN part_categories pc ON pg.category_id = pc.id_part_category
LEFT JOIN materials mat ON p.id_material = mat.id_material
ORDER BY p.oem_part_number

Guardar → Click ⋯ → Turn into a model → Nombrar: Piezas OEM

Modelo 2: Fitments → New → SQL Query:

SELECT
    vp.id_vehicle_part,
    b.name_brand AS marca,
    m.name_model AS modelo,
    y.year_car AS año,
    e.name_engine AS motor,
    p.oem_part_number,
    p.name_part AS pieza,
    vp.quantity_required AS cantidad,
    pp.name_position_part AS posicion,
    vp.fitment_notes AS notas
FROM vehicle_parts vp
JOIN model_year_engine mye ON vp.model_year_engine_id = mye.id_mye
JOIN models m ON mye.model_id = m.id_model
JOIN brands b ON m.brand_id = b.id_brand
JOIN years y ON mye.year_id = y.id_year
JOIN engines e ON mye.engine_id = e.id_engine
JOIN parts p ON vp.part_id = p.id_part
LEFT JOIN position_part pp ON vp.id_position_part = pp.id_position_part
ORDER BY b.name_brand, m.name_model, y.year_car

Guardar → Turn into a model → Nombrar: Fitments

Modelo 3: Aftermarket → New → SQL Query:

SELECT
    ap.id_aftermarket_parts,
    p.oem_part_number AS oem_ref,
    p.name_part AS pieza_oem,
    mfr.name_manufacture AS fabricante,
    ap.part_number AS numero_aftermarket,
    ap.name_aftermarket_parts AS nombre,
    ap.name_es AS nombre_es,
    qt.name_quality AS calidad,
    ap.price_usd AS precio_usd,
    ap.warranty_months AS garantia_meses
FROM aftermarket_parts ap
JOIN parts p ON ap.oem_part_id = p.id_part
JOIN manufacturers mfr ON ap.manufacturer_id = mfr.id_manufacture
LEFT JOIN quality_tier qt ON ap.id_quality_tier = qt.id_quality_tier
ORDER BY p.oem_part_number, mfr.name_manufacture

Guardar → Turn into a model → Nombrar: Aftermarket

Modelo 4: Cross-References → New → SQL Query:

SELECT
    pcr.id_part_cross_ref,
    p.oem_part_number AS oem_ref,
    p.name_part AS pieza,
    pcr.cross_reference_number AS numero_cruzado,
    rt.name_ref_type AS tipo_referencia,
    pcr.source_ref AS fuente,
    pcr.notes AS notas
FROM part_cross_references pcr
JOIN parts p ON pcr.part_id = p.id_part
LEFT JOIN reference_type rt ON pcr.id_ref_type = rt.id_ref_type
ORDER BY p.oem_part_number, rt.name_ref_type

Guardar → Turn into a model → Nombrar: Cross-References


2. Crear Actions (Formularios de Alta)

Para cada Modelo, crear Actions que permiten insertar datos.

Action 1: Nueva Pieza OEM

  1. Abrir el modelo Piezas OEM
  2. Click InfoActionsNew action
  3. Nombrar: Alta de Pieza OEM
  4. Pegar este SQL:
INSERT INTO parts (
    oem_part_number,
    name_part,
    name_es,
    group_id,
    description,
    description_es,
    weight_kg,
    id_material
) VALUES (
    {{oem_part_number}},
    {{name_part}},
    {{name_es}},
    {{group_id}},
    {{description}},
    {{description_es}},
    {{weight_kg}},
    {{id_material}}
)
  1. Configurar campos del formulario:
Variable Label Tipo Requerido
oem_part_number Número OEM string Si
name_part Nombre (EN) string Si
name_es Nombre (ES) string No
group_id ID Grupo number Si
description Descripción (EN) string (long) No
description_es Descripción (ES) string (long) No
weight_kg Peso (kg) number No
id_material ID Material number No
  1. Click Save

Tip: Para que el usuario no tenga que memorizar group_id, crea una pregunta auxiliar con los grupos disponibles:

SELECT pg.id_part_group AS id, pg.name_part_group AS grupo,
       pc.name_part_category AS categoria
FROM part_groups pg
JOIN part_categories pc ON pg.category_id = pc.id_part_category
ORDER BY pc.display_order, pg.display_order

Action 2: Nuevo Fitment (vincular pieza a vehículo)

  1. Abrir el modelo Fitments
  2. New action → Nombrar: Alta de Fitment
  3. SQL:
INSERT INTO vehicle_parts (
    model_year_engine_id,
    part_id,
    quantity_required,
    id_position_part,
    fitment_notes
) VALUES (
    {{model_year_engine_id}},
    {{part_id}},
    {{quantity_required}},
    {{id_position_part}},
    {{fitment_notes}}
)
Variable Label Tipo Requerido Default
model_year_engine_id ID Vehículo (MYE) number Si
part_id ID Pieza number Si
quantity_required Cantidad number No 1
id_position_part Posición (1=front, 2=rear) number No
fitment_notes Notas string No

Tip: Para encontrar el model_year_engine_id, crea esta pregunta auxiliar:

SELECT mye.id_mye AS id, b.name_brand AS marca,
       m.name_model AS modelo, y.year_car AS año, e.name_engine AS motor
FROM model_year_engine mye
JOIN models m ON mye.model_id = m.id_model
JOIN brands b ON m.brand_id = b.id_brand
JOIN years y ON mye.year_id = y.id_year
JOIN engines e ON mye.engine_id = e.id_engine
WHERE b.name_brand ILIKE {{'%' || marca || '%'}}
  AND m.name_model ILIKE {{'%' || modelo || '%'}}
ORDER BY b.name_brand, m.name_model, y.year_car

Action 3: Fitment Masivo (una pieza → varios vehículos)

  1. En el modelo FitmentsNew action
  2. Nombrar: Fitment Masivo por Marca/Modelo/Años
  3. SQL:
INSERT INTO vehicle_parts (model_year_engine_id, part_id, quantity_required, id_position_part)
SELECT mye.id_mye, {{part_id}}, {{quantity_required}}, {{id_position_part}}
FROM model_year_engine mye
JOIN models m ON mye.model_id = m.id_model
JOIN brands b ON m.brand_id = b.id_brand
JOIN years y ON mye.year_id = y.id_year
WHERE b.name_brand ILIKE {{marca}}
  AND m.name_model ILIKE {{modelo}}
  AND y.year_car BETWEEN {{year_from}} AND {{year_to}}
ON CONFLICT DO NOTHING
Variable Label Tipo Requerido
part_id ID Pieza number Si
marca Marca (ej: TOYOTA) string Si
modelo Modelo (ej: Camry) string Si
year_from Año desde number Si
year_to Año hasta number Si
quantity_required Cantidad number Si
id_position_part Posición (1=front, 2=rear, vacío=N/A) number No

Action 4: Nueva Pieza Aftermarket

  1. En el modelo AftermarketNew action
  2. Nombrar: Alta de Pieza Aftermarket
  3. SQL:
INSERT INTO aftermarket_parts (
    oem_part_id,
    manufacturer_id,
    part_number,
    name_aftermarket_parts,
    name_es,
    id_quality_tier,
    price_usd,
    warranty_months
) VALUES (
    {{oem_part_id}},
    {{manufacturer_id}},
    {{part_number}},
    {{name_aftermarket_parts}},
    {{name_es}},
    {{id_quality_tier}},
    {{price_usd}},
    {{warranty_months}}
)
Variable Label Tipo Requerido
oem_part_id ID Pieza OEM number Si
manufacturer_id ID Fabricante number Si
part_number Número Aftermarket string Si
name_aftermarket_parts Nombre (EN) string No
name_es Nombre (ES) string No
id_quality_tier Calidad (1=economy, 2=oem, 3=premium, 4=standard) number No
price_usd Precio USD number No
warranty_months Garantía (meses) number No

Tip: Pregunta auxiliar para fabricantes:

SELECT id_manufacture AS id, name_manufacture AS fabricante
FROM manufacturers ORDER BY name_manufacture

Action 5: Nueva Cross-Reference

  1. En el modelo Cross-ReferencesNew action
  2. Nombrar: Alta de Cross-Reference
  3. SQL:
INSERT INTO part_cross_references (
    part_id,
    cross_reference_number,
    id_ref_type,
    source_ref,
    notes
) VALUES (
    {{part_id}},
    {{cross_reference_number}},
    {{id_ref_type}},
    {{source_ref}},
    {{notes}}
)
Variable Label Tipo Requerido
part_id ID Pieza OEM number Si
cross_reference_number Número de Referencia string Si
id_ref_type Tipo (1=competitor, 2=interchange, 3=oem_alternate, 4=supersession) number No
source_ref Fuente string No
notes Notas string No

3. Dashboard de Carga de Datos

Crear un Dashboard que agrupe todo el flujo de carga:

  1. NewDashboard → Nombrar: Panel de Carga de Datos
  2. Agregar estas tarjetas:

Fila 1: Consulta rápida

  • Buscar Pieza (pregunta con filtro {{oem_number}})
  • Buscar Vehículo (pregunta con filtros {{marca}}, {{modelo}})

Fila 2: Botones de Actions

  • + Nueva Pieza OEM → Action 1
  • + Nuevo Fitment → Action 2
  • + Fitment Masivo → Action 3
  • + Aftermarket → Action 4
  • + Cross-Reference → Action 5

Fila 3: Referencias

  • Tabla de Grupos (grupos con IDs para referencia)
  • Tabla de Fabricantes (fabricantes con IDs)
  • Estadísticas (conteos actuales)

Fila 4: Últimos registros

  • Últimas piezas cargadas:
    SELECT oem_part_number, name_part, name_es, created_at
    FROM parts ORDER BY created_at DESC LIMIT 10
    
  • Últimos fitments:
    SELECT b.name_brand, m.name_model, y.year_car, p.oem_part_number, vp.created_at
    FROM vehicle_parts vp
    JOIN model_year_engine mye ON vp.model_year_engine_id = mye.id_mye
    JOIN models m ON mye.model_id = m.id_model
    JOIN brands b ON m.brand_id = b.id_brand
    JOIN years y ON mye.year_id = y.id_year
    JOIN parts p ON vp.part_id = p.id_part
    ORDER BY vp.created_at DESC LIMIT 10
    

4. Flujo de Trabajo Recomendado

Para cargar una pieza nueva con todo su contexto:

1. Abrir "Panel de Carga de Datos"

2. Click [+ Nueva Pieza OEM]
   → Llenar: OEM#, Nombre, Grupo, Descripción
   → Submit → Anotar el ID generado

3. Click [+ Fitment Masivo]
   → Ingresar: ID pieza, Marca, Modelo, Rango de años
   → Submit → La pieza queda vinculada a todos los vehículos

4. Click [+ Aftermarket] (repetir por cada fabricante)
   → Ingresar: ID pieza OEM, ID fabricante, # aftermarket, precio
   → Submit

5. Click [+ Cross-Reference] (repetir por cada referencia)
   → Ingresar: ID pieza, # referencia, tipo
   → Submit

6. Verificar en "Últimos registros" que todo se cargó

5. Preguntas Auxiliares Importantes

Guardar estas como preguntas para tener a mano durante la carga:

Buscar pieza por número

SELECT id_part, oem_part_number, name_part, name_es
FROM parts
WHERE oem_part_number ILIKE {{'%' || numero || '%'}}
   OR name_part ILIKE {{'%' || numero || '%'}}
ORDER BY oem_part_number
LIMIT 50

Buscar vehículo por marca/modelo

SELECT mye.id_mye, b.name_brand, m.name_model, y.year_car, e.name_engine
FROM model_year_engine mye
JOIN models m ON mye.model_id = m.id_model
JOIN brands b ON m.brand_id = b.id_brand
JOIN years y ON mye.year_id = y.id_year
JOIN engines e ON mye.engine_id = e.id_engine
WHERE b.name_brand ILIKE {{'%' || marca || '%'}}
  AND m.name_model ILIKE {{'%' || modelo || '%'}}
ORDER BY y.year_car DESC
LIMIT 100

Catálogo de grupos (referencia para group_id)

SELECT pg.id_part_group AS id, pg.name_part_group AS grupo,
       pc.name_part_category AS categoria
FROM part_groups pg
JOIN part_categories pc ON pg.category_id = pc.id_part_category
ORDER BY pc.display_order, pg.display_order

Catálogo de fabricantes (referencia para manufacturer_id)

SELECT m.id_manufacture AS id, m.name_manufacture AS fabricante,
       mt.name_type_manu AS tipo, qt.name_quality AS calidad
FROM manufacturers m
LEFT JOIN manufacture_type mt ON m.id_type_manu = mt.id_type_manu
LEFT JOIN quality_tier qt ON m.id_quality_tier = qt.id_quality_tier
ORDER BY m.name_manufacture

6. IDs de Referencia Rápida

Calidad (id_quality_tier)

ID Valor
1 economy
2 oem
3 premium
4 standard

Tipo de referencia (id_ref_type)

ID Valor Uso
1 competitor Número de competidor equivalente
2 interchange Intercambio directo compatible
3 oem_alternate Número OEM alterno
4 supersession Pieza que esta reemplaza

Posición (id_position_part)

ID Valor
1 front
2 rear

Tipo de fabricante (id_type_manu)

ID Valor
1 aftermarket
2 oem