feat: migrate to PostgreSQL + SQLAlchemy ORM, rebrand to Nexus Autoparts
- Migrate from SQLite to PostgreSQL with normalized schema - Add 11 lookup tables (fuel_type, body_type, drivetrain, transmission, materials, position_part, manufacture_type, quality_tier, countries, reference_type, shapes) - Rewrite dashboard/server.py (76 routes) using SQLAlchemy text() queries - Rewrite console/db.py (27 methods) using SQLAlchemy ORM - Add models.py with 27 SQLAlchemy model definitions - Add config.py for centralized DB_URL configuration - Add migrate_to_postgres.py migration script - Add docs/METABASE_GUIDE.md with complete data entry guide - Rebrand from "AUTOPARTS DB" to "NEXUS AUTOPARTS" - Fill vehicle data gaps via NHTSA API + heuristics: engines (cylinders, power, torque), brands (country, founded_year), models (body_type, production years), MYE (drivetrain, transmission, trim) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# API Reference - Autoparts DB
|
||||
# API Reference - Nexus Autoparts
|
||||
|
||||
Documentación completa de la API REST del sistema Autoparts DB.
|
||||
Documentación completa de la API REST del sistema Nexus Autoparts.
|
||||
|
||||
## Base URL
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Documentación de Base de Datos - Autoparts DB
|
||||
# Documentación de Base de Datos - Nexus Autoparts
|
||||
|
||||
## Resumen
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Guía de Instalación - Autoparts DB
|
||||
# Guía de Instalación - Nexus Autoparts
|
||||
|
||||
## Requisitos del Sistema
|
||||
|
||||
@@ -28,10 +28,10 @@ El proyecto es compatible con:
|
||||
|
||||
```bash
|
||||
# 1. Clonar el repositorio
|
||||
git clone https://git.consultoria-as.com/[usuario]/Autoparts-DB.git
|
||||
git clone https://git.consultoria-as.com/[usuario]/Nexus-Autoparts.git
|
||||
|
||||
# 2. Entrar al directorio
|
||||
cd Autoparts-DB
|
||||
cd Nexus-Autoparts
|
||||
|
||||
# 3. Instalar dependencias
|
||||
pip install -r requirements.txt
|
||||
@@ -48,8 +48,8 @@ python3 server.py
|
||||
### Paso 1: Clonar el Repositorio
|
||||
|
||||
```bash
|
||||
git clone https://git.consultoria-as.com/[usuario]/Autoparts-DB.git
|
||||
cd Autoparts-DB
|
||||
git clone https://git.consultoria-as.com/[usuario]/Nexus-Autoparts.git
|
||||
cd Nexus-Autoparts
|
||||
```
|
||||
|
||||
### Paso 2: Crear Entorno Virtual (Recomendado)
|
||||
@@ -254,16 +254,16 @@ gunicorn -w 4 -b 0.0.0.0:8080 server:app
|
||||
|
||||
### Usando systemd
|
||||
|
||||
Crear archivo `/etc/systemd/system/autoparts-db.service`:
|
||||
Crear archivo `/etc/systemd/system/nexus-autoparts.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Autoparts DB Dashboard
|
||||
Description=Nexus Autoparts Dashboard
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=www-data
|
||||
WorkingDirectory=/path/to/Autoparts-DB/dashboard
|
||||
WorkingDirectory=/path/to/Nexus-Autoparts/dashboard
|
||||
ExecStart=/usr/bin/python3 server.py
|
||||
Restart=always
|
||||
|
||||
@@ -274,8 +274,8 @@ WantedBy=multi-user.target
|
||||
Habilitar e iniciar:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable autoparts-db
|
||||
sudo systemctl start autoparts-db
|
||||
sudo systemctl enable nexus-autoparts
|
||||
sudo systemctl start nexus-autoparts
|
||||
```
|
||||
|
||||
### Usando Docker (Opcional)
|
||||
@@ -294,8 +294,8 @@ CMD ["python3", "dashboard/server.py"]
|
||||
```
|
||||
|
||||
```bash
|
||||
docker build -t autoparts-db .
|
||||
docker run -p 5000:5000 autoparts-db
|
||||
docker build -t nexus-autoparts .
|
||||
docker run -p 5000:5000 nexus-autoparts
|
||||
```
|
||||
|
||||
---
|
||||
@@ -319,7 +319,7 @@ pip install --upgrade -r requirements.txt
|
||||
deactivate
|
||||
|
||||
# Eliminar directorio del proyecto
|
||||
rm -rf Autoparts-DB
|
||||
rm -rf Nexus-Autoparts
|
||||
|
||||
# Eliminar entorno virtual (si está separado)
|
||||
rm -rf venv
|
||||
|
||||
599
docs/METABASE_GUIDE.md
Normal file
599
docs/METABASE_GUIDE.md
Normal file
@@ -0,0 +1,599 @@
|
||||
# Guía Metabase — Nexus Autoparts
|
||||
|
||||
## 1. Conexión a la Base de Datos
|
||||
|
||||
### Datos de conexión PostgreSQL
|
||||
|
||||
| Campo | Valor |
|
||||
|-------|-------|
|
||||
| **Host** | `localhost` (o la IP del servidor: `192.168.10.198`) |
|
||||
| **Puerto** | `5432` |
|
||||
| **Base de datos** | `nexus_autoparts` |
|
||||
| **Usuario** | `nexus` |
|
||||
| **Contraseña** | `nexus_autoparts_2026` |
|
||||
| **SSL** | No requerido (conexión local) |
|
||||
|
||||
### Pasos en Metabase
|
||||
|
||||
1. Ir a **Admin** → **Databases** → **Add database**
|
||||
2. Seleccionar **PostgreSQL**
|
||||
3. Llenar los campos con los datos anteriores
|
||||
4. Click **Save**
|
||||
5. Metabase sincronizará las tablas automáticamente (~30 segundos)
|
||||
|
||||
> **Tip:** Si Metabase está en otro servidor, usar la IP `192.168.10.198` en lugar de `localhost`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Estructura de la Base de Datos
|
||||
|
||||
### Diagrama de relaciones simplificado
|
||||
|
||||
```
|
||||
brands ──→ models ──→ model_year_engine (MYE) ←── years
|
||||
↑ ↑ ↑
|
||||
engines │ vehicle_parts ──→ parts
|
||||
│ ↑
|
||||
vehicle_diagrams part_cross_references
|
||||
↓ aftermarket_parts
|
||||
diagrams diagram_hotspots
|
||||
```
|
||||
|
||||
### Tablas principales (con datos)
|
||||
|
||||
| Tabla | Registros | Descripción |
|
||||
|-------|-----------|-------------|
|
||||
| `brands` | 102 | Marcas de vehículos |
|
||||
| `models` | 4,031 | Modelos por marca |
|
||||
| `years` | 80 | Años (1946-2026) |
|
||||
| `engines` | 13,430 | Motores con specs |
|
||||
| `model_year_engine` | 47,858 | Combinación marca-modelo-año-motor |
|
||||
|
||||
### Tablas de piezas (vacías — para llenar)
|
||||
|
||||
| Tabla | Descripción |
|
||||
|-------|-------------|
|
||||
| `parts` | Piezas OEM (número de parte, nombre, grupo) |
|
||||
| `vehicle_parts` | Relación pieza ↔ vehículo (fitments) |
|
||||
| `aftermarket_parts` | Piezas aftermarket por fabricante |
|
||||
| `part_cross_references` | Intercambios y referencias cruzadas |
|
||||
| `manufacturers` | 47 fabricantes ya cargados |
|
||||
|
||||
### Tablas lookup (catálogos de referencia)
|
||||
|
||||
| Tabla | Valores actuales |
|
||||
|-------|-----------------|
|
||||
| `part_categories` | 12: Body, Brake, Cooling, Drivetrain, Electrical, Engine, Exhaust, Fuel, HVAC, Steering, Suspension, Transmission |
|
||||
| `part_groups` | 63 grupos dentro de las categorías |
|
||||
| `quality_tier` | economy, standard, oem, premium |
|
||||
| `reference_type` | competitor, interchange, oem_alternate, supersession |
|
||||
| `position_part` | front, rear |
|
||||
| `manufacture_type` | aftermarket, oem |
|
||||
| `materials` | (vacía — agregar según se necesite) |
|
||||
|
||||
---
|
||||
|
||||
## 3. Alta de Piezas OEM
|
||||
|
||||
### Orden obligatorio de carga
|
||||
|
||||
```
|
||||
1. materials (si aplica)
|
||||
2. parts ← PRIMERO las piezas
|
||||
3. vehicle_parts ← DESPUÉS los fitments
|
||||
4. aftermarket_parts
|
||||
5. part_cross_references
|
||||
```
|
||||
|
||||
> **IMPORTANTE:** Respetar este orden. `vehicle_parts` y `aftermarket_parts` requieren que la pieza ya exista en `parts`.
|
||||
|
||||
---
|
||||
|
||||
### 3.1 Agregar una pieza OEM (`parts`)
|
||||
|
||||
En Metabase: click **+ New** → **SQL query** → ejecutar:
|
||||
|
||||
```sql
|
||||
INSERT INTO parts (oem_part_number, name_part, name_es, group_id, description, description_es, weight_kg, id_material)
|
||||
VALUES (
|
||||
'04465-06090', -- Número OEM (obligatorio, único por grupo)
|
||||
'Front Brake Pad Set', -- Nombre en inglés (obligatorio)
|
||||
'Juego de Balatas Delanteras', -- Nombre en español (opcional)
|
||||
16, -- group_id: 16 = Brake Pads (ver tabla abajo)
|
||||
'Ceramic brake pad set for front axle', -- Descripción EN (opcional)
|
||||
'Juego de balatas cerámicas para eje delantero', -- Descripción ES (opcional)
|
||||
1.2, -- Peso en kg (opcional)
|
||||
NULL -- id_material (opcional, ver tabla materials)
|
||||
);
|
||||
```
|
||||
|
||||
### Carga masiva de piezas
|
||||
|
||||
```sql
|
||||
INSERT INTO parts (oem_part_number, name_part, name_es, group_id, description) VALUES
|
||||
('04465-06090', 'Front Brake Pad Set', 'Juego Balatas Delanteras', 16, 'Ceramic front pads'),
|
||||
('04465-33471', 'Front Brake Pad Set', 'Juego Balatas Delanteras', 16, 'Semi-metallic front pads'),
|
||||
('43512-06150', 'Front Brake Rotor', 'Disco de Freno Delantero', 17, 'Vented front rotor 296mm'),
|
||||
('19101-28491', 'Radiator', 'Radiador', 31, 'Aluminum core radiator'),
|
||||
('16400-28531', 'Cooling Fan Assembly', 'Ensamble Ventilador', 35, 'Electric cooling fan')
|
||||
ON CONFLICT DO NOTHING;
|
||||
```
|
||||
|
||||
### Referencia de `group_id` (grupos de piezas)
|
||||
|
||||
| group_id | Grupo | Categoría |
|
||||
|----------|-------|-----------|
|
||||
| **Frenos y Ruedas** | | |
|
||||
| 16 | Brake Pads | Brake & Wheel Hub |
|
||||
| 17 | Brake Rotors | Brake & Wheel Hub |
|
||||
| 20 | Brake Calipers | Brake & Wheel Hub |
|
||||
| 27 | Wheel Bearings | Brake & Wheel Hub |
|
||||
| 28 | Wheel Hubs | Brake & Wheel Hub |
|
||||
| **Motor** | | |
|
||||
| 70 | Oil Filters | Engine |
|
||||
| 71 | Air Filters | Engine |
|
||||
| 72 | Spark Plugs | Engine |
|
||||
| 73 | Belts | Engine |
|
||||
| 76 | Timing Components | Engine |
|
||||
| 91 | Engine Mounts | Engine |
|
||||
| **Enfriamiento** | | |
|
||||
| 31 | Radiators | Cooling System |
|
||||
| 33 | Water Pumps | Cooling System |
|
||||
| 34 | Thermostats | Cooling System |
|
||||
| 35 | Cooling Fans | Cooling System |
|
||||
| **Eléctrico** | | |
|
||||
| 55 | Alternators | Electrical & Lighting |
|
||||
| 56 | Starters | Electrical & Lighting |
|
||||
| 57 | Ignition Coils | Electrical & Lighting |
|
||||
| 65 | Sensors | Electrical & Lighting |
|
||||
| **Combustible** | | |
|
||||
| 110 | Fuel Pumps | Fuel & Air |
|
||||
| 111 | Fuel Filters | Fuel & Air |
|
||||
| 112 | Fuel Injectors | Fuel & Air |
|
||||
| **Escape** | | |
|
||||
| 99 | Catalytic Converters | Exhaust |
|
||||
| 100 | Mufflers | Exhaust |
|
||||
| 108 | Headers | Exhaust |
|
||||
| **Dirección** | | |
|
||||
| 141 | Power Steering Pumps | Steering |
|
||||
| 144 | Steering Racks | Steering |
|
||||
| 145 | Steering Gearboxes | Steering |
|
||||
| 146 | Tie Rods | Steering |
|
||||
| 147 | Tie Rod Ends | Steering |
|
||||
| 148 | Inner Tie Rods | Steering |
|
||||
| 151 | Pitman Arms | Steering |
|
||||
| 152 | Idler Arms | Steering |
|
||||
| 153 | Center Links | Steering |
|
||||
| 154 | Drag Links | Steering |
|
||||
| 155 | Steering Knuckles | Steering |
|
||||
| 191 | Steering Dampers | Steering |
|
||||
| **Suspensión** | | |
|
||||
| 156 | Shocks | Suspension |
|
||||
| 157 | Struts | Suspension |
|
||||
| 158 | Strut Mounts | Suspension |
|
||||
| 159 | Coil Springs | Suspension |
|
||||
| 160 | Leaf Springs | Suspension |
|
||||
| 161 | Control Arms | Suspension |
|
||||
| 164 | Ball Joints | Suspension |
|
||||
| 165 | Bushings | Suspension |
|
||||
| 167 | Sway Bar Links | Suspension |
|
||||
| 168 | Sway Bar Bushings | Suspension |
|
||||
| 169 | Torsion Bars | Suspension |
|
||||
| 170 | Trailing Arms | Suspension |
|
||||
| **Transmisión** | | |
|
||||
| 175 | Transmission Filters | Transmission |
|
||||
| 185 | Transmission Mounts | Transmission |
|
||||
| **A/C y Calefacción** | | |
|
||||
| 127 | AC Compressors | Heat & Air Conditioning |
|
||||
| 135 | Blower Motors | Heat & Air Conditioning |
|
||||
| 138 | Cabin Air Filters | Heat & Air Conditioning |
|
||||
| **Tren Motriz** | | |
|
||||
| 44 | CV Axles | Drivetrain |
|
||||
| 45 | CV Joints | Drivetrain |
|
||||
| 50 | Axle Shafts | Drivetrain |
|
||||
| **Carrocería** | | |
|
||||
| 15 | Moldings & Trim | Body & Lamp Assembly |
|
||||
|
||||
---
|
||||
|
||||
## 4. Alta de Fitments (Pieza ↔ Vehículo)
|
||||
|
||||
Un fitment vincula una pieza con un vehículo específico (combinación modelo-año-motor).
|
||||
|
||||
### 4.1 Encontrar el `id_mye` del vehículo
|
||||
|
||||
```sql
|
||||
-- Buscar el id_mye para un vehículo específico
|
||||
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 'Toyota'
|
||||
AND m.name_model ILIKE 'Camry'
|
||||
AND y.year_car = 2020
|
||||
ORDER BY e.name_engine;
|
||||
```
|
||||
|
||||
### 4.2 Encontrar el `id_part` de la pieza
|
||||
|
||||
```sql
|
||||
-- Buscar pieza por número OEM
|
||||
SELECT id_part, oem_part_number, name_part FROM parts
|
||||
WHERE oem_part_number = '04465-06090';
|
||||
```
|
||||
|
||||
### 4.3 Crear el fitment (`vehicle_parts`)
|
||||
|
||||
```sql
|
||||
INSERT INTO vehicle_parts (model_year_engine_id, part_id, quantity_required, id_position_part, fitment_notes)
|
||||
VALUES (
|
||||
12345, -- id_mye del vehículo (del paso 4.1)
|
||||
67890, -- id_part de la pieza (del paso 4.2)
|
||||
1, -- Cantidad requerida (1 juego)
|
||||
1, -- Posición: 1 = front, 2 = rear (ver position_part)
|
||||
'Fits all trim levels' -- Notas de compatibilidad (opcional)
|
||||
);
|
||||
```
|
||||
|
||||
### 4.4 Fitment masivo (misma pieza en varios vehículos)
|
||||
|
||||
```sql
|
||||
-- Ejemplo: Balata 04465-06090 compatible con todos los Camry 2018-2023
|
||||
INSERT INTO vehicle_parts (model_year_engine_id, part_id, quantity_required, id_position_part)
|
||||
SELECT mye.id_mye,
|
||||
(SELECT id_part FROM parts WHERE oem_part_number = '04465-06090'),
|
||||
1, -- cantidad
|
||||
1 -- posición: front
|
||||
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 = 'TOYOTA'
|
||||
AND m.name_model = 'Camry'
|
||||
AND y.year_car BETWEEN 2018 AND 2023
|
||||
ON CONFLICT DO NOTHING;
|
||||
```
|
||||
|
||||
### Valores de `position_part`
|
||||
|
||||
| id_position_part | Nombre |
|
||||
|-----------------|--------|
|
||||
| 1 | front |
|
||||
| 2 | rear |
|
||||
|
||||
> Para agregar más posiciones (left, right, upper, lower):
|
||||
> ```sql
|
||||
> INSERT INTO position_part (name_position_part) VALUES ('left'), ('right'), ('upper'), ('lower');
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
## 5. Alta de Piezas Aftermarket
|
||||
|
||||
Vincula una pieza aftermarket con su equivalente OEM y el fabricante.
|
||||
|
||||
### 5.1 Crear pieza aftermarket (`aftermarket_parts`)
|
||||
|
||||
```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 (
|
||||
67890, -- id_part de la pieza OEM equivalente (de tabla parts)
|
||||
3, -- id_manufacture del fabricante (ver manufacturers)
|
||||
'CXD1293', -- Número de parte aftermarket
|
||||
'Ceramic Brake Pad Set', -- Nombre EN
|
||||
'Juego Balatas Cerámicas', -- Nombre ES
|
||||
3, -- Calidad: 1=economy, 2=oem, 3=premium, 4=standard
|
||||
45.99, -- Precio USD
|
||||
24 -- Garantía en meses
|
||||
);
|
||||
```
|
||||
|
||||
### 5.2 Carga masiva aftermarket
|
||||
|
||||
```sql
|
||||
INSERT INTO aftermarket_parts (oem_part_id, manufacturer_id, part_number, name_aftermarket_parts, id_quality_tier, price_usd, warranty_months) VALUES
|
||||
(67890, 3, 'CXD1293', 'Premium Ceramic Brake Pad', 3, 45.99, 24),
|
||||
(67890, 5, 'MKD1293', 'Economy Semi-Metallic Brake Pad', 1, 22.50, 12),
|
||||
(67890, 8, 'PBR1293', 'OEM Replacement Brake Pad', 2, 38.00, 18)
|
||||
ON CONFLICT DO NOTHING;
|
||||
```
|
||||
|
||||
### Referencia de `quality_tier`
|
||||
|
||||
| id_quality_tier | Nombre | Descripción |
|
||||
|----------------|--------|-------------|
|
||||
| 1 | economy | Económica, calidad básica |
|
||||
| 2 | oem | Calidad equivalente al original |
|
||||
| 3 | premium | Calidad superior al original |
|
||||
| 4 | standard | Calidad estándar del mercado |
|
||||
|
||||
### Consultar fabricantes existentes
|
||||
|
||||
```sql
|
||||
SELECT m.id_manufacture, m.name_manufacture, mt.name_type_manu AS tipo,
|
||||
qt.name_quality AS calidad, c.name_country AS pais
|
||||
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
|
||||
LEFT JOIN countries c ON m.id_country = c.id_country
|
||||
ORDER BY m.name_manufacture;
|
||||
```
|
||||
|
||||
### Agregar un nuevo fabricante
|
||||
|
||||
```sql
|
||||
INSERT INTO manufacturers (name_manufacture, id_type_manu, id_quality_tier, id_country, website)
|
||||
VALUES (
|
||||
'BREMBO',
|
||||
1, -- 1=aftermarket, 2=oem
|
||||
3, -- 1=economy, 2=oem, 3=premium, 4=standard
|
||||
NULL, -- id_country (buscar en tabla countries o agregar)
|
||||
'https://www.brembo.com'
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Alta de Referencias Cruzadas / Intercambios
|
||||
|
||||
Las cross-references vinculan una pieza OEM con números de parte alternativos.
|
||||
|
||||
### 6.1 Crear referencia cruzada (`part_cross_references`)
|
||||
|
||||
```sql
|
||||
INSERT INTO part_cross_references (part_id, cross_reference_number, id_ref_type, source_ref, notes)
|
||||
VALUES (
|
||||
67890, -- id_part de la pieza OEM
|
||||
'D1293', -- Número de referencia cruzada
|
||||
2, -- Tipo: 2 = interchange (ver tabla abajo)
|
||||
'Wagner Catalog', -- Fuente de la referencia (opcional)
|
||||
'Direct replacement' -- Notas (opcional)
|
||||
);
|
||||
```
|
||||
|
||||
### 6.2 Carga masiva de cross-references
|
||||
|
||||
```sql
|
||||
INSERT INTO part_cross_references (part_id, cross_reference_number, id_ref_type, source_ref) VALUES
|
||||
(67890, 'D1293', 2, 'Wagner'), -- interchange
|
||||
(67890, '04465-06100', 3, 'Toyota'), -- oem_alternate (número OEM alterno)
|
||||
(67890, 'BC1293', 1, 'Akebono'), -- competitor
|
||||
(67890, '04465-06080', 4, 'Toyota') -- supersession (reemplaza a esta)
|
||||
ON CONFLICT DO NOTHING;
|
||||
```
|
||||
|
||||
### Valores de `reference_type`
|
||||
|
||||
| id_ref_type | Nombre | Uso |
|
||||
|------------|--------|-----|
|
||||
| 1 | competitor | Número equivalente de competidor |
|
||||
| 2 | interchange | Intercambio directo compatible |
|
||||
| 3 | oem_alternate | Número OEM alterno del mismo fabricante |
|
||||
| 4 | supersession | El número OEM que esta pieza reemplaza |
|
||||
|
||||
---
|
||||
|
||||
## 7. Alta de Materiales
|
||||
|
||||
Si necesitas especificar el material de una pieza:
|
||||
|
||||
```sql
|
||||
-- Agregar materiales
|
||||
INSERT INTO materials (name_material) VALUES
|
||||
('Steel'),
|
||||
('Aluminum'),
|
||||
('Ceramic'),
|
||||
('Rubber'),
|
||||
('Cast Iron'),
|
||||
('Stainless Steel'),
|
||||
('Copper'),
|
||||
('Plastic')
|
||||
ON CONFLICT (name_material) DO NOTHING;
|
||||
|
||||
-- Luego, al crear una pieza, usar el id_material correspondiente:
|
||||
-- SELECT id_material FROM materials WHERE name_material = 'Ceramic';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Queries Útiles para Metabase (Dashboards)
|
||||
|
||||
### Vista completa de una pieza con todos sus datos
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
p.oem_part_number AS "Número OEM",
|
||||
p.name_part AS "Nombre EN",
|
||||
p.name_es AS "Nombre ES",
|
||||
pg.name_part_group AS "Grupo",
|
||||
pc.name_part_category AS "Categoría",
|
||||
p.weight_kg AS "Peso (kg)",
|
||||
mat.name_material AS "Material",
|
||||
COUNT(DISTINCT vp.model_year_engine_id) AS "Vehículos compatibles",
|
||||
COUNT(DISTINCT ap.id_aftermarket_parts) AS "Opciones aftermarket",
|
||||
COUNT(DISTINCT pcr.id_part_cross_ref) AS "Cross-references"
|
||||
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
|
||||
LEFT JOIN vehicle_parts vp ON vp.part_id = p.id_part
|
||||
LEFT JOIN aftermarket_parts ap ON ap.oem_part_id = p.id_part
|
||||
LEFT JOIN part_cross_references pcr ON pcr.part_id = p.id_part
|
||||
GROUP BY p.id_part, p.oem_part_number, p.name_part, p.name_es,
|
||||
pg.name_part_group, pc.name_part_category, p.weight_kg, mat.name_material
|
||||
ORDER BY pc.name_part_category, pg.name_part_group, p.name_part;
|
||||
```
|
||||
|
||||
### Catálogo de piezas por vehículo
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
b.name_brand AS "Marca",
|
||||
m.name_model AS "Modelo",
|
||||
y.year_car AS "Año",
|
||||
e.name_engine AS "Motor",
|
||||
pc.name_part_category AS "Categoría",
|
||||
pg.name_part_group AS "Grupo",
|
||||
p.oem_part_number AS "# OEM",
|
||||
p.name_part AS "Pieza",
|
||||
vp.quantity_required AS "Cantidad",
|
||||
pp.name_position_part AS "Posición"
|
||||
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
|
||||
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 position_part pp ON vp.id_position_part = pp.id_position_part
|
||||
WHERE b.name_brand ILIKE '{{marca}}'
|
||||
AND m.name_model ILIKE '{{modelo}}'
|
||||
ORDER BY pc.display_order, pg.display_order, p.name_part;
|
||||
```
|
||||
|
||||
> En Metabase, `{{marca}}` y `{{modelo}}` se convierten en filtros interactivos.
|
||||
|
||||
### Piezas aftermarket con precios
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
p.oem_part_number AS "OEM #",
|
||||
p.name_part AS "Pieza OEM",
|
||||
mfr.name_manufacture AS "Fabricante",
|
||||
ap.part_number AS "# Aftermarket",
|
||||
ap.name_aftermarket_parts AS "Nombre",
|
||||
qt.name_quality AS "Calidad",
|
||||
ap.price_usd AS "Precio USD",
|
||||
ap.warranty_months AS "Garantía (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, qt.name_quality DESC, ap.price_usd;
|
||||
```
|
||||
|
||||
### Cross-references de una pieza
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
p.oem_part_number AS "OEM #",
|
||||
p.name_part AS "Pieza",
|
||||
pcr.cross_reference_number AS "# Referencia",
|
||||
rt.name_ref_type AS "Tipo",
|
||||
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
|
||||
WHERE p.oem_part_number = '{{numero_oem}}'
|
||||
ORDER BY rt.name_ref_type, pcr.cross_reference_number;
|
||||
```
|
||||
|
||||
### Estadísticas generales
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM parts) AS "Total piezas",
|
||||
(SELECT COUNT(*) FROM vehicle_parts) AS "Total fitments",
|
||||
(SELECT COUNT(*) FROM aftermarket_parts) AS "Total aftermarket",
|
||||
(SELECT COUNT(*) FROM part_cross_references) AS "Total cross-refs",
|
||||
(SELECT COUNT(*) FROM manufacturers) AS "Total fabricantes",
|
||||
(SELECT COUNT(DISTINCT model_year_engine_id) FROM vehicle_parts) AS "Vehículos con piezas";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Flujo Completo: Ejemplo Paso a Paso
|
||||
|
||||
### Dar de alta "Balata delantera Toyota Camry 2020"
|
||||
|
||||
**Paso 1:** Agregar la pieza OEM
|
||||
```sql
|
||||
INSERT INTO parts (oem_part_number, name_part, name_es, group_id)
|
||||
VALUES ('04465-06090', 'Front Brake Pad Set', 'Juego Balatas Delanteras', 16)
|
||||
RETURNING id_part;
|
||||
-- Resultado: id_part = 1 (anotar este ID)
|
||||
```
|
||||
|
||||
**Paso 2:** Buscar los vehículos compatibles
|
||||
```sql
|
||||
SELECT mye.id_mye, 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 = 'TOYOTA' AND m.name_model = 'Camry'
|
||||
AND y.year_car BETWEEN 2018 AND 2023;
|
||||
-- Resultado: lista de id_mye para cada configuración
|
||||
```
|
||||
|
||||
**Paso 3:** Crear los fitments
|
||||
```sql
|
||||
INSERT INTO vehicle_parts (model_year_engine_id, part_id, quantity_required, id_position_part)
|
||||
SELECT mye.id_mye, 1, 1, 1 -- id_part=1, qty=1, position=front
|
||||
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 = 'TOYOTA' AND m.name_model = 'Camry'
|
||||
AND y.year_car BETWEEN 2018 AND 2023
|
||||
ON CONFLICT DO NOTHING;
|
||||
```
|
||||
|
||||
**Paso 4:** Agregar opciones aftermarket
|
||||
```sql
|
||||
INSERT INTO aftermarket_parts (oem_part_id, manufacturer_id, part_number, name_aftermarket_parts, id_quality_tier, price_usd, warranty_months) VALUES
|
||||
(1, 3, 'CXD1293', 'Premium Ceramic Pad', 3, 45.99, 24),
|
||||
(1, 5, 'MKD1293', 'Economy Brake Pad', 1, 22.50, 12);
|
||||
```
|
||||
|
||||
**Paso 5:** Agregar cross-references
|
||||
```sql
|
||||
INSERT INTO part_cross_references (part_id, cross_reference_number, id_ref_type, source_ref) VALUES
|
||||
(1, 'D1293', 2, 'Wagner'),
|
||||
(1, 'BC1293', 1, 'Akebono'),
|
||||
(1, '04465-06100', 3, 'Toyota OEM Alternate');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Notas Importantes
|
||||
|
||||
### Restricciones únicas (evitan duplicados)
|
||||
- `parts`: No tiene constraint único en `oem_part_number` (puede haber mismo OEM en diferentes grupos)
|
||||
- `vehicle_parts`: Único por `(model_year_engine_id, part_id, id_position_part)`
|
||||
- `vehicle_diagrams`: Único por `(diagram_id, model_year_engine_id)`
|
||||
- `model_year_engine`: Único por `(model_id, year_id, engine_id, trim_level)`
|
||||
|
||||
### Búsqueda full-text
|
||||
La tabla `parts` tiene un trigger que auto-genera `search_vector` al insertar/actualizar. Esto permite búsquedas rápidas en español:
|
||||
```sql
|
||||
SELECT * FROM parts
|
||||
WHERE search_vector @@ plainto_tsquery('spanish', 'balata delantera');
|
||||
```
|
||||
|
||||
### Para agregar nuevas categorías o grupos
|
||||
```sql
|
||||
-- Nueva categoría
|
||||
INSERT INTO part_categories (name_part_category, name_es, display_order)
|
||||
VALUES ('Interior', 'Interior', 13);
|
||||
|
||||
-- Nuevo grupo dentro de una categoría
|
||||
INSERT INTO part_groups (category_id, name_part_group, name_es, display_order)
|
||||
VALUES (1, 'Headlights', 'Faros Delanteros', 10);
|
||||
-- (category_id 1 = Body & Lamp Assembly)
|
||||
```
|
||||
|
||||
### Para agregar un país (para fabricantes)
|
||||
```sql
|
||||
INSERT INTO countries (name_country) VALUES ('Italy')
|
||||
ON CONFLICT (name_country) DO NOTHING;
|
||||
```
|
||||
Reference in New Issue
Block a user