feat: configurable vehicle compatibility source (TecDoc / QWEN / Both)

Backend:
- Added GET/PUT /pos/api/config/vehicle-compat-source endpoints
- Added get_compat_source() helper reading from tenant_config
- create_item() now respects config: runs TecDoc and/or QWEN accordingly
- auto_match_item_vehicles() respects config: runs only configured source

Frontend:
- Added 'Compatibilidad de Vehiculos' section in config.html
- Added loadVehicleCompatSource() / saveVehicleCompatSource() in config.js
- Regenerated config.min.js
This commit is contained in:
2026-05-01 06:52:06 +00:00
parent 5421c47ffc
commit af7b010e55
6 changed files with 232 additions and 42 deletions

View File

@@ -18,7 +18,7 @@ from services.audit import log_action
from tenant_db import get_master_conn
from services.inventory_vehicle_compat import (
auto_match_vehicle_compatibility, add_compatibility, remove_compatibility,
remove_all_compatibility, get_compatibility, search_mye,
remove_all_compatibility, get_compatibility, search_mye, get_compat_source,
)
inventory_bp = Blueprint('inventory', __name__, url_prefix='/pos/api/inventory')
@@ -283,38 +283,43 @@ def create_item():
conn.commit()
cur.close()
# Auto-match vehicle compatibility via TecDoc
try:
master = get_master_conn()
auto_match_vehicle_compatibility(master, conn, item_id, data['part_number'],
brand=data.get('brand'), name=data.get('name'))
master.close()
except Exception as am_err:
print(f"[auto_match] Error for item {item_id}: {am_err}")
# QWEN AI fitment (complementa TecDoc mientras se termina)
# ── Vehicle compatibility (respects tenant config) ────────────────
compat_source = get_compat_source(g.tenant_id)
qwen_added = 0
try:
from services.qwen_fitment import get_vehicle_fitment
fitment = get_vehicle_fitment(
data['part_number'],
data['name'],
data.get('brand', '')
)
for v in fitment.get('vehicles', []):
if v.get('mye_id'):
cur = conn.cursor()
cur.execute("""
INSERT INTO inventory_vehicle_compat
(inventory_id, model_year_engine_id, source, confidence, created_at)
VALUES (%s, %s, %s, %s, NOW())
ON CONFLICT (inventory_id, model_year_engine_id) DO NOTHING
""", (item_id, v['mye_id'], 'qwen_ai', fitment.get('confidence', 0)))
cur.close()
qwen_added += 1
conn.commit()
except Exception as qwen_err:
print(f"[qwen_fitment] Error for item {item_id}: {qwen_err}")
# TecDoc auto-match
if compat_source in ('tecdoc', 'both'):
try:
master = get_master_conn()
auto_match_vehicle_compatibility(master, conn, item_id, data['part_number'],
brand=data.get('brand'), name=data.get('name'))
master.close()
except Exception as am_err:
print(f"[auto_match] Error for item {item_id}: {am_err}")
# QWEN AI fitment
if compat_source in ('qwen', 'both'):
try:
from services.qwen_fitment import get_vehicle_fitment
fitment = get_vehicle_fitment(
data['part_number'],
data['name'],
data.get('brand', '')
)
for v in fitment.get('vehicles', []):
if v.get('mye_id'):
cur = conn.cursor()
cur.execute("""
INSERT INTO inventory_vehicle_compat
(inventory_id, model_year_engine_id, source, confidence, created_at)
VALUES (%s, %s, %s, %s, NOW())
ON CONFLICT (inventory_id, model_year_engine_id) DO NOTHING
""", (item_id, v['mye_id'], 'qwen_ai', fitment.get('confidence', 0)))
cur.close()
qwen_added += 1
conn.commit()
except Exception as qwen_err:
print(f"[qwen_fitment] Error for item {item_id}: {qwen_err}")
conn.close()
return jsonify({
@@ -1363,14 +1368,51 @@ def auto_match_item_vehicles(item_id):
return jsonify({'error': 'Item not found'}), 404
part_number, brand, name = row
master = get_master_conn()
try:
result = auto_match_vehicle_compatibility(master, conn, item_id, part_number,
brand=brand, name=name)
return jsonify(result)
finally:
master.close()
conn.close()
compat_source = get_compat_source(g.tenant_id)
# TecDoc auto-match
if compat_source in ('tecdoc', 'both'):
master = get_master_conn()
try:
result = auto_match_vehicle_compatibility(master, conn, item_id, part_number,
brand=brand, name=name)
return jsonify(result)
finally:
master.close()
conn.close()
# QWEN AI auto-match
if compat_source == 'qwen':
try:
from services.qwen_fitment import get_vehicle_fitment
fitment = get_vehicle_fitment(part_number, name, brand)
# Insert results
inserted = 0
cur2 = conn.cursor()
for v in fitment.get('vehicles', []):
if v.get('mye_id'):
cur2.execute("""
INSERT INTO inventory_vehicle_compat
(inventory_id, model_year_engine_id, source, confidence, created_at)
VALUES (%s, %s, %s, %s, NOW())
ON CONFLICT (inventory_id, model_year_engine_id) DO NOTHING
""", (item_id, v['mye_id'], 'qwen_ai', fitment.get('confidence', 0)))
if cur2.rowcount > 0:
inserted += 1
conn.commit()
cur2.close()
return jsonify({
'matched': inserted > 0,
'matches': [],
'myes': [v['mye_id'] for v in fitment.get('vehicles', []) if v.get('mye_id')],
'inserted': inserted,
})
except Exception as e:
conn.close()
return jsonify({'error': str(e)}), 500
conn.close()
return jsonify({'error': 'No compatibility source configured'}), 400
@inventory_bp.route('/mye/search', methods=['GET'])