Files
shopdb-flask/README.md
cproudlock 70f10c6fa0 Stop the README offering a feature this image cannot provide
Two claims did not survive the lean cut.

The plugin list and the overview both advertised notifications as carrying a
"recognition feed". Recognition, along with training and recertification, splits
one notification into a card per employee and renders an employee photo - all of
which needs the employees plugin, which this image does not bundle, so those
three types are no longer seeded here. A site reading the README would have gone
looking for a feature that is deliberately absent. The plugin line now says
which types need employees and why.

"Fast path (Docker)" also implied a slower path exists. On this branch Docker is
the only path: there is no installer here, and the Distribution section above it
already says so. Renamed to "Standing up a site".

The rest of the README was already right for what main is - it lists the twelve
bundled plugins, explains that applications is core rather than a plugin, and
describes the three compose files without mentioning the Windows installer that
lives on the site line.
2026-09-19 12:20:47 -04:00

272 lines
10 KiB
Markdown

# 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 supply integration
- **Network devices** - Switches, routers, and the subnet browser
- **Applications** - Software deployed across the shop floor, with per-PC install tracking
- **Endpoints** - RMM telemetry reported by the ShopDB agent: metrics, services, inventory, Windows events
- **Backups** - Per-asset configuration backups with revision history and diffs
- **Warranties** - Coverage records with vendor warranty lookups
- **Knowledge Base and Guides** - Reference articles and step-by-step procedures with working checklists
- **Notifications** - Shopfloor announcements, planned changes and incident notices
- **Slides** - Lobby display and shopfloor screensaver slideshows
## Tech Stack
**Backend:**
- Python 3.14 with Flask
- SQLAlchemy ORM
- MySQL 5.7+ database (5.6 works with extra utf8mb4 config; see the DEPLOY wiki page)
- 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: `assets`, `computers`, `printers`, `businessunits`
- **Column names:** Lowercase, single word, no underscores or dashes
- Examples: `assetid`, `assetnumber`, `hostname`, `isactive`, `createddate`
- **Foreign keys:** Referenced table name + `id`
- Examples: `locationid`, `vendorid`, `modelnumberid`, `computertypeid`
- **Boolean columns:** Prefixed with `is` or `has`
- Examples: `isactive`, `isshopfloor`, `iscolor`, `isdhcp`, `islicenced`
### 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/computers`, `/api/locations`
- **Query parameters:** Lowercase, single word
- Examples: `?locationid=5`, `?isactive=true`, `?assettype=computer`
## 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.14
- Node.js 18+
- MySQL 5.7+ (5.6 works with extra utf8mb4 config; see the DEPLOY wiki page)
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
Source lives here, and a site stands up ShopDB with Docker. Three compose
files cover the three situations: `docker-compose.yml` builds the image from
this checkout, `docker-compose.pull.yml` runs an image published to a
registry, and `docker-compose.airgap.yml` runs an image loaded from a tarball
at a site with no internet.
### Standing up a site
The Docker image builds the Vue frontend and serves it from the API container,
so a container deploy needs no separate Node build step.
```bash
cp .env.example .env
# Edit .env: set SECRET_KEY, JWT_SECRET_KEY, DATABASE_URL, CORS_ORIGINS,
# and the MYSQL_* passwords (see the CONFIG wiki page 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:
```bash
docker compose exec api flask seed admin --username admin --email admin@facility.example.com
```
### Manual path (venv + Node)
```bash
# 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.
export FLASK_APP=shopdb
flask db upgrade
flask plugin upgrade-all # per-plugin schema (ADR-008)
flask seed permissions
flask seed settings
flask seed reference-data
flask run --port 5001 # MUST be 5001 - the frontend dev server proxies here
# 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. The repo ships VS Code config in `.vscode/` (F5 debugs the
backend; a "Dev site" task runs both servers). A fuller day-one walkthrough,
including VS Code and troubleshooting, is the DEVELOPMENT-SETUP page in the
project wiki.
To import a site's legacy data, use the HTTP import surface: an admin API
token plus the IMPORT-API page in the project wiki drive the whole migration
through documented endpoints (`X-Import-Mode` preserves original timestamps).
`scripts/site_imports/` holds the shared import machinery - the resolver, the
idempotent journal, the approval packet builder and the WINC machine-adoption
writer that the core import routes call.
### Which deployment route
| Target | Use |
|---|---|
| Docker, connected | the DEPLOY page in the project wiki (`docker-compose.yml` or `docker-compose.pull.yml`) |
| Docker, air-gapped | the DEPLOY-AIRGAP page in the project wiki (`docker-compose.airgap.yml`) |
For every environment variable and Setting key see the CONFIG page in the project wiki.
## 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 |
Each asset plugin exposes the same CRUD pattern on its own prefix
(`/api/computers`, `/api/printers`, `/api/network`, `/api/machines`),
and cross-cutting asset endpoints live under `/api/assets`.
Query parameters for list endpoints:
- `page` - Page number (default: 1)
- `perpage` - Items per page
- `sort` - Sort field
- `dir` - Sort direction (asc/desc)
- `search` - Search term
- `assettype` - Filter by asset type (computer, printer, machine, networkdevice)
## Where to start
the START-HERE page in the project wiki routes by what you are here to do -
standing up a site, deploying the shop-floor tools, writing a plugin,
integrating with the API, or diagnosing something. On the published mirror the
same page is the wiki's front door.
## Plugin System
ShopDB supports plugins for extending functionality. See `CONTRIBUTING.md` for plugin development guidelines.
The image bundles these plugins; only the ones a site installs are loaded. The
current count and each plugin's version and migration head are in
the PROJECT-MAP page in the project wiki, which is generated:
- **backups** - Per-asset configuration backups (NTLARS/DNC, CMM, part marker, UDC) with revision history and diffs
- **computers** - Shopfloor PCs and workstations, collector fleet ingest
- **endpoints** - RMM telemetry from the ShopDB agent: metrics, services, inventory, Windows events
- **guides** - Step-by-step procedures with images, working checklists and printable output
- **knowledgebase** - Documentation and troubleshooting articles
- **machines** - CNC, CMM, and other shop-floor machines
- **network** - Network devices and subnets
- **notifications** - Shopfloor notifications. The employee-facing types (recognition, training, recertification) need the employees plugin, which this image does not bundle
- **printers** - Extended printer management with Zabbix integration
- **slides** - Lobby display and shopfloor screensaver slideshows
- **tools** - Tech Tools: barcode/QR label generation and one-view secure send
- **warranty** - Warranty records with derived coverage status
Applications is not in that list because it is not a plugin: it is core, has no
manifest, and always ships.
## 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.