Consolidate Reports and Data Entry apps into a single Vue.js SPA with: Architecture: - Module-based structure with lazy-loaded routes (@reports, @data-entry) - Error boundaries per module to prevent cascade failures - Dual API proxy in Vite for microservices (reports:8001, data-entry:8003) - Pinia store factories for shared auth, company, and period stores - Vite path aliases for clear module boundaries (@shared, @reports, @data-entry) Service Management: - Granular service control scripts (backend-reports.sh, backend-data-entry.sh, bot.sh, frontend.sh) - 87% faster frontend restart: 7s vs 53s full restart - 38% faster full startup: 33s vs 53s via parallel backend initialization - Enhanced start-dev.sh with proper service timeouts (OCR: 30s, Vite: 15s, Bot: 10s) - status.sh for comprehensive health checks Features: - Auto-select first company on login with period auto-load - Hamburger menu with feature toggle support - JWT token auto-injection via axios interceptors - Unified header with company/period selectors - IIS web.config for production deployment with multi-API routing UX Improvements: - Vue watchers for reactive company/period loading - Lazy store initialization with graceful error handling - Period persistence per user+company in localStorage - Feature flags for optional modules Deployment: - Single IIS site serves unified frontend with API proxy rules - Maintains separate backend processes for microservices - Windows line ending fixes (.env CRLF → LF conversion) Stats: 112 files changed, 38,342 insertions(+), 2,342 deletions(-) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
355 lines
9.4 KiB
Bash
355 lines
9.4 KiB
Bash
#!/bin/bash
|
|
|
|
# ROA2WEB Unified App - TEST Starter Script
|
|
# Starts all services for the unified application:
|
|
# - Reports Backend (8001)
|
|
# - Data Entry Backend (8003)
|
|
# - Telegram Bot (8002)
|
|
# - Unified Frontend (3000)
|
|
|
|
set -e # Exit on any error
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Function to print colored messages
|
|
print_message() {
|
|
echo -e "${CYAN}[UNIFIED]${NC} $1"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Function to check if port is in use
|
|
check_port() {
|
|
local port=$1
|
|
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Function to cleanup processes on exit
|
|
cleanup() {
|
|
print_message "Stopping all services..."
|
|
|
|
# Stop Reports Backend (8001)
|
|
if check_port 8001; then
|
|
print_message "Stopping Reports Backend..."
|
|
lsof -ti:8001 | xargs kill -TERM 2>/dev/null || true
|
|
sleep 1
|
|
lsof -ti:8001 | xargs kill -KILL 2>/dev/null || true
|
|
fi
|
|
|
|
# Stop Data Entry Backend (8003)
|
|
if check_port 8003; then
|
|
print_message "Stopping Data Entry Backend..."
|
|
lsof -ti:8003 | xargs kill -TERM 2>/dev/null || true
|
|
sleep 1
|
|
lsof -ti:8003 | xargs kill -KILL 2>/dev/null || true
|
|
fi
|
|
|
|
# Stop Telegram Bot (8002)
|
|
if check_port 8002; then
|
|
print_message "Stopping Telegram Bot..."
|
|
lsof -ti:8002 | xargs kill -TERM 2>/dev/null || true
|
|
sleep 1
|
|
lsof -ti:8002 | xargs kill -KILL 2>/dev/null || true
|
|
fi
|
|
|
|
# Stop Unified Frontend (3000)
|
|
if check_port 3000; then
|
|
print_message "Stopping Unified Frontend..."
|
|
lsof -ti:3000 | xargs kill -TERM 2>/dev/null || true
|
|
sleep 1
|
|
lsof -ti:3000 | xargs kill -KILL 2>/dev/null || true
|
|
fi
|
|
|
|
# Stop SSH tunnel
|
|
if [ -f "./ssh-tunnel-test.sh" ]; then
|
|
print_message "Stopping SSH Tunnel..."
|
|
./ssh-tunnel-test.sh stop 2>/dev/null || true
|
|
fi
|
|
|
|
print_success "All services stopped."
|
|
exit 0
|
|
}
|
|
|
|
# Check command line arguments
|
|
if [ "$1" = "stop" ]; then
|
|
cleanup
|
|
fi
|
|
|
|
# Set up signal handlers
|
|
trap cleanup SIGINT SIGTERM
|
|
|
|
print_message "Starting ROA2WEB Unified App (TEST Environment)..."
|
|
echo
|
|
|
|
# Step 1: Start SSH Tunnel
|
|
print_message "1. Starting SSH Tunnel..."
|
|
if [ -f "./ssh-tunnel-test.sh" ]; then
|
|
if ./ssh-tunnel-test.sh start; then
|
|
print_success "SSH Tunnel started"
|
|
else
|
|
print_warning "SSH tunnel may already be running or failed to start"
|
|
fi
|
|
else
|
|
print_warning "SSH tunnel script not found - skipping"
|
|
fi
|
|
|
|
sleep 2
|
|
|
|
# Steps 2-4: Start backends in PARALLEL for faster startup
|
|
print_message "2-4. Starting backends in parallel..."
|
|
echo
|
|
|
|
# Start Reports Backend in background (parallel)
|
|
(
|
|
if check_port 8001; then
|
|
print_warning "Port 8001 already in use - Reports Backend may be running"
|
|
else
|
|
print_message "[Reports] Starting backend on port 8001..."
|
|
cd reports-app/backend/
|
|
|
|
# Create venv if doesn't exist
|
|
if [ ! -d "venv" ]; then
|
|
print_message "[Reports] Creating Python virtual environment..."
|
|
python3 -m venv venv
|
|
fi
|
|
|
|
# Activate venv
|
|
source venv/bin/activate
|
|
|
|
# Install dependencies if needed
|
|
if ! python -c "import fastapi, uvicorn" 2>/dev/null; then
|
|
print_message "[Reports] Installing dependencies..."
|
|
pip install -q -r requirements.txt
|
|
fi
|
|
|
|
# Load test environment
|
|
if [ -f ".env.test" ]; then
|
|
set -a
|
|
source .env.test
|
|
set +a
|
|
fi
|
|
|
|
# Start backend
|
|
nohup uvicorn app.main:app --host 0.0.0.0 --port 8001 > /tmp/reports_backend.log 2>&1 &
|
|
|
|
cd - > /dev/null
|
|
fi
|
|
) &
|
|
REPORTS_START_PID=$!
|
|
|
|
# Start Data Entry Backend in background (parallel)
|
|
(
|
|
if check_port 8003; then
|
|
print_warning "Port 8003 already in use - Data Entry Backend may be running"
|
|
else
|
|
print_message "[Data Entry] Starting backend on port 8003..."
|
|
cd data-entry-app/backend/
|
|
|
|
# Create venv if doesn't exist
|
|
if [ ! -d "venv" ]; then
|
|
print_message "[Data Entry] Creating Python virtual environment..."
|
|
python3 -m venv venv
|
|
fi
|
|
|
|
# Activate venv
|
|
source venv/bin/activate
|
|
|
|
# Install dependencies if needed
|
|
if ! python -c "import fastapi, uvicorn, sqlmodel" 2>/dev/null; then
|
|
print_message "[Data Entry] Installing dependencies..."
|
|
pip install -q -r requirements.txt
|
|
fi
|
|
|
|
# Copy TEST environment
|
|
if [ -f ".env.test" ]; then
|
|
cp .env.test .env
|
|
fi
|
|
|
|
# Load environment
|
|
if [ -f ".env" ]; then
|
|
set -a
|
|
source .env
|
|
set +a
|
|
fi
|
|
|
|
# Start backend
|
|
nohup uvicorn app.main:app --host 0.0.0.0 --port 8003 > /tmp/data_entry_backend.log 2>&1 &
|
|
|
|
cd - > /dev/null
|
|
fi
|
|
) &
|
|
DATA_ENTRY_START_PID=$!
|
|
|
|
# Start Telegram Bot in background (parallel)
|
|
(
|
|
if check_port 8002; then
|
|
print_warning "Port 8002 already in use - Telegram Bot may be running"
|
|
else
|
|
cd reports-app/telegram-bot/
|
|
|
|
# Copy TEST environment if exists
|
|
if [ -f ".env.test" ]; then
|
|
cp .env.test .env
|
|
elif [ ! -f ".env" ]; then
|
|
print_warning "[Bot] .env not found - skipping"
|
|
cd - > /dev/null
|
|
exit 0
|
|
fi
|
|
|
|
if [ -f ".env" ]; then
|
|
print_message "[Bot] Starting Telegram bot on port 8002..."
|
|
|
|
# Create venv if doesn't exist
|
|
if [ ! -d "venv" ]; then
|
|
print_message "[Bot] Creating Python virtual environment..."
|
|
python3 -m venv venv
|
|
fi
|
|
|
|
# Activate venv
|
|
source venv/bin/activate
|
|
|
|
# Install dependencies if needed
|
|
if ! python -c "import telegram" 2>/dev/null; then
|
|
print_message "[Bot] Installing dependencies..."
|
|
pip install -q -r requirements.txt
|
|
fi
|
|
|
|
# Start bot
|
|
nohup python -m app.main > /tmp/telegram_bot.log 2>&1 &
|
|
|
|
cd - > /dev/null
|
|
fi
|
|
fi
|
|
) &
|
|
BOT_START_PID=$!
|
|
|
|
# Wait for all background startup processes to complete
|
|
print_message "Waiting for backends to initialize..."
|
|
wait $REPORTS_START_PID $DATA_ENTRY_START_PID $BOT_START_PID
|
|
|
|
# Now check if services are actually running on their ports
|
|
echo
|
|
print_message "Checking backend status..."
|
|
|
|
# Check Reports Backend (wait up to 20s)
|
|
if ! check_port 8001; then
|
|
print_message "Waiting for Reports Backend (Oracle pool initialization)..."
|
|
for i in {1..20}; do
|
|
sleep 1
|
|
if check_port 8001; then
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if check_port 8001; then
|
|
print_success "Reports Backend started on http://localhost:8001"
|
|
else
|
|
print_error "Reports Backend failed to start - check /tmp/reports_backend.log"
|
|
cleanup
|
|
fi
|
|
|
|
# Check Data Entry Backend (wait up to 25s for DB migrations)
|
|
if ! check_port 8003; then
|
|
print_message "Waiting for Data Entry Backend (database initialization)..."
|
|
for i in {1..25}; do
|
|
sleep 1
|
|
if check_port 8003; then
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if check_port 8003; then
|
|
print_success "Data Entry Backend started on http://localhost:8003"
|
|
else
|
|
print_error "Data Entry Backend failed to start - check /tmp/data_entry_backend.log"
|
|
cleanup
|
|
fi
|
|
|
|
# Check Telegram Bot
|
|
if ! check_port 8002; then
|
|
print_message "Waiting for Telegram Bot..."
|
|
for i in {1..5}; do
|
|
sleep 1
|
|
if check_port 8002; then
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if check_port 8002; then
|
|
print_success "Telegram Bot started on http://localhost:8002 (Internal API)"
|
|
else
|
|
print_warning "Telegram Bot may have failed - check /tmp/telegram_bot.log"
|
|
fi
|
|
|
|
# Step 5: Start Unified Frontend (port 3000)
|
|
print_message "5. Starting Unified Frontend (port 3000)..."
|
|
|
|
if check_port 3000; then
|
|
print_warning "Port 3000 already in use - Unified Frontend may be running"
|
|
else
|
|
# Check if node_modules exists
|
|
if [ ! -d "node_modules" ] || [ ! -f "node_modules/.bin/vite" ]; then
|
|
print_message "Installing Unified Frontend dependencies..."
|
|
npm install
|
|
fi
|
|
|
|
# Start frontend
|
|
print_message "Starting Vite development server..."
|
|
nohup npm run dev > /tmp/unified_frontend.log 2>&1 &
|
|
FRONTEND_PID=$!
|
|
|
|
# Wait for frontend to start
|
|
sleep 10
|
|
if check_port 3000; then
|
|
print_success "Unified Frontend started on http://localhost:3000"
|
|
else
|
|
print_error "Unified Frontend failed to start - check /tmp/unified_frontend.log"
|
|
cat /tmp/unified_frontend.log
|
|
cleanup
|
|
fi
|
|
fi
|
|
|
|
# Summary
|
|
echo
|
|
print_success "🚀 ROA2WEB Unified App is now running!"
|
|
echo
|
|
echo -e "${BLUE}Services:${NC}"
|
|
echo " • SSH Tunnel: Active (Oracle DB connection)"
|
|
echo " • Reports Backend: http://localhost:8001"
|
|
echo " • Data Entry Backend: http://localhost:8003"
|
|
echo " • Telegram Bot: http://localhost:8002 (Internal API)"
|
|
echo " • Unified Frontend: http://localhost:3000"
|
|
echo
|
|
echo -e "${BLUE}API Documentation:${NC}"
|
|
echo " • Reports API: http://localhost:8001/docs"
|
|
echo " • Data Entry API: http://localhost:8003/docs"
|
|
echo
|
|
echo -e "${YELLOW}Press Ctrl+C to stop all services${NC}"
|
|
echo
|
|
|
|
# Keep script running
|
|
wait
|