From the database review (verdict: sound-with-minor-issues). Applies the actionable findings. Redundant indexes: five non-unique secondary indexes duplicated a named idx_* or a unique index on the same column - ix_communications_assetid, ix_computers_hostname, ix_networkdevices_hostname, ix_printers_hostname (each shadowing an idx_*), and idx_usb_serial (shadowing the serialnumber unique index). Removed the redundant index source from the models (column index=True / the extra db.Index) and added core migration 7d25 dropping the live duplicates. The unique ix_*_assetid indexes are kept (they enforce assetid uniqueness). Dead column: usbcheckouts.machineid was a NOT NULL soft-ref to the retired machines table storing sentinel 0 (ADR-001). Dropped from the model + the machineid=0 literal in selfhosted checkout; usb plugin migration 0002 drops it live (downgrade restores it default 0). Index: notifications.businessunitid (filtered by the shopfloor feed) was unindexed; added index=True + notifications migration 0002. CI: new migrations-mysql job proves the real multi-site deploy path - fresh `flask db upgrade` + per-plugin install on utf8mb4 MySQL from empty, asserting table count + charset and a clean second-run no-op. The pytest suite only exercises SQLite create_all(), so a regression in the Alembic chain on MySQL would otherwise ship undetected. Verified: fresh core upgrade on a scratch utf8mb4 MySQL builds clean + no-op on rerun (redundant indexes absent, unique assetid kept); plugin migrations applied + verified on the dev DB (machineid gone, bu index present). 953 backend tests pass; naming + pyflakes green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ShopDB Flask
A modern rewrite of the classic ASP/VBScript ShopDB application using Flask (Python) and Vue 3. This application manages shop floor machines, PCs, printers, applications, and related infrastructure for manufacturing environments.
Overview
ShopDB tracks and manages:
- Machines - CNC equipment, CMMs, inspection systems, etc.
- PCs - Shopfloor computers, engineering workstations
- Printers - Network printers with Zabbix integration
- Applications - Software deployed across the shop floor
- Knowledge Base - Documentation and troubleshooting guides
Tech Stack
Backend:
- Python 3.x with Flask
- SQLAlchemy ORM
- MySQL 5.7+ database (5.6 works with extra utf8mb4 config; see docs/DEPLOY.md)
- JWT authentication
- Plugin architecture for extensibility
Frontend:
- Vue 3 with Composition API
- Vue Router for navigation
- Pinia for state management
- Vite build system
Project Structure
shopdb-flask/
├── shopdb/ # Flask application
│ ├── core/
│ │ ├── api/ # REST API endpoints
│ │ ├── models/ # SQLAlchemy models
│ │ ├── schemas/ # Validation schemas
│ │ └── services/ # Business logic
│ ├── plugins/ # Plugin system
│ └── utils/ # Shared utilities
├── frontend/ # Vue 3 application
│ ├── src/
│ │ ├── api/ # API client
│ │ ├── components/ # Reusable components
│ │ ├── views/ # Page components
│ │ ├── router/ # Route definitions
│ │ └── stores/ # Pinia stores
│ └── public/ # Static assets
├── plugins/ # Bundled and external plugins
├── migrations/ # Alembic migration chain (flask db upgrade)
├── scripts/ # Import and utility scripts
└── tests/ # Test suite
Naming Conventions
To maintain consistency with the legacy ShopDB database and codebase, the following naming standards apply:
Database
- Table names: Lowercase, single word, no underscores or dashes
- Examples:
machines,pctypes,machinetypes,businessunits
- Examples:
- Column names: Lowercase, single word, no underscores or dashes
- Examples:
machineid,machinenumber,pctypeid,isactive,createddate
- Examples:
- Foreign keys: Referenced table name +
id- Examples:
locationid,vendorid,modelnumberid,pctypeid
- Examples:
- Boolean columns: Prefixed with
isorhas- Examples:
isactive,isshopfloor,isvnc,iswinrm,islicenced
- Examples:
Code
- Python variables: Follow database naming where applicable (lowercase, no underscores for model fields)
- JavaScript variables: camelCase for local variables, but match API field names from backend
- Vue components: PascalCase for component names
- CSS classes: Lowercase with dashes for multi-word classes
API
- Endpoints: Lowercase, plural nouns
- Examples:
/api/machines,/api/pctypes,/api/locations
- Examples:
- Query parameters: Lowercase, single word
- Examples:
?type=pc,?locationid=5,?isactive=true
- Examples:
Style Guidelines
- No emojis in code, comments, documentation, or UI
- Keep UI functional and professional
- Dark theme is the default
- Consistent table layouts across all list views
Setup
Prerequisites
- Python 3.8+
- Node.js 18+
- MySQL 5.7+ (5.6 works with extra utf8mb4 config; see docs/DEPLOY.md)
ShopDB Flask uses MySQL as the canonical database. SQLite is used only for the
test suite (TestingConfig in shopdb/config.py points at an in-memory
SQLite). Do not run dev or production against SQLite.
Distribution
The application is distributed internally through the GE Aerospace Gitea. Clone it from there; there is no public package or image registry.
Fast path (Docker)
The Docker image builds the Vue frontend and serves it from the API container, so a container deploy needs no separate Node build step.
cp .env.example .env
# Edit .env: set SECRET_KEY, JWT_SECRET_KEY, DATABASE_URL, CORS_ORIGINS,
# and the MYSQL_* passwords (see docs/CONFIG.md for every variable).
docker compose up -d --build
# Create the schema and seed the platform data (idempotent, safe to re-run):
docker compose exec api flask db upgrade
docker compose exec api flask seed permissions
docker compose exec api flask seed settings
docker compose exec api flask seed reference-data
Then browse to the site and complete the first-run setup wizard at /setup
(it creates the first admin account and captures site identity). To create the
admin headlessly instead of using the wizard:
docker compose exec api flask seed admin --username admin --email admin@facility.example.com
Manual path (venv + Node)
# Backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Edit .env with your database credentials and secrets.
flask db upgrade
flask seed permissions
flask seed settings
flask seed reference-data
flask run
# Frontend (separate terminal)
cd frontend
npm install
npm run dev # dev server on :5173
npm run build # production build into frontend/dist (served by Flask)
Complete first-run setup at /setup, or run flask seed admin for a headless
admin account.
To import data from the legacy ShopDB MySQL database (one-time, see
migrations/DATA_MIGRATION_GUIDE.md):
python scripts/import_from_mysql.py
For the full per-site deployment runbook see docs/DEPLOY.md; for every environment variable and Setting key see docs/CONFIG.md.
Configuration
Environment variables (.env):
| Variable | Description |
|---|---|
DATABASE_URL |
MySQL connection string |
SECRET_KEY |
Flask secret key |
JWT_SECRET_KEY |
JWT signing key |
JWT_ACCESS_TOKEN_EXPIRES |
Access token TTL (seconds) |
LOG_LEVEL |
Logging verbosity |
API Documentation
The REST API follows standard conventions:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/machines |
List machines (filterable by type) |
| GET | /api/machines/:id |
Get machine details |
| POST | /api/machines |
Create machine |
| PUT | /api/machines/:id |
Update machine |
| DELETE | /api/machines/:id |
Soft delete machine |
Query parameters for list endpoints:
page- Page number (default: 1)per_page- Items per page (default: 25)sort- Sort fieldorder- Sort direction (asc/desc)search- Search termtype- Filter by asset type (computer, printer, machine, network_device)
Plugin System
ShopDB supports plugins for extending functionality. See CONTRIBUTING.md for plugin development guidelines.
The image bundles eleven plugins; only the ones a site installs are loaded:
- computers - Shopfloor PCs and workstations
- employees - Employee directory
- machines - CNC, CMM, and other shop-floor machines
- measuringtools - Gage-lab instruments with calibration tracking
- knowledgebase - Documentation and troubleshooting guides
- network - Network devices
- notifications - Shopfloor notifications and recognition feed
- printers - Extended printer management with Zabbix integration
- slides - TV/kiosk slideshows
- usb - CMMC USB check-in/out tracking
- warranty - Dell warranty lookups
Legacy Migration
This project replicates functionality from the classic ASP/VBScript ShopDB site. Key mappings:
| Legacy | Modern |
|---|---|
| ASP/VBScript | Flask/Python |
| Classic ADO | SQLAlchemy |
| Server-side HTML | Vue 3 SPA |
| Session auth | JWT tokens |
License
Internal use only.