feat: module toggles in POS config and Instance Manager
- Add GET/PUT /pos/api/config/modules endpoints in POS config_bp.py - Update sidebar.js to filter nav items based on enabled modules - Add Modules section to POS config.html with toggles for WhatsApp, Marketplace, MercadoLibre - Add module load/save logic to POS config.js - Preload modules in app-init.js for sidebar caching - Add tenant module management to Instance Manager - get_tenant_modules / update_tenant_modules in tenant_service.py - GET/PUT /api/tenants/<id>/modules endpoints in tenants_bp.py - Add modules modal to manager index.html - Add module editing UI and logic to manager.js - Add toggle-switch CSS to manager.css
This commit is contained in:
@@ -16,6 +16,7 @@ sys.path.insert(0, os.path.join(_base, '..', 'pos')) # pos/ for auth, services
|
||||
sys.path.insert(0, os.path.join(_base, '..')) # root config.py (has DB_URL)
|
||||
from config import DB_URL
|
||||
from auth import hash_password, check_password, create_access_token, create_refresh_token, decode_token, require_auth
|
||||
from tenant_db import get_tenant_conn
|
||||
from services.translations import translate_part_name, translate_category
|
||||
|
||||
sys.path.insert(0, os.path.join(_base, '..', 'pos'))
|
||||
@@ -4628,6 +4629,76 @@ def part_aftermarket(part_id):
|
||||
session.close()
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Tenant Module Config Endpoints
|
||||
# ============================================================================
|
||||
|
||||
MODULE_CONFIG_KEYS = [
|
||||
'whatsapp_enabled',
|
||||
'marketplace_enabled',
|
||||
'meli_enabled',
|
||||
]
|
||||
|
||||
|
||||
@app.route('/api/admin/tenants')
|
||||
def api_admin_tenants():
|
||||
session = Session()
|
||||
try:
|
||||
rows = session.execute(text(
|
||||
"SELECT id, name, db_name, is_active, is_seller FROM tenants WHERE is_active = true ORDER BY id"
|
||||
)).mappings().all()
|
||||
return jsonify({'tenants': [dict(r) for r in rows]})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
@app.route('/api/admin/tenants/<int:tenant_id>/modules')
|
||||
def api_admin_tenant_modules(tenant_id):
|
||||
try:
|
||||
conn = get_tenant_conn(tenant_id)
|
||||
cur = conn.cursor()
|
||||
result = {}
|
||||
for key in MODULE_CONFIG_KEYS:
|
||||
cur.execute("SELECT value FROM tenant_config WHERE key = %s", (key,))
|
||||
row = cur.fetchone()
|
||||
result[key] = (row[0] or '').lower() == 'true' if row else False
|
||||
cur.close()
|
||||
conn.close()
|
||||
return jsonify(result)
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@app.route('/api/admin/tenants/<int:tenant_id>/modules', methods=['PUT'])
|
||||
def api_admin_tenant_modules_update(tenant_id):
|
||||
data = request.get_json() or {}
|
||||
if not data:
|
||||
return jsonify({'error': 'No data provided'}), 400
|
||||
|
||||
try:
|
||||
conn = get_tenant_conn(tenant_id)
|
||||
cur = conn.cursor()
|
||||
for key, value in data.items():
|
||||
if key not in MODULE_CONFIG_KEYS:
|
||||
continue
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO tenant_config (key, value, updated_at)
|
||||
VALUES (%s, %s, NOW())
|
||||
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()
|
||||
""",
|
||||
(key, 'true' if value else 'false'),
|
||||
)
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
return jsonify({'ok': True})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Static files from dashboard root (CSS/JS/HTML)
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user