docs: add README, API reference, and architecture documentation
- README.md: project overview, features, quick start, API overview - docs/API.md: full endpoint reference with examples - docs/ARCHITECTURE.md: system diagram, DB schema, data pipeline, auth flow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
432
README.md
432
README.md
@@ -1,333 +1,205 @@
|
||||
# Nexus Autoparts
|
||||
|
||||
Sistema completo de gestión de base de datos de vehículos y nexus-autoparts con dashboard web, herramientas de web scraping y múltiples interfaces de consulta.
|
||||
**Sistema de catalogo de autopartes con navegacion jerarquica, similar a 7zap.com/RockAuto.**
|
||||
|
||||
## Descripción
|
||||
Plataforma SaaS que conecta talleres con bodegas/distribuidores. Permite buscar partes OEM y aftermarket por vehiculo (marca, modelo, ano, motor), gestionar inventario de bodegas, y consultar disponibilidad y precios en tiempo real.
|
||||
|
||||
**Nexus Autoparts** es una solución integral para la gestión de información de vehículos que incluye:
|
||||
## Tech Stack
|
||||
|
||||
- Base de datos SQLite normalizada con información de marcas, modelos, motores y años
|
||||
- Dashboard web moderno y responsivo para consultar y explorar datos
|
||||
- Herramientas de web scraping para recopilar datos de RockAuto.com
|
||||
- Interfaces de línea de comandos (CLI) y programática
|
||||
- Scripts de utilidad para gestión y mantenimiento de datos
|
||||
| Componente | Tecnologia |
|
||||
|------------|-----------|
|
||||
| Backend | Python 3, Flask |
|
||||
| Base de datos | PostgreSQL |
|
||||
| ORM / SQL | SQLAlchemy (`text()` raw SQL) |
|
||||
| Autenticacion | JWT (PyJWT) + bcrypt |
|
||||
| Data import | TecDoc via Apify, NHTSA VIN API |
|
||||
| Frontend | HTML/CSS/JS vanilla (sin framework) |
|
||||
| Dependencias extra | openpyxl (Excel), csv (CSV import) |
|
||||
|
||||
## Estadísticas de la Base de Datos
|
||||
## Estadisticas de la Base de Datos
|
||||
|
||||
| Elemento | Cantidad |
|
||||
|----------|----------|
|
||||
| Marcas | 12 |
|
||||
| Modelos | 10,923 |
|
||||
| Motores | 10,919 |
|
||||
| Combinaciones modelo-año-motor | 12,075 |
|
||||
- **1.4M+** partes OEM
|
||||
- **300K+** partes aftermarket
|
||||
- **13M+** cross-references (numeros alternos, supersesiones, intercambios)
|
||||
- **12B+** vehicle-part links (fitment)
|
||||
- **100+** marcas, miles de modelos, anos 1956-2026
|
||||
|
||||
## Tecnologías Utilizadas
|
||||
## Features
|
||||
|
||||
### Backend
|
||||
- **Python 3** - Lenguaje principal
|
||||
- **SQLite 3** - Base de datos
|
||||
- **Flask 2.3.3** - Framework web
|
||||
- **BeautifulSoup4** - Web scraping
|
||||
- **requests** - HTTP client
|
||||
- **lxml** - Parser XML/HTML
|
||||
- **Catalogo de autopartes** con navegacion jerarquica: Marca > Modelo > Ano > Motor > Categoria > Grupo > Parte
|
||||
- **TecDoc integration** (via Apify) para importar datos OEM y aftermarket de Europa/Mexico
|
||||
- **SaaS multi-tenant** con roles: `ADMIN`, `OWNER`, `TALLER`, `BODEGA`
|
||||
- **JWT authentication** con access tokens (15 min) y refresh tokens (30 dias)
|
||||
- **Gestion de inventario** para bodegas con mapeo flexible de columnas CSV/Excel
|
||||
- **Disponibilidad de partes** en multiples bodegas con precios comparativos
|
||||
- **Alternativas aftermarket** con cross-references por cada parte OEM
|
||||
- **Panel de administracion** con gestion de usuarios, import/export CSV, CRUD de categorias/grupos/partes/fabricantes/fitment
|
||||
- **Busqueda full-text** en el catalogo de partes (PostgreSQL `tsvector`)
|
||||
- **Busqueda combinada** vehiculo + parte (e.g., "Toyota Corolla 2020 frenos")
|
||||
- **VIN decoder** via NHTSA API con cache en base de datos
|
||||
- **Diagramas explosionados** con hotspots clickeables
|
||||
- **Vehicle-to-part linking** (12B+ vehicle_parts links)
|
||||
|
||||
### Frontend
|
||||
- **HTML5** - Estructura
|
||||
- **Bootstrap 5.3.0** - Framework CSS
|
||||
- **JavaScript (ES6+)** - Lógica cliente
|
||||
- **Font Awesome 6.0.0** - Iconos
|
||||
## Quick Start
|
||||
|
||||
## Estructura del Proyecto
|
||||
### Requisitos previos
|
||||
|
||||
```
|
||||
Autopartes/
|
||||
├── vehicle_database/ # Sistema principal de base de datos
|
||||
│ ├── sql/
|
||||
│ │ └── schema.sql # Esquema de la base de datos
|
||||
│ ├── scripts/
|
||||
│ │ ├── database_manager.py # Gestión de la BD
|
||||
│ │ ├── query_interface.py # Interfaz CLI
|
||||
│ │ └── csv_importer.py # Importador CSV
|
||||
│ ├── data/
|
||||
│ │ ├── brands.csv # Datos de marcas
|
||||
│ │ ├── engines.csv # Datos de motores
|
||||
│ │ └── models.csv # Datos de modelos
|
||||
│ ├── vehicle_database.db # Base de datos SQLite
|
||||
│ └── setup.sh # Script de inicialización
|
||||
│
|
||||
├── dashboard/ # Interfaz web
|
||||
│ ├── server.py # Backend Flask
|
||||
│ ├── index.html # Frontend HTML
|
||||
│ ├── dashboard.js # Lógica JavaScript
|
||||
│ └── start_dashboard.sh # Script de inicio
|
||||
│
|
||||
├── console/ # Consola Pick/VT220
|
||||
│ ├── main.py # Punto de entrada
|
||||
│ ├── db.py # Capa de datos abstracta
|
||||
│ ├── core/ # Framework (app, screens, nav, keys)
|
||||
│ ├── screens/ # 14 pantallas (menú, CRUD, búsqueda)
|
||||
│ ├── renderers/ # Renderer VT220 (curses)
|
||||
│ ├── utils/ # Formato y API VIN
|
||||
│ └── tests/ # 116 tests
|
||||
│
|
||||
├── vehicle_scraper/ # Herramientas de web scraping
|
||||
│ ├── rockauto_scraper.py # Scraper RockAuto
|
||||
│ ├── rockauto_scraper_v2.py # Scraper mejorado
|
||||
│ ├── scrape_toyota.py # Scraper Toyota
|
||||
│ ├── scrape_nissan_ford_chevrolet.py
|
||||
│ └── manual_input.py # Ingreso manual
|
||||
│
|
||||
├── add_*.py # Scripts para agregar datos
|
||||
├── remove_*.py # Scripts de limpieza
|
||||
└── QUICK_START.sh # Guía rápida de inicio
|
||||
```
|
||||
- Python 3.8+
|
||||
- PostgreSQL con la base `nexus_autoparts`
|
||||
|
||||
## Consola Pick/VT220
|
||||
|
||||
Interfaz de terminal inspirada en los sistemas Pick/D3, 100% operada con teclado. Estética verde sobre negro con caracteres de caja, sin dependencias externas.
|
||||
### Instalacion
|
||||
|
||||
```bash
|
||||
python -m console
|
||||
cd /home/Autopartes
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Funcionalidades: navegación por vehículo (marca→modelo→año→motor), búsqueda por número de parte, búsqueda full-text, decodificador VIN (NHTSA), catálogo por categorías, comparador OEM vs aftermarket, y administración CRUD completa.
|
||||
|
||||
116 tests automatizados. Ver [`console/README.md`](console/README.md) para documentación completa.
|
||||
|
||||
## Instalación
|
||||
|
||||
### Requisitos Previos
|
||||
|
||||
- Python 3.8 o superior
|
||||
- pip (gestor de paquetes de Python)
|
||||
|
||||
### Pasos de Instalación
|
||||
|
||||
1. **Clonar el repositorio**
|
||||
```bash
|
||||
git clone https://git.consultoria-as.com/[usuario]/Nexus-Autoparts.git
|
||||
cd Nexus-Autoparts
|
||||
```
|
||||
|
||||
2. **Instalar dependencias**
|
||||
```bash
|
||||
pip install flask requests beautifulsoup4 lxml
|
||||
```
|
||||
|
||||
3. **Inicializar la base de datos (opcional - ya incluye datos)**
|
||||
```bash
|
||||
cd vehicle_database
|
||||
./setup.sh
|
||||
```
|
||||
|
||||
## Uso
|
||||
|
||||
### Iniciar el Dashboard Web
|
||||
### Ejecutar el servidor
|
||||
|
||||
```bash
|
||||
cd dashboard
|
||||
cd /home/Autopartes/dashboard
|
||||
python3 server.py
|
||||
```
|
||||
|
||||
El dashboard estará disponible en: `http://localhost:5000`
|
||||
El servidor arranca en `http://localhost:5000`.
|
||||
|
||||
### Iniciar la Consola Pick/VT220
|
||||
### Importar datos de TecDoc
|
||||
|
||||
```bash
|
||||
python -m console
|
||||
# Fase 1: descargar datos de TecDoc a JSON
|
||||
python3 scripts/import_tecdoc.py download
|
||||
|
||||
# Fase 2: importar JSON a PostgreSQL
|
||||
python3 scripts/import_tecdoc.py import
|
||||
|
||||
# Ver progreso
|
||||
python3 scripts/import_tecdoc.py status
|
||||
```
|
||||
|
||||
### Usar la Interfaz CLI Legacy
|
||||
### Importar partes y linkar vehiculos
|
||||
|
||||
```bash
|
||||
cd vehicle_database/scripts
|
||||
python3 query_interface.py
|
||||
# Importar partes TecDoc (OEM + aftermarket)
|
||||
python3 scripts/import_tecdoc_parts.py
|
||||
|
||||
# Importar datos en vivo desde TecDoc API
|
||||
python3 scripts/import_live.py
|
||||
|
||||
# Crear links vehiculo-parte (fitment masivo)
|
||||
python3 scripts/link_vehicle_parts.py
|
||||
|
||||
# Migrar datos aftermarket
|
||||
python3 scripts/migrate_aftermarket.py
|
||||
|
||||
# Aplicar schema SaaS (roles, users, inventory tables)
|
||||
python3 scripts/migrate_saas_schema.py
|
||||
```
|
||||
|
||||
### Ejecutar Web Scraping
|
||||
## Paginas del Dashboard
|
||||
|
||||
```bash
|
||||
cd vehicle_scraper
|
||||
python3 rockauto_scraper_v2.py
|
||||
```
|
||||
| Ruta | Archivo | Descripcion |
|
||||
|------|---------|-------------|
|
||||
| `/login.html` | `login.html` | Login con JWT |
|
||||
| `/demo.html` | `demo.html` | Catalogo publico / demo |
|
||||
| `/admin` | `admin.html` | Panel de administracion (ADMIN/OWNER) |
|
||||
| `/bodega.html` | `bodega.html` | Gestion de inventario para bodegas |
|
||||
| `/tienda.html` | `tienda.html` | Vista de tienda/catalogo para talleres |
|
||||
| `/pos.html` | `pos.html` | Punto de venta |
|
||||
| `/captura.html` | `captura.html` | Captura de partes |
|
||||
| `/cuentas.html` | `cuentas.html` | Gestion de cuentas |
|
||||
|
||||
### Agregar Datos Manualmente
|
||||
## API Overview
|
||||
|
||||
```bash
|
||||
cd vehicle_scraper
|
||||
python3 manual_input.py
|
||||
```
|
||||
Documentacion completa en [`docs/API.md`](docs/API.md).
|
||||
|
||||
## API REST
|
||||
### Auth (`/api/auth/`)
|
||||
- `POST /api/auth/register` - Registrar usuario (TALLER/BODEGA)
|
||||
- `POST /api/auth/login` - Login, retorna access + refresh tokens
|
||||
- `POST /api/auth/refresh` - Renovar access token
|
||||
- `GET /api/auth/me` - Info del usuario autenticado
|
||||
|
||||
El dashboard expone los siguientes endpoints:
|
||||
### Catalogo (`/api/`)
|
||||
- `GET /api/brands` - Listar marcas
|
||||
- `GET /api/models?brand=X` - Modelos por marca
|
||||
- `GET /api/years?brand=X&model=Y` - Anos disponibles
|
||||
- `GET /api/engines?brand=X&model=Y&year=Z` - Motores disponibles
|
||||
- `GET /api/categories` - Categorias de partes (arbol jerarquico)
|
||||
- `GET /api/parts?group_id=X` - Partes por grupo
|
||||
- `GET /api/parts/{id}/alternatives` - Alternativas aftermarket
|
||||
- `GET /api/parts/{id}/cross-references` - Cross-references
|
||||
- `GET /api/search?q=...` - Busqueda combinada (vehiculos + partes + aftermarket)
|
||||
|
||||
| Endpoint | Método | Descripción |
|
||||
|----------|--------|-------------|
|
||||
| `/api/brands` | GET | Obtiene todas las marcas |
|
||||
| `/api/models?brand=X` | GET | Obtiene modelos por marca |
|
||||
| `/api/years` | GET | Obtiene años disponibles |
|
||||
| `/api/engines` | GET | Obtiene motores disponibles |
|
||||
| `/api/vehicles` | GET | Búsqueda con filtros |
|
||||
### Inventario (`/api/inventory/`)
|
||||
- `GET/PUT /api/inventory/mapping` - Mapeo de columnas CSV
|
||||
- `POST /api/inventory/upload` - Subir CSV/Excel de inventario
|
||||
- `GET /api/inventory/items` - Listar inventario propio
|
||||
- `DELETE /api/inventory/items` - Limpiar inventario
|
||||
|
||||
### Ejemplo de Uso
|
||||
### Disponibilidad y Aftermarket
|
||||
- `GET /api/parts/{id}/availability` - Bodegas con stock (auth: TALLER/ADMIN/OWNER)
|
||||
- `GET /api/parts/{id}/aftermarket` - Alternativas aftermarket + cross-refs (publico)
|
||||
|
||||
```bash
|
||||
# Obtener todas las marcas
|
||||
curl http://localhost:5000/api/brands
|
||||
### Admin (`/api/admin/`)
|
||||
- `GET /api/admin/users` - Listar usuarios (auth: ADMIN/OWNER)
|
||||
- `PUT /api/admin/users/{id}/activate` - Activar/desactivar usuario
|
||||
- `GET /api/admin/stats` - Estadisticas del catalogo
|
||||
- CRUD completo: categories, groups, parts, manufacturers, aftermarket, crossref, fitment
|
||||
- Import/Export CSV: `POST /api/admin/import/{type}`, `GET /api/admin/export/{type}`
|
||||
|
||||
# Buscar vehículos por marca y año
|
||||
curl "http://localhost:5000/api/vehicles?brand=Toyota&year=2020"
|
||||
```
|
||||
### VIN Decoder
|
||||
- `GET /api/vin/decode/{vin}` - Decodificar VIN via NHTSA API
|
||||
- `GET /api/vin/{vin}/parts` - Partes para un VIN decodificado
|
||||
- `GET /api/vin/{vin}/match?mye_id=X` - Vincular VIN manualmente a vehiculo
|
||||
|
||||
## Esquema de Base de Datos
|
||||
## Scripts
|
||||
|
||||
### Tablas
|
||||
| Script | Funcion |
|
||||
|--------|---------|
|
||||
| `import_tecdoc.py` | Descarga datos de TecDoc API (vehiculos, modelos, marcas) a JSON |
|
||||
| `import_tecdoc_parts.py` | Importa partes OEM y aftermarket desde TecDoc |
|
||||
| `import_live.py` | Importacion en vivo desde TecDoc API |
|
||||
| `link_vehicle_parts.py` | Genera links vehiculo-parte (fitment masivo) |
|
||||
| `migrate_aftermarket.py` | Migra datos aftermarket a la estructura normalizada |
|
||||
| `migrate_saas_schema.py` | Crea tablas SaaS: sessions, warehouse_inventory, roles, etc. |
|
||||
| `import_phase1.py` | Importacion inicial fase 1 |
|
||||
| `run_all_brands.sh` | Script auxiliar para importar todas las marcas |
|
||||
|
||||
#### brands
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | INTEGER | Clave primaria |
|
||||
| name | TEXT | Nombre de la marca |
|
||||
| country | TEXT | País de origen |
|
||||
| founded_year | INTEGER | Año de fundación |
|
||||
## Configuracion
|
||||
|
||||
#### models
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | INTEGER | Clave primaria |
|
||||
| brand_id | INTEGER | FK a brands |
|
||||
| name | TEXT | Nombre del modelo |
|
||||
| body_type | TEXT | Tipo de carrocería |
|
||||
| generation | TEXT | Generación |
|
||||
| production_start_year | INTEGER | Año inicio producción |
|
||||
| production_end_year | INTEGER | Año fin producción |
|
||||
Archivo principal: [`config.py`](config.py)
|
||||
|
||||
#### engines
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | INTEGER | Clave primaria |
|
||||
| name | TEXT | Nombre del motor |
|
||||
| displacement_cc | INTEGER | Cilindrada en cc |
|
||||
| cylinders | INTEGER | Número de cilindros |
|
||||
| fuel_type | TEXT | Tipo de combustible |
|
||||
| power_hp | INTEGER | Potencia en HP |
|
||||
| torque_nm | INTEGER | Torque en Nm |
|
||||
| engine_code | TEXT | Código del motor |
|
||||
| Variable | Default | Descripcion |
|
||||
|----------|---------|-------------|
|
||||
| `DATABASE_URL` | `postgresql://nexus:...@localhost/nexus_autoparts` | PostgreSQL connection string |
|
||||
| `JWT_SECRET` | `nexus-saas-secret-change-in-prod-2026` | Secreto para firmar tokens JWT |
|
||||
| `JWT_ACCESS_EXPIRES` | `900` (15 min) | Duracion del access token en segundos |
|
||||
| `JWT_REFRESH_EXPIRES` | `2592000` (30 dias) | Duracion del refresh token en segundos |
|
||||
|
||||
#### years
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | INTEGER | Clave primaria |
|
||||
| year | INTEGER | Año |
|
||||
## Arquitectura
|
||||
|
||||
#### model_year_engine
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | INTEGER | Clave primaria |
|
||||
| model_id | INTEGER | FK a models |
|
||||
| year_id | INTEGER | FK a years |
|
||||
| engine_id | INTEGER | FK a engines |
|
||||
| trim_level | TEXT | Nivel de equipamiento |
|
||||
| drivetrain | TEXT | Tracción |
|
||||
| transmission | TEXT | Transmisión |
|
||||
|
||||
### Diagrama de Relaciones
|
||||
Documentacion detallada en [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
|
||||
|
||||
```
|
||||
brands ──┐
|
||||
│
|
||||
├──< models ──┐
|
||||
│ │
|
||||
years ───┼─────────────┼──< model_year_engine
|
||||
│ │
|
||||
engines ─┴─────────────┘
|
||||
+------------------+
|
||||
| TecDoc (Apify) |
|
||||
+--------+---------+
|
||||
|
|
||||
download/import
|
||||
|
|
||||
v
|
||||
+----------+ +--------+---------+ +----------------+
|
||||
| Frontend |<--->| Flask Server |<--->| PostgreSQL |
|
||||
| (HTML/JS)| | (server.py) | | nexus_autoparts|
|
||||
+----------+ +--------+---------+ +----------------+
|
||||
|
|
||||
JWT auth (PyJWT)
|
||||
|
|
||||
+------------+------------+
|
||||
| | |
|
||||
TALLER BODEGA ADMIN
|
||||
(consulta) (inventario) (gestion)
|
||||
```
|
||||
|
||||
## Scripts Disponibles
|
||||
|
||||
### Scripts de Datos
|
||||
|
||||
| Script | Descripción |
|
||||
|--------|-------------|
|
||||
| `add_toyota_data.py` | Agrega datos de Toyota |
|
||||
| `add_honda_data.py` | Agrega datos de Honda |
|
||||
| `add_nissan_data.py` | Agrega datos de Nissan |
|
||||
| `add_ford_data.py` | Agrega datos de Ford |
|
||||
| `add_chevrolet_data.py` | Agrega datos de Chevrolet |
|
||||
| `add_audi_data.py` | Agrega datos de Audi |
|
||||
| `add_acura_data.py` | Agrega datos de Acura |
|
||||
| ... | Y más marcas |
|
||||
|
||||
### Scripts de Mantenimiento
|
||||
|
||||
| Script | Descripción |
|
||||
|--------|-------------|
|
||||
| `remove_brands_and_cleanup.py` | Limpia marcas innecesarias |
|
||||
| `check_and_remove_brands.py` | Verifica y elimina marcas |
|
||||
|
||||
## Funcionalidades del Dashboard
|
||||
|
||||
### Panel de Filtros
|
||||
- Selección de marca
|
||||
- Selección de modelo (dinámico según marca)
|
||||
- Filtro por año
|
||||
- Filtro por motor
|
||||
|
||||
### Panel de Resultados
|
||||
- Visualización en tarjetas
|
||||
- Información detallada del vehículo
|
||||
- Especificaciones del motor
|
||||
- Datos de transmisión y tracción
|
||||
|
||||
### Características
|
||||
- Diseño responsivo
|
||||
- Actualización en tiempo real
|
||||
- Animaciones y transiciones suaves
|
||||
- Soporte para múltiples idiomas
|
||||
|
||||
## Arquitectura del Sistema
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────┐
|
||||
│ RockAuto.com │────>│ Web Scraper │
|
||||
└─────────────────┘ └────────┬─────────┘
|
||||
│
|
||||
v
|
||||
┌─────────────────┐ ┌──────────────────┐
|
||||
│ Manual Input │────>│ SQLite Database │
|
||||
└─────────────────┘ └────────┬─────────┘
|
||||
│
|
||||
┌───────────────────────┼───────────────────────┐
|
||||
│ │ │
|
||||
v v v
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
||||
│ Flask API │ │ Pick Console │ │ CSV Importer │
|
||||
└────────┬────────┘ │ (VT220/Rich) │ └──────────────────┘
|
||||
│ └──────────────────┘
|
||||
v
|
||||
┌─────────────────┐
|
||||
│ Web Dashboard │
|
||||
│ (Browser) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## Contribuir
|
||||
|
||||
1. Fork el repositorio
|
||||
2. Crea una rama para tu feature (`git checkout -b feature/nueva-funcionalidad`)
|
||||
3. Commit tus cambios (`git commit -am 'Agrega nueva funcionalidad'`)
|
||||
4. Push a la rama (`git push origin feature/nueva-funcionalidad`)
|
||||
5. Crea un Pull Request
|
||||
|
||||
## Licencia
|
||||
|
||||
Este proyecto es de uso interno.
|
||||
|
||||
## Contacto
|
||||
|
||||
Para más información, contactar al equipo de desarrollo.
|
||||
|
||||
---
|
||||
|
||||
**Nexus Autoparts** - Sistema de Gestión de Base de Datos de Vehículos
|
||||
**Nexus Autoparts** - Tu conexion directa con las partes que necesitas
|
||||
|
||||
1579
docs/API.md
1579
docs/API.md
File diff suppressed because it is too large
Load Diff
449
docs/ARCHITECTURE.md
Normal file
449
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,449 @@
|
||||
# Arquitectura - Nexus Autoparts
|
||||
|
||||
## Vista General del Sistema
|
||||
|
||||
```
|
||||
+-------------------+ +-------------------+ +-------------------+
|
||||
| | | | | |
|
||||
| TecDoc (Apify) | | NHTSA VIN API | | CSV/Excel |
|
||||
| Actor API | | vpic.nhtsa.gov | | (Bodega upload) |
|
||||
| | | | | |
|
||||
+--------+----------+ +--------+----------+ +--------+----------+
|
||||
| | |
|
||||
| download/import | decode | upload
|
||||
| | |
|
||||
v v v
|
||||
+--------+---------------------------+---------------------------+----------+
|
||||
| |
|
||||
| Flask Server (server.py) |
|
||||
| Puerto 5000 |
|
||||
| |
|
||||
| +-------------+ +-------------+ +-------------+ +-----------------+ |
|
||||
| | Auth Module | | Catalog API | | Inventory | | Admin CRUD | |
|
||||
| | (auth.py) | | (publico) | | (BODEGA) | | (import/export) | |
|
||||
| | JWT + bcrypt | | | | CSV mapping | | | |
|
||||
| +------+------+ +------+------+ +------+------+ +--------+--------+ |
|
||||
| | | | | |
|
||||
+---------+----------------+----------------+-------------------+-----------+
|
||||
| | | |
|
||||
v v v v
|
||||
+-------------------------------------------------------------------------+
|
||||
| |
|
||||
| PostgreSQL (nexus_autoparts) |
|
||||
| SQLAlchemy text() raw SQL |
|
||||
| |
|
||||
| +----------+ +----------+ +----------+ +----------+ +---------------+ |
|
||||
| | brands | | models | | years | | engines | | fuel_type | |
|
||||
| +----+-----+ +----+-----+ +----+-----+ +----+-----+ | drivetrain | |
|
||||
| | | | | | transmission | |
|
||||
| +------+------+------------+------------+ +---------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------------+ |
|
||||
| | model_year_engine | (MYE - tabla central de vehiculos) |
|
||||
| | PK: id_mye | |
|
||||
| | UNIQUE(model,year, | |
|
||||
| | engine,trim_level) | |
|
||||
| +----------+------------+ |
|
||||
| | |
|
||||
| | 1:N |
|
||||
| v |
|
||||
| +---------------------+ +---------------------+ |
|
||||
| | vehicle_parts | | vehicle_diagrams | |
|
||||
| | (12B+ rows) | | | |
|
||||
| | mye_id + part_id | | mye_id + diagram_id | |
|
||||
| +----------+----------+ +----------+----------+ |
|
||||
| | | |
|
||||
| v v |
|
||||
| +---------------------+ +---------------------+ |
|
||||
| | parts (1.4M+ OEM) | | diagrams | |
|
||||
| | oem_part_number | | image_path | |
|
||||
| | group_id -> groups | | group_id -> groups | |
|
||||
| +---+------+----------+ +-----+---------------+ |
|
||||
| | | | |
|
||||
| | v v |
|
||||
| | +--------------------+ +---------------------+ |
|
||||
| | | part_groups | | diagram_hotspots | |
|
||||
| | | category_id | | part_id, coords | |
|
||||
| | +--------+-----------+ +---------------------+ |
|
||||
| | | |
|
||||
| | v |
|
||||
| | +--------------------+ |
|
||||
| | | part_categories | |
|
||||
| | | (arbol jerarquico) | |
|
||||
| | | parent_id -> self | |
|
||||
| | +--------------------+ |
|
||||
| | |
|
||||
| +----------+-----------+ |
|
||||
| | | |
|
||||
| v v |
|
||||
| +---------------------+ +------------------------+ |
|
||||
| | aftermarket_parts | | part_cross_references | |
|
||||
| | (300K+) | | (13M+) | |
|
||||
| | oem_part_id -> parts| | part_id -> parts | |
|
||||
| | manufacturer_id | | reference_type | |
|
||||
| +----------+----------+ +------------------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +---------------------+ |
|
||||
| | manufacturers | |
|
||||
| | type, quality_tier | |
|
||||
| +---------------------+ |
|
||||
| |
|
||||
| === SaaS Tables === |
|
||||
| |
|
||||
| +----------+ +----------+ +---------------------+ +-------------+ |
|
||||
| | users | | roles | | warehouse_inventory | | sessions | |
|
||||
| | id_user | | ADMIN | | user_id + part_id | | refresh | |
|
||||
| | id_rol | | OWNER | | price, stock | | token | |
|
||||
| | email | | TALLER | | location | | expires_at | |
|
||||
| | pass | | BODEGA | +---------------------+ +-------------+ |
|
||||
| +----------+ +----------+ |
|
||||
| +------------------------+ |
|
||||
| | inventory_uploads | |
|
||||
| | inventory_col_mappings | |
|
||||
| +------------------------+ |
|
||||
| |
|
||||
| === Lookup Tables === |
|
||||
| countries, materials, shapes, position_part, reference_type, |
|
||||
| manufacture_type, quality_tier |
|
||||
| |
|
||||
+-------------------------------------------------------------------------+
|
||||
|
||||
| | | |
|
||||
v v v v
|
||||
+-------------------+ +----------+ +-------------+ +----------------+
|
||||
| login.html | | demo.html| | admin.html | | bodega.html |
|
||||
| tienda.html | | (catalog)| | (CRUD + | | (inventory |
|
||||
| pos.html | | | | users) | | upload/manage) |
|
||||
| cuentas.html | | | | | | |
|
||||
| captura.html | | | | | | |
|
||||
+-------------------+ +----------+ +-------------+ +----------------+
|
||||
Frontend: HTML/CSS/JS vanilla (sin framework)
|
||||
Shared: nav.js, shared.css
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Schema Overview
|
||||
|
||||
### Tablas principales y sus relaciones
|
||||
|
||||
**Vehiculos (jerarquia):**
|
||||
```
|
||||
brands (id_brand, name_brand, country, region)
|
||||
|
|
||||
+--< models (id_model, brand_id, name_model, body_type)
|
||||
|
|
||||
+--< model_year_engine (id_mye, model_id, year_id, engine_id, trim_level)
|
||||
| | |
|
||||
| | +-- engines (id_engine, name_engine, displacement_cc, cylinders, power_hp)
|
||||
| +-------- years (id_year, year_car)
|
||||
|
|
||||
+--< vehicle_parts (mye_id, part_id, quantity, position)
|
||||
+--< vehicle_diagrams (mye_id, diagram_id)
|
||||
```
|
||||
|
||||
**Partes (jerarquia):**
|
||||
```
|
||||
part_categories (id, name, parent_id) <-- arbol recursivo
|
||||
|
|
||||
+--< part_groups (id, category_id, name)
|
||||
|
|
||||
+--< parts (id_part, oem_part_number, name, group_id)
|
||||
|
|
||||
+--< aftermarket_parts (oem_part_id -> parts, manufacturer_id, part_number)
|
||||
+--< part_cross_references (part_id -> parts, cross_reference_number, type)
|
||||
+--< vehicle_parts (part_id -> parts, mye_id)
|
||||
```
|
||||
|
||||
**SaaS / Multi-tenant:**
|
||||
```
|
||||
roles (id_rol: 1=ADMIN, 2=OWNER, 3=TALLER, 4=BODEGA)
|
||||
|
|
||||
+--< users (id_user, email, pass, id_rol, business_name, is_active)
|
||||
|
|
||||
+--< sessions (refresh_token, expires_at)
|
||||
+--< warehouse_inventory (user_id, part_id, price, stock, location)
|
||||
+--< inventory_uploads (user_id, filename, status, rows_imported)
|
||||
+--< inventory_column_mappings (user_id, mapping JSON)
|
||||
```
|
||||
|
||||
### Convenciones de nombres en PostgreSQL
|
||||
|
||||
| Tabla | PK | Naming pattern |
|
||||
|-------|-----|---------------|
|
||||
| brands | `id_brand` | `name_brand` |
|
||||
| models | `id_model` | `name_model` |
|
||||
| years | `id_year` | `year_car` |
|
||||
| engines | `id_engine` | `name_engine` |
|
||||
| model_year_engine | `id_mye` | Tabla pivote central |
|
||||
| parts | `id_part` | `name_part`, `oem_part_number` |
|
||||
| part_categories | `id_part_category` | `name_part_category` |
|
||||
| part_groups | `id_part_group` | `name_part_group` |
|
||||
| manufacturers | `id_manufacture` | `name_manufacture` |
|
||||
|
||||
---
|
||||
|
||||
## TecDoc Data Pipeline
|
||||
|
||||
Pipeline de 3 fases para importar datos de TecDoc (el catalogo europeo de autopartes).
|
||||
|
||||
```
|
||||
Fase 1: DOWNLOAD Fase 2: IMPORT Fase 3: LINK
|
||||
(import_tecdoc.py download) (import_tecdoc.py import) (link_vehicle_parts.py)
|
||||
|
||||
+------------------+ +------------------+ +------------------+
|
||||
| Apify TecDoc | | JSON files | | parts + |
|
||||
| Actor API | | data/tecdoc/ | | model_year_engine|
|
||||
| $69/month | | | | |
|
||||
| HTTP 201 = run | | manufacturers/ | | Genera links |
|
||||
| | --------> | models/ | ---------> | masivos en |
|
||||
| typeId=1 (cars) | JSON | vehicles/ | INSERT | vehicle_parts |
|
||||
| langId=4 (EN) | files | | partes + | (12B+ filas) |
|
||||
| countryId=153(MX)| | Resumable: | vehiculos | |
|
||||
+------------------+ | skips existing | +------------------+
|
||||
+------------------+
|
||||
```
|
||||
|
||||
### Scripts adicionales
|
||||
|
||||
- **`import_tecdoc_parts.py`**: Importa partes OEM y aftermarket desde TecDoc
|
||||
- **`import_live.py`**: Importa datos en tiempo real (sin bajar a JSON primero)
|
||||
- **`migrate_aftermarket.py`**: Normaliza datos aftermarket a la estructura con `quality_tier`, `manufacturers`
|
||||
|
||||
### Filtros de importacion
|
||||
|
||||
- Se descartan variantes regionales (e.g., "TOYOTA (GAC)")
|
||||
- `countryFilterId=153` limita a vehiculos vendidos en Mexico
|
||||
- El script es resumable: si un JSON ya existe en `data/tecdoc/`, se salta
|
||||
|
||||
---
|
||||
|
||||
## Auth Flow
|
||||
|
||||
Flujo de autenticacion basado en JWT con refresh tokens.
|
||||
|
||||
```
|
||||
Cliente Servidor PostgreSQL
|
||||
| | |
|
||||
| POST /api/auth/register | |
|
||||
| {name, email, pass, role} | |
|
||||
|------------------------------>| bcrypt.hash(pass) |
|
||||
| |----------------------------->|
|
||||
| | INSERT users (is_active=F) |
|
||||
| 201 "pending activation" | |
|
||||
|<------------------------------| |
|
||||
| | |
|
||||
| (Admin activa la cuenta) | |
|
||||
| | |
|
||||
| POST /api/auth/login | |
|
||||
| {email, password} | |
|
||||
|------------------------------>| SELECT users WHERE email |
|
||||
| |<-----------------------------|
|
||||
| | bcrypt.check(pass) |
|
||||
| | Verify is_active=true |
|
||||
| | |
|
||||
| | jwt.encode(user_id, role, |
|
||||
| | business_name, exp=15min) |
|
||||
| | |
|
||||
| | secrets.token_urlsafe(48) |
|
||||
| | INSERT sessions |
|
||||
| |----------------------------->|
|
||||
| | |
|
||||
| {access_token, refresh_token,| |
|
||||
| user: {id, name, role}} | |
|
||||
|<------------------------------| |
|
||||
| | |
|
||||
| GET /api/... (protected) | |
|
||||
| Authorization: Bearer <AT> | |
|
||||
|------------------------------>| jwt.decode(AT) |
|
||||
| | Check role in allowed_roles |
|
||||
| | Set g.user = {user_id, role}|
|
||||
| 200 {data} | |
|
||||
|<------------------------------| |
|
||||
| | |
|
||||
| (Access token expires) | |
|
||||
| | |
|
||||
| POST /api/auth/refresh | |
|
||||
| {refresh_token} | |
|
||||
|------------------------------>| SELECT sessions |
|
||||
| |<-----------------------------|
|
||||
| | Check expires_at > now() |
|
||||
| | jwt.encode(new access_token)|
|
||||
| {access_token} | |
|
||||
|<------------------------------| |
|
||||
```
|
||||
|
||||
### Roles y permisos
|
||||
|
||||
| Rol | ID | Permisos |
|
||||
|-----|----|----------|
|
||||
| `ADMIN` | 1 | Todo: gestionar usuarios, catalogo, inventario |
|
||||
| `OWNER` | 2 | Gestionar usuarios, ver estadisticas |
|
||||
| `TALLER` | 3 | Consultar catalogo, ver disponibilidad en bodegas |
|
||||
| `BODEGA` | 4 | Gestionar inventario propio, subir CSV/Excel |
|
||||
|
||||
### JWT Token payload
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": 1,
|
||||
"role": "TALLER",
|
||||
"business_name": "Taller Perez",
|
||||
"type": "access",
|
||||
"exp": 1742300000,
|
||||
"iat": 1742299100
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inventory Flow (Bodega)
|
||||
|
||||
Flujo para que una bodega suba su inventario via CSV/Excel.
|
||||
|
||||
```
|
||||
Bodega (Browser) Servidor PostgreSQL
|
||||
| | |
|
||||
| 1. PUT /api/inventory/mapping| |
|
||||
| {part_number: "NUM_PARTE", | |
|
||||
| price: "PRECIO", | |
|
||||
| stock: "EXISTENCIA", | UPSERT inventory_col_map |
|
||||
| location: "ALMACEN"} |----------------------------->|
|
||||
|<------------------------------| |
|
||||
| | |
|
||||
| 2. POST /api/inventory/upload| |
|
||||
| multipart/form-data: file | |
|
||||
|------------------------------>| |
|
||||
| | a) Read mapping |
|
||||
| |<-----------------------------|
|
||||
| | |
|
||||
| | b) Parse CSV/Excel |
|
||||
| | (openpyxl or csv module) |
|
||||
| | |
|
||||
| | c) For each row: |
|
||||
| | - Extract part_number |
|
||||
| | using mapping |
|
||||
| | - Find part by OEM # |
|
||||
| | - If not found, try |
|
||||
| | aftermarket_parts |
|
||||
| | - UPSERT warehouse_inv |
|
||||
| |----------------------------->|
|
||||
| | |
|
||||
| {imported: 450, errors: 12} | d) Update inventory_uploads |
|
||||
|<------------------------------|----------------------------->|
|
||||
```
|
||||
|
||||
### Tabla `warehouse_inventory`
|
||||
|
||||
```sql
|
||||
warehouse_inventory (
|
||||
id_inventory BIGSERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users,
|
||||
part_id INTEGER REFERENCES parts,
|
||||
price NUMERIC(12,2),
|
||||
stock_quantity INTEGER DEFAULT 0,
|
||||
warehouse_location VARCHAR(100) DEFAULT 'Principal',
|
||||
updated_at TIMESTAMP,
|
||||
UNIQUE(user_id, part_id, warehouse_location)
|
||||
)
|
||||
```
|
||||
|
||||
El UNIQUE constraint permite que una bodega tenga la misma parte en multiples ubicaciones (e.g., "Principal", "Sucursal Norte").
|
||||
|
||||
---
|
||||
|
||||
## Aftermarket Linking
|
||||
|
||||
Como se relacionan partes OEM con alternativas aftermarket y cross-references.
|
||||
|
||||
```
|
||||
+--------------------+
|
||||
| parts |
|
||||
| (OEM catalog) |
|
||||
| id_part: 500 |
|
||||
| oem_part_number: |
|
||||
| "04152-YZZA1" |
|
||||
+--------+-----------+
|
||||
|
|
||||
+--------------+--------------+
|
||||
| |
|
||||
v v
|
||||
+----------------------------+ +----------------------------+
|
||||
| aftermarket_parts | | part_cross_references |
|
||||
| (alternativas) | | (numeros alternos) |
|
||||
| | | |
|
||||
| oem_part_id: 500 | | part_id: 500 |
|
||||
| manufacturer_id: -> DENSO | | cross_reference_number: |
|
||||
| part_number: "DXP-1234" | | "90915-YZZF1" |
|
||||
| quality_tier: "premium" | | reference_type: |
|
||||
| price_usd: 12.50 | | "oem_alternate" |
|
||||
| warranty_months: 24 | | source: "TecDoc" |
|
||||
+----------------------------+ +----------------------------+
|
||||
```
|
||||
|
||||
### Tipos de cross-reference
|
||||
|
||||
| Tipo | Descripcion |
|
||||
|------|-------------|
|
||||
| `oem_alternate` | Otro numero OEM para la misma parte (mismo fabricante) |
|
||||
| `supersession` | La parte fue reemplazada por un numero nuevo |
|
||||
| `interchange` | Numero de un competidor que es equivalente |
|
||||
| `competitor` | Referencia cruzada a otra marca |
|
||||
|
||||
### Flujo de busqueda por numero de parte
|
||||
|
||||
Cuando un taller busca un numero de parte, el sistema busca en 3 lugares:
|
||||
|
||||
1. **`parts.oem_part_number`** - Match directo OEM
|
||||
2. **`aftermarket_parts.part_number`** - Match en parte aftermarket, retorna el OEM original
|
||||
3. **`part_cross_references.cross_reference_number`** - Match en cross-ref, retorna el OEM original
|
||||
|
||||
Esto permite que el taller encuentre la parte sin importar que numero use (OEM, aftermarket, o numero alterno).
|
||||
|
||||
### Calidad (quality_tier)
|
||||
|
||||
| Tier | Descripcion | Ejemplo |
|
||||
|------|-------------|---------|
|
||||
| `economy` | Precio bajo, calidad basica | Marcas genericas |
|
||||
| `standard` | Calidad media, buen balance | Monroe, Moog |
|
||||
| `premium` | Calidad alta, cercana a OEM | Denso, Bosch |
|
||||
|
||||
---
|
||||
|
||||
## Stack Frontend
|
||||
|
||||
El frontend es HTML/CSS/JS vanilla sin framework. Cada pagina es independiente.
|
||||
|
||||
```
|
||||
dashboard/
|
||||
+-- shared.css # Estilos compartidos (colores, layout, cards)
|
||||
+-- nav.js # Navegacion compartida (inyecta sidebar/header)
|
||||
+-- login.html + .css + .js
|
||||
+-- demo.html # Catalogo publico
|
||||
+-- admin.html + .js # Panel admin (CRUD, users, import/export)
|
||||
+-- bodega.html + .css + .js # Inventory management
|
||||
+-- tienda.html + .css + .js # Store view para talleres
|
||||
+-- pos.html + .css + .js # Point of sale
|
||||
+-- captura.html + .css + .js # Captura de partes
|
||||
+-- cuentas.html + .css + .js # Gestion de cuentas
|
||||
+-- dashboard.js # Logica del catalogo principal
|
||||
+-- enhanced-search.js # Busqueda avanzada
|
||||
```
|
||||
|
||||
### Patron de comunicacion con API
|
||||
|
||||
Todas las paginas usan `fetch()` con el patron:
|
||||
|
||||
```javascript
|
||||
const token = localStorage.getItem('access_token');
|
||||
const res = await fetch('/api/...', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
const data = await res.json();
|
||||
```
|
||||
|
||||
### Nota sobre NUMERIC de PostgreSQL
|
||||
|
||||
PostgreSQL retorna valores `NUMERIC` como strings. Todas las funciones de formato en JS usan `parseFloat()` para convertir antes de mostrar.
|
||||
Reference in New Issue
Block a user