Files
Autoparts-DB/pos/services/catalog_modes.py
consultoria-as e95f7cf684 feat: complete session — catalog, marketplace, WhatsApp, peer-to-peer, install scripts
Major features:
- Pixel-Perfect glassmorphism design (landing + POS + public catalog)
- OEM/Local catalog toggle with Nexpart taxonomy (14 groups, 108 subgroups, 558 part types)
- Marketplace B2B Phase 1 (bodegas, POs, status machine, WA+email notifications)
- Peer-to-peer inventory (multi-instance, LAN discovery)
- WhatsApp: photo→Vision AI, voice→Whisper, conversational quotations
- Smart unified search (VIN/plate/part_number/keyword auto-detect)
- Shop Supplies tab (vehicle-independent parts)
- Chatbot AI fallback chain (5 models) + response cache
- CSV inventory import tool + setup_instance.sh installer
- Tablet-responsive CSS + sidebar toggle
- Filters, export CSV, employee edit, business data save
- Quotation system (WA→POS) with auto-print on confirmation
- Live stats on landing page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 05:35:53 +00:00

130 lines
4.8 KiB
Python

"""
Catalog modes — OEM vs Local bodega filtering for brand lists.
Two catalog modes coexist:
- 'oem' : Full TecDoc catalog (36+ vehicle brands from Apify import).
Use this for any customer-facing "find your exact OEM part" flow.
- 'local' : Curated list of vehicle brands that local bodegas in Mexico
actually service. Used while the TecDoc/Apify import is paused
or to simplify navigation for customers who only care about
what's available locally.
Both modes use the SAME navigation hierarchy (brand > model > year > engine >
category > parts). Only the initial brand list is filtered.
Edit LOCAL_BODEGA_BRANDS below to add/remove brands as the bodega network grows.
Brand names must match the `brands.name_brand` column in nexus_autoparts
(case-sensitive, uppercase).
"""
# ─── OEM mode — full North America coverage (imported from TecDoc) ──────────
OEM_BRANDS_NA = (
'ACURA', 'AUDI', 'BMW', 'BUICK', 'CADILLAC', 'CHEVROLET', 'CHRYSLER',
'DODGE', 'FIAT', 'FORD', 'GMC', 'HONDA', 'HYUNDAI', 'INFINITI',
'JAGUAR', 'JEEP', 'KIA', 'LAND ROVER', 'LEXUS', 'LINCOLN', 'MAZDA',
'MERCEDES-BENZ', 'MINI', 'MITSUBISHI', 'NISSAN', 'PEUGEOT', 'PORSCHE',
'RAM', 'RENAULT', 'SEAT', 'SUBARU', 'SUZUKI', 'TESLA', 'TOYOTA',
'VOLVO', 'VW',
)
# ─── Local mode — brands actually stocked by Mexican bodegas ────────────────
# Popular Mexican market passenger cars + light trucks. Edit as needed.
LOCAL_BODEGA_BRANDS = (
'NISSAN', # Tsuru, Sentra, Versa, March, Tiida, Navara
'VW', # Jetta, Pointer, Vento, Gol, Polo, Beetle
'CHEVROLET', # Aveo, Chevy, Spark, Beat, Sonic, Sail
'FORD', # Fiesta, Focus, EcoSport, Ranger, Figo
'TOYOTA', # Corolla, Yaris, Hilux, Avanza, Tacoma
'HONDA', # Civic, City, CR-V, Fit, HR-V
'DODGE', # Attitude, Neon, Journey
'CHRYSLER',
'RAM', # Pickups
'HYUNDAI', # Accent, Grand i10, Tucson, Elantra
'KIA', # Rio, Forte, Sportage, Sorento
'MAZDA', # 2, 3, CX-5, CX-30
'MITSUBISHI', # Lancer, L200, Outlander
'RENAULT', # Logan, Sandero, Duster, Stepway
'SEAT', # Ibiza, Leon, Arona
'FIAT', # Uno, Palio, Mobi
'SUZUKI', # Swift, Vitara, Ignis, Ertiga
'JEEP', # Compass, Wrangler, Grand Cherokee, Renegade
'GMC', # Sierra, Terrain
'BUICK', # Encore, Enclave (GM)
)
def get_brands_for_mode(mode):
"""Return the tuple of allowed brand names for a given catalog mode.
Args:
mode: 'oem' or 'local'. Anything else defaults to 'oem'.
Returns:
A tuple of uppercase brand name strings.
"""
if mode == 'local':
return LOCAL_BODEGA_BRANDS
return OEM_BRANDS_NA
def normalize_mode(raw):
"""Normalize a raw mode string from a query param or header."""
if not raw:
return 'oem'
cleaned = str(raw).strip().lower()
return 'local' if cleaned == 'local' else 'oem'
# ─── Local mode — priority aftermarket manufacturer brands ─────────────────
# Ordered list. Brands earlier in the list are shown first and get the top
# "priority" badge in the UI. Match `manufacturers.name_manufacture` (uppercase).
#
# Tier 1 (most trusted / most stocked in Mexican bodegas) — shown first.
# Tier 2 (also popular but not always on every shelf) — shown second.
# Anything not in either list is "other" and shown last.
LOCAL_PRIORITY_MANUFACTURERS_TIER1 = (
'BOSCH', # Universal — ignition, sensors, filters, wipers
'GATES', # Bandas / timing belts
'MONROE', # Amortiguadores
'DENSO', # Ignition, cooling, AC
'MANN-FILTER', # Filtros
'MAHLE', # Filtros, pistones, termostatos
'NGK', # Bujias
'BREMBO', # Frenos premium
'KYB', # Amortiguadores
'SKF', # Rodamientos
)
LOCAL_PRIORITY_MANUFACTURERS_TIER2 = (
'DELPHI',
'VALEO',
'HELLA',
'DAYCO',
'SACHS',
'CHAMPION',
'WAGNER',
'FRAM',
'NSK',
)
# Combined flat tuple (Tier1 followed by Tier2) — used for SQL IN clauses
# and for determining "any priority" status.
LOCAL_PRIORITY_MANUFACTURERS = LOCAL_PRIORITY_MANUFACTURERS_TIER1 + LOCAL_PRIORITY_MANUFACTURERS_TIER2
def get_priority_tier(manufacturer_name):
"""Return 1 for tier 1, 2 for tier 2, 3 for everything else.
Used both by the sort order and by the UI to render a priority badge.
"""
if not manufacturer_name:
return 3
name = manufacturer_name.upper()
if name in LOCAL_PRIORITY_MANUFACTURERS_TIER1:
return 1
if name in LOCAL_PRIORITY_MANUFACTURERS_TIER2:
return 2
return 3