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>
This commit is contained in:
@@ -8,10 +8,11 @@ Usage:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from console.config import VERSION, APP_NAME, APP_SUBTITLE, DB_PATH
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
from console.config import VERSION, APP_NAME, APP_SUBTITLE, DB_URL
|
||||||
|
|
||||||
|
|
||||||
def parse_args(argv=None):
|
def parse_args(argv=None):
|
||||||
@@ -27,20 +28,29 @@ def parse_args(argv=None):
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--db",
|
"--db",
|
||||||
default=DB_PATH,
|
default=DB_URL,
|
||||||
help="Path to the vehicle database (default: auto-detected)",
|
help="PostgreSQL connection URL (default: from config)",
|
||||||
)
|
)
|
||||||
return parser.parse_args(argv)
|
return parser.parse_args(argv)
|
||||||
|
|
||||||
|
|
||||||
def _print_banner(db_path):
|
def _print_banner(db_url):
|
||||||
"""Print a startup banner before entering terminal mode."""
|
"""Print a startup banner before entering terminal mode."""
|
||||||
|
# Mask password in display
|
||||||
|
display_url = db_url
|
||||||
|
if '@' in db_url:
|
||||||
|
pre_at = db_url.split('@')[0]
|
||||||
|
post_at = db_url.split('@', 1)[1]
|
||||||
|
if ':' in pre_at.split('//')[-1]:
|
||||||
|
user = pre_at.split('//')[-1].split(':')[0]
|
||||||
|
display_url = f"postgresql://{user}:****@{post_at}"
|
||||||
|
|
||||||
border = "=" * 58
|
border = "=" * 58
|
||||||
print(border)
|
print(border)
|
||||||
print(f" {APP_NAME} v{VERSION}")
|
print(f" {APP_NAME} v{VERSION}")
|
||||||
print(f" {APP_SUBTITLE}")
|
print(f" {APP_SUBTITLE}")
|
||||||
print(border)
|
print(border)
|
||||||
print(f" DB : {db_path}")
|
print(f" DB : {display_url}")
|
||||||
print(border)
|
print(border)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
@@ -49,20 +59,7 @@ def main(argv=None):
|
|||||||
"""Main entry point: parse args, set up renderer, DB, and launch the app."""
|
"""Main entry point: parse args, set up renderer, DB, and launch the app."""
|
||||||
args = parse_args(argv)
|
args = parse_args(argv)
|
||||||
|
|
||||||
db_path = args.db
|
db_url = args.db
|
||||||
|
|
||||||
# Verify the database file exists before proceeding
|
|
||||||
if not os.path.isfile(db_path):
|
|
||||||
print(
|
|
||||||
f"Error: Database not found at '{db_path}'.\n"
|
|
||||||
f"\n"
|
|
||||||
f"Make sure the vehicle database exists. You can specify a\n"
|
|
||||||
f"custom path with the --db flag:\n"
|
|
||||||
f"\n"
|
|
||||||
f" python -m console --db /path/to/vehicle_database.db\n",
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Lazy imports so the module can be loaded without curses available
|
# Lazy imports so the module can be loaded without curses available
|
||||||
# (e.g. during tests or when just checking --version).
|
# (e.g. during tests or when just checking --version).
|
||||||
@@ -71,9 +68,30 @@ def main(argv=None):
|
|||||||
from console.core.app import App
|
from console.core.app import App
|
||||||
|
|
||||||
# Print startup banner
|
# Print startup banner
|
||||||
_print_banner(db_path)
|
_print_banner(db_url)
|
||||||
|
|
||||||
|
# Test database connection before entering curses mode
|
||||||
|
db = Database(db_url)
|
||||||
|
try:
|
||||||
|
db._get_engine()
|
||||||
|
session = db._session()
|
||||||
|
session.execute(text("SELECT 1"))
|
||||||
|
session.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(
|
||||||
|
f"Error: Cannot connect to database.\n"
|
||||||
|
f"\n"
|
||||||
|
f" URL: {db_url}\n"
|
||||||
|
f" Error: {e}\n"
|
||||||
|
f"\n"
|
||||||
|
f"Make sure PostgreSQL is running and the connection URL is correct.\n"
|
||||||
|
f"You can specify a custom URL with the --db flag:\n"
|
||||||
|
f"\n"
|
||||||
|
f" python -m console --db postgresql://user:pass@host/dbname\n",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
db = Database(db_path)
|
|
||||||
renderer = CursesRenderer()
|
renderer = CursesRenderer()
|
||||||
app = App(renderer=renderer, db=db)
|
app = App(renderer=renderer, db=db)
|
||||||
|
|
||||||
|
|||||||
473
docs/METABASE_ACTIONS.md
Normal file
473
docs/METABASE_ACTIONS.md
Normal file
@@ -0,0 +1,473 @@
|
|||||||
|
# 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 **Admin** → **Settings**
|
||||||
|
2. Buscar **"Enable Actions"** → Activar
|
||||||
|
3. Ir a **Admin** → **Databases** → 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:
|
||||||
|
```sql
|
||||||
|
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:
|
||||||
|
```sql
|
||||||
|
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:
|
||||||
|
```sql
|
||||||
|
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:
|
||||||
|
```sql
|
||||||
|
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 **⋯** → **Info** → **Actions** → **New action**
|
||||||
|
3. Nombrar: `Alta de Pieza OEM`
|
||||||
|
4. Pegar este SQL:
|
||||||
|
|
||||||
|
```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}}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
5. 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 |
|
||||||
|
|
||||||
|
6. Click **Save**
|
||||||
|
|
||||||
|
> **Tip:** Para que el usuario no tenga que memorizar `group_id`, crea una pregunta
|
||||||
|
> auxiliar con los grupos disponibles:
|
||||||
|
> ```sql
|
||||||
|
> 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:
|
||||||
|
|
||||||
|
```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:
|
||||||
|
> ```sql
|
||||||
|
> 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 **Fitments** → **New action**
|
||||||
|
2. Nombrar: `Fitment Masivo por Marca/Modelo/Años`
|
||||||
|
3. SQL:
|
||||||
|
|
||||||
|
```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 **Aftermarket** → **New action**
|
||||||
|
2. Nombrar: `Alta de Pieza Aftermarket`
|
||||||
|
3. SQL:
|
||||||
|
|
||||||
|
```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:
|
||||||
|
> ```sql
|
||||||
|
> 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-References** → **New action**
|
||||||
|
2. Nombrar: `Alta de Cross-Reference`
|
||||||
|
3. SQL:
|
||||||
|
|
||||||
|
```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. **New** → **Dashboard** → 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**:
|
||||||
|
```sql
|
||||||
|
SELECT oem_part_number, name_part, name_es, created_at
|
||||||
|
FROM parts ORDER BY created_at DESC LIMIT 10
|
||||||
|
```
|
||||||
|
- **Últimos fitments**:
|
||||||
|
```sql
|
||||||
|
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
|
||||||
|
```sql
|
||||||
|
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
|
||||||
|
```sql
|
||||||
|
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)
|
||||||
|
```sql
|
||||||
|
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)
|
||||||
|
```sql
|
||||||
|
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 |
|
||||||
Reference in New Issue
Block a user