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>
This commit is contained in:
2026-04-18 05:35:53 +00:00
parent 6b097614a0
commit e95f7cf684
54 changed files with 11226 additions and 1422 deletions

225
scripts/setup_instance.sh Executable file
View File

@@ -0,0 +1,225 @@
#!/bin/bash
# ═══════════════════════════════════════════════════════════════════════
# Nexus Autoparts — Instance Setup Script
# Target: Raspberry Pi OS / Debian / Ubuntu
# Usage: sudo bash setup_instance.sh "Refaccionaria El Toro" "refac-eltoro"
# ═══════════════════════════════════════════════════════════════════════
set -e
BUSINESS_NAME="${1:-Refaccionaria Demo}"
INSTANCE_ID="${2:-refac-$(date +%s)}"
DB_PASSWORD="nexus_autoparts_2026"
DB_USER="nexus"
MASTER_DB="nexus_autoparts"
OWNER_PIN="${3:-1234}"
INSTALL_DIR="/home/Autopartes"
echo "╔══════════════════════════════════════════════╗"
echo "║ Nexus Autoparts — Instance Setup ║"
echo "║ Business: $BUSINESS_NAME"
echo "║ ID: $INSTANCE_ID"
echo "╚══════════════════════════════════════════════╝"
echo ""
# ─── 1. System deps ───────────────────────────────────────────────────
echo "→ Installing system dependencies..."
apt-get update -qq
apt-get install -y -qq \
postgresql postgresql-client \
python3 python3-pip python3-venv python3-dev \
nodejs npm \
ffmpeg espeak-ng \
git curl wget \
libpq-dev gcc \
2>/dev/null
echo " ✓ System deps installed"
# ─── 2. Python deps ──────────────────────────────────────────────────
echo "→ Installing Python packages..."
pip3 install --break-system-packages --quiet \
flask psycopg2-binary sqlalchemy pyjwt bcrypt requests \
gunicorn faster-whisper \
2>/dev/null || pip3 install --quiet \
flask psycopg2-binary sqlalchemy pyjwt bcrypt requests \
gunicorn faster-whisper
echo " ✓ Python packages installed"
# ─── 3. Node.js deps (WhatsApp bridge) ───────────────────────────────
if [ -d "/opt/whatsapp-bridge" ]; then
echo "→ Installing WhatsApp bridge deps..."
cd /opt/whatsapp-bridge && npm install --silent 2>/dev/null
echo " ✓ WhatsApp bridge ready"
else
echo " ⚠ WhatsApp bridge not found at /opt/whatsapp-bridge — skipping"
fi
# ─── 4. PostgreSQL setup ─────────────────────────────────────────────
echo "→ Configuring PostgreSQL..."
systemctl enable postgresql
systemctl start postgresql
# Create user if doesn't exist
su - postgres -c "psql -tc \"SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'\" | grep -q 1" \
|| su - postgres -c "createuser -s $DB_USER"
# Set password
su - postgres -c "psql -c \"ALTER USER $DB_USER WITH PASSWORD '$DB_PASSWORD';\""
# Create master DB if doesn't exist
su - postgres -c "psql -tc \"SELECT 1 FROM pg_database WHERE datname='$MASTER_DB'\" | grep -q 1" \
|| su - postgres -c "createdb -O $DB_USER $MASTER_DB"
echo " ✓ PostgreSQL configured"
# ─── 5. Import schema (master + tenant template) ─────────────────────
echo "→ Importing database schema..."
if [ -f "$INSTALL_DIR/vehicle_database/sql/schema.sql" ]; then
PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d $MASTER_DB \
-f "$INSTALL_DIR/vehicle_database/sql/schema.sql" 2>/dev/null || true
fi
if [ -f "$INSTALL_DIR/sql/marketplace_schema.sql" ]; then
PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d $MASTER_DB \
-f "$INSTALL_DIR/sql/marketplace_schema.sql" 2>/dev/null || true
fi
echo " ✓ Schema imported"
# ─── 6. Create tenant for this refaccionaria ─────────────────────────
echo "→ Creating tenant database for '$BUSINESS_NAME'..."
TENANT_DB="tenant_${INSTANCE_ID//-/_}"
su - postgres -c "psql -tc \"SELECT 1 FROM pg_database WHERE datname='$TENANT_DB'\" | grep -q 1" && {
echo " ⚠ Tenant DB '$TENANT_DB' already exists — skipping creation"
} || {
# Create from template if available, else create fresh
if su - postgres -c "psql -tc \"SELECT 1 FROM pg_database WHERE datname='tenant_template'\" | grep -q 1"; then
su - postgres -c "createdb -O $DB_USER -T tenant_template $TENANT_DB"
echo " ✓ Created from tenant_template"
else
su - postgres -c "createdb -O $DB_USER $TENANT_DB"
echo " ✓ Created fresh (no template available)"
fi
}
# Apply marketplace migration to tenant
if [ -f "$INSTALL_DIR/sql/marketplace_tenant_users.sql" ]; then
PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d "$TENANT_DB" \
-f "$INSTALL_DIR/sql/marketplace_tenant_users.sql" 2>/dev/null || true
fi
# Apply plate_vehicles migration
if [ -f "$INSTALL_DIR/pos/migrations/v1.7_plates.sql" ]; then
PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d "$TENANT_DB" \
-f "$INSTALL_DIR/pos/migrations/v1.7_plates.sql" 2>/dev/null || true
fi
echo " ✓ Tenant DB ready: $TENANT_DB"
# ─── 7. Register tenant in master ────────────────────────────────────
echo "→ Registering tenant in master DB..."
PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d $MASTER_DB -c "
INSERT INTO tenants (name, db_name, is_active, subdomain)
VALUES ('$BUSINESS_NAME', '$TENANT_DB', true, '$INSTANCE_ID')
ON CONFLICT DO NOTHING;
" 2>/dev/null || true
# Get tenant ID
TENANT_ID=$(PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d $MASTER_DB -t -c "
SELECT id FROM tenants WHERE db_name = '$TENANT_DB' LIMIT 1;
" 2>/dev/null | tr -d ' ')
echo " ✓ Tenant registered: ID=$TENANT_ID"
# ─── 8. Create owner employee ────────────────────────────────────────
echo "→ Creating owner employee..."
PIN_HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw('$OWNER_PIN'.encode(), bcrypt.gensalt()).decode())")
PGPASSWORD=$DB_PASSWORD psql -U $DB_USER -h localhost -d "$TENANT_DB" -c "
INSERT INTO employees (name, role, pin, password_hash, is_active, marketplace_role)
VALUES ('Administrador', 'owner', '$PIN_HASH', '$PIN_HASH', true, 'buyer')
ON CONFLICT DO NOTHING;
INSERT INTO branches (name, address, phone, is_active)
VALUES ('Principal', '', '', true)
ON CONFLICT DO NOTHING;
" 2>/dev/null || true
echo " ✓ Owner employee created (PIN: $OWNER_PIN)"
# ─── 9. Configure peers.json ─────────────────────────────────────────
echo "→ Configuring peers.json..."
# Get this machine's IP
LOCAL_IP=$(hostname -I | awk '{print $1}')
cat > "$INSTALL_DIR/pos/peers.json" << EOJSON
{
"instance_name": "$BUSINESS_NAME",
"instance_id": "$INSTANCE_ID",
"tenant_id": $TENANT_ID,
"peers": [],
"peer_timeout_seconds": 3,
"notes": "Add peer instances here: {\"name\": \"Refac B\", \"url\": \"http://192.168.X.Y:5001\", \"enabled\": true}"
}
EOJSON
echo " ✓ peers.json configured (local IP: $LOCAL_IP)"
# ─── 10. Create Gunicorn systemd service ─────────────────────────────
echo "→ Setting up Gunicorn service..."
cat > /etc/systemd/system/nexus-pos.service << EOSERVICE
[Unit]
Description=Nexus Autoparts POS
After=network.target postgresql.service
[Service]
User=root
WorkingDirectory=$INSTALL_DIR/pos
Environment="PATH=/usr/local/bin:/usr/bin"
ExecStart=/usr/local/bin/gunicorn -w 2 -b 0.0.0.0:5001 --timeout 120 app:app
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOSERVICE
systemctl daemon-reload
systemctl enable nexus-pos
# Don't start yet — let user verify config first
echo " ✓ Gunicorn service created (nexus-pos)"
# ─── Done ─────────────────────────────────────────────────────────────
echo ""
echo "╔══════════════════════════════════════════════╗"
echo "║ SETUP COMPLETE ║"
echo "╚══════════════════════════════════════════════╝"
echo ""
echo "Instance: $BUSINESS_NAME"
echo "Tenant DB: $TENANT_DB (ID: $TENANT_ID)"
echo "Owner PIN: $OWNER_PIN"
echo "Local IP: $LOCAL_IP"
echo ""
echo "To start the POS:"
echo " systemctl start nexus-pos"
echo " # or manually: cd $INSTALL_DIR/pos && gunicorn -w 2 -b 0.0.0.0:5001 app:app"
echo ""
echo "To add peers, edit: $INSTALL_DIR/pos/peers.json"
echo "To import inventory: python3 $INSTALL_DIR/scripts/import_inventory.py --tenant=$TENANT_ID --csv=inventario.csv"
echo ""
echo "Access: http://$LOCAL_IP:5001/pos/login"