main was 16 days and 259 commits behind the line the product is actually built on, at contract 0.30.0 against 0.35.0, with no per-PC credential code at all. It was neither current nor curated - just stale. This brings it forward and, at the same time, makes it mean something: main is what a receiving site installs, and nothing else. WHAT IT CARRIES. Twelve plugins - backups, computers, endpoints, guides, knowledgebase, machines, network, notifications, printers, slides, tools, warranty - plus applications, which is manifest-less core and always ships. The only manifest dependency inside that set is endpoints on computers, and both are in it, so the closure is self-contained. WHAT IT DOES NOT. employees, geenforce, measuringtools, printedparts and usb stay on the site line. So do the Windows installer tree, the VM rehearsal helpers, the agent tooling config, one site's data loader, the internal audit and findings records, and the planner spreadsheet. 1,135 tracked files against 1,438. A REMOVAL THAT BREAKS THE APP IS NOT A REMOVAL, and two nearly shipped: deploy/site-profile-universal.json still named all seventeen plugins. It is the file docs/DEPLOY.md tells a site to provision from, so a fresh install would have failed at `flask plugin apply-profile` with PluginError - the first thing a receiving site does, broken by the branch meant to serve them. It now names the twelve that exist, and its comment says the two must agree. agent/ was never refreshed. Whoever populated this branch copied shopdb/, plugins/, frontend/ and tests/ from the site line and left the agent tree at its September state: 22 C# and PowerShell sources missing, including AgentCredentials, EnrollmentService, AgentHttpFactory and the fleet-alert client, plus one file the site line had deleted still present. The old tree is internally consistent, so it compiles, and nothing in CI builds it - every gate was green over a server that speaks enrollment and per-PC credentials to a bundled agent source that cannot. Resynced whole. DECISIONS THIS ENCODES, rather than defers: - The plugin-authoring lab builds printedparts, whose manifest depends on employees, so it could not stay. The lab remains on the site line and main ships no build-along tutorial. That is a real loss for an adopting developer and is recorded here rather than discovered later. - Recognition, Training and Recertification notifications are no longer seeded. Each splits one notification into a card per employee and renders a photo, which needs a plugin this branch does not bundle. Seeding them would offer an author a type that cannot resolve anybody. A site that installs employees gets them from that plugin's own seed. - Windows/IIS is documented as the legacy path throughout, and the README leads with Docker, because that is what a receiving site gets. The API description is regenerated for THIS branch - 347 paths and 483 operations, down from 415 and 573 - so the published contract describes what is here rather than what the site line serves. docs/CONFIG.md lost the two measuring-tool label keys the code no longer declares, which two lanes had decided opposite ways. Suite: 3124 passed, 6 skipped. Naming and style gates pass. The docs gates run rather than skip, and every index line count is derived from the file it names.
272 lines
10 KiB
Markdown
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 and recognition feed
|
|
- **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.
|
|
|
|
### 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.
|
|
|
|
```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 and recognition feed
|
|
- **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.
|