The equipment plugin is now the machines plugin, ending the UI-vs-code vocabulary split while the contract is pre-1.0 and nothing external depends on the old names. - plugins/equipment -> plugins/machines: manifest, class, /api/machines, machines.* permissions, registry key (with an auto-migrating load shim for existing installs). - Tables: equipment -> machines (equipmentid -> machineid) and equipmenttypes -> machinetypes, renamed in the plugin's own migration chain (machines0002rename), idempotent for both upgrading and fresh installs. - The legacy core machinetypes lookup actually types the vendor MODELS catalog, so it is renamed losslessly to modeltypes (models.modeltypeid, /api/modeltypes, Model Types settings page) rather than collapsed, freeing the machinetypes name. Core migration 7d17_machines_rename also flips data in place: assettypes row equipment -> machine, auditlog entitytype, identifier_/search_ settings keys, permission rows, and renames alembic_version_equipment. - Frontend: machinesApi/modeltypesApi, item.machine response shape, assettype value compares 'equipment' -> 'machine' (map, search, custom fields, relationships), routes machines.js with plugin gating retagged, /print/machine-badge, Machine Types (subtypes) and Model Types (catalog) settings pages, machines-by-type report id. - Docs swept; ADRs left as history per the authoring rule. Upgrade: flask db upgrade then flask plugin upgrade-all. Verified: dev DB flipped live (262 machines, 35 modeltypes, 95 models retyped, zero equipment tables remain); fresh scratch-MySQL install produces the new names; 341 tests green; naming/style green; frontend builds; live E2E on machines list/detail, PC relationships, map, reports, and both settings pages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
130 lines
6.0 KiB
Markdown
130 lines
6.0 KiB
Markdown
# ShopDB Flask Project
|
|
|
|
Modern rewrite of the classic-ASP shopdb. Built as a framework so sister GE Aerospace sites can adopt it. Plugin system is the product.
|
|
|
|
## Database
|
|
|
|
- **Active database:** `shopdb_flask` (MySQL, asset-based schema)
|
|
- **Legacy database:** `shopdb` (Classic ASP schema, used only for one-time data import via `scripts/import_from_mysql.py`)
|
|
- **Connection:** `.env` file. See `.env.example`.
|
|
|
|
Architecture decisions live in `docs/adr/`. Read those before making schema or contract changes.
|
|
|
|
- ADR-001: Asset model is the platform contract (Machine retires) - ACCEPTED
|
|
- ADR-002: Plugin contract versioning (semver) - ACCEPTED
|
|
- ADR-003: Plugin distribution model (in-tree bundled + filesystem-based external) - ACCEPTED
|
|
- ADR-004: Deployment topology (per-site instances, not multi-tenant) - ACCEPTED
|
|
- ADR-005: Equipment vs measuringtools plugin scope - ACCEPTED
|
|
- ADR-006: Plugin collector contract pattern - ACCEPTED
|
|
|
|
## Coding convention
|
|
|
|
`CONTRIBUTING.md` defines naming rules (DB tables, columns, Python, JS, Vue, API). Pre-commit hook at `scripts/check-naming-and-style.sh` enforces them. Read `CONTRIBUTING.md` before naming any new identifier.
|
|
|
|
## Current state (as of 2026-07-10)
|
|
|
|
Refactor phases 0-5 landed; phase 6 (multi-site distribution readiness) in progress.
|
|
|
|
### Phases done
|
|
|
|
- **Phase 0**: 6 ADRs accepted, naming convention v1, pre-commit style hook
|
|
- **Phase 1**: 8 smoke tests + 7 production-config tests, Flask-SQLAlchemy 3 fixtures, uv lockfile, hardened ProductionConfig
|
|
- **Phase 2**: contract surface defined (`__contract_version__`, `BasePlugin` hooks, `docs/PLUGIN-HOOKS.md`), 51 contract tests
|
|
- **Phase 3**: manifest-first loader, fail-loud/isolate policy, contract-version range checking, auto-register core blueprints, `shopdb.api` namespace, `BasePlugin.get_setting/set_setting` helpers
|
|
- **Phase 4**: `flask plugin new <name>` CLI, scaffold templates, 14 canary tests, `docs/PLUGIN-QUICKSTART.md`
|
|
- **Phase 5**: ADRs moved to `docs/adr/`, Alembic baseline migration, per-site deploy artifacts (`Dockerfile`, `docker-compose.yml`, `docs/DEPLOY.md`)
|
|
|
|
### Active state
|
|
|
|
- 340 tests passing, naming/style check green, Gitea Actions CI (backend + naming + frontend build)
|
|
- `__contract_version__` at 0.6.0 (product `__version__` 0.5.0 - distinct series, ADR-007)
|
|
- 11 bundled plugins all satisfy contract: computers, employees, knowledgebase, machines, measuringtools, network, notifications, printers, slides, usb, warranty
|
|
- Single core Alembic chain: baseline `68b3947ae14f` -> head `7d16_directoryemployees` (23 migrations). A fresh site runs `flask db upgrade` from empty; it is reproducible and idempotent.
|
|
- Pre-1.0 framework; sister sites should pin tight `core_version` ranges until contract reaches 1.0
|
|
|
|
### Deferred
|
|
|
|
- Equipment data migration (one-shot script for legacy ASP shopdb -> assets). Per ADR-001, only `category='Equipment' AND machinenumber IS NOT NULL` migrates. Skill `migrating-asset-schema` documents the pattern; the actual one-shot script lives in `scripts/migration/` when run.
|
|
- Printers retirement: legacy `PrinterData` model + frontend changes. Coordinated with the equipment data migration.
|
|
- (DONE 2026-07-11) `measuringtools` plugin (ADR-005) is built and bundled; docs/PLUGIN-GUIDE.md narrates its construction as the plugin tutorial.
|
|
- Frontend hook contract for asset-detail, map markers, search results
|
|
- Alembic per-plugin migration chains (the framework supports them; bundled plugins haven't moved off `db.create_all()` yet)
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
# Start dev environment
|
|
~/start-dev-env.sh
|
|
|
|
# Activate venv and install deps
|
|
cd /home/camp/projects/shopdb-flask
|
|
source venv/bin/activate
|
|
pip install -r requirements.txt
|
|
|
|
# Configure environment
|
|
cp .env.example .env
|
|
# Edit .env with DB credentials, JWT secrets
|
|
|
|
# Create / update database tables via the Alembic chain
|
|
flask db upgrade
|
|
|
|
# Seed RBAC, default settings, and reference data (all idempotent)
|
|
flask seed permissions
|
|
flask seed settings
|
|
flask seed reference-data
|
|
|
|
# Restart services
|
|
pm2 restart shopdb-flask-api shopdb-flask-ui
|
|
```
|
|
|
|
## Service URLs
|
|
|
|
- Flask API: http://localhost:5001
|
|
- Flask UI: http://localhost:5173
|
|
- Legacy ASP (data source for one-time import): http://192.168.122.151:8080
|
|
|
|
## Plugin structure
|
|
|
|
```
|
|
plugins/
|
|
<plugin_name>/
|
|
__init__.py
|
|
plugin.py # BasePlugin implementation
|
|
manifest.json # Plugin metadata (name, version, dependencies, api_prefix)
|
|
models/
|
|
__init__.py # Export all models
|
|
<model>.py # SQLAlchemy models
|
|
api/
|
|
__init__.py
|
|
routes.py # Flask Blueprint
|
|
services/ # Optional, business logic
|
|
schemas/ # Optional, marshmallow schemas
|
|
migrations/ # Optional, plugin-specific Alembic migrations
|
|
```
|
|
|
|
Each plugin must have:
|
|
|
|
- `models/__init__.py` exports all models
|
|
- `plugin.py` extends `BasePlugin`
|
|
- `manifest.json` with metadata (single source of truth per ADR-002)
|
|
- No direct imports from core code (use the contract surface defined in ADR-001)
|
|
|
|
## Key files
|
|
|
|
- `shopdb/__init__.py` - app factory, blueprint registration
|
|
- `shopdb/plugins/base.py` - BasePlugin ABC, PluginMeta dataclass
|
|
- `shopdb/plugins/loader.py` - filesystem discovery, dependency-aware loading
|
|
- `shopdb/core/api/assets.py` - example of optional plugin imports
|
|
- `frontend/src/router/index.js` - frontend routing
|
|
- `frontend/src/components/AppSidebar.vue` - navigation menu
|
|
- `docs/adr/` - architecture decision records
|
|
|
|
## Migration notes
|
|
|
|
- `migrations/DATA_MIGRATION_GUIDE.md` - one-time import from legacy ASP shopdb
|
|
- `migrations/MIGRATE_USB_DEVICES_FROM_EQUIPMENT.md` - USB device migration from equipment table
|
|
- `migrations/FIX_LOCATIONONLY_EQUIPMENT_TYPES.md` - LocationOnly equipment type fix
|
|
- `migrations/PRODUCTION_MIGRATION_GUIDE.md` - production import methods
|
|
- `migrations/rename_underscore_columns.sql` - one-time rename of snake_case columns to lowercase concatenated (per CONTRIBUTING.md)
|
|
- `migrations/versions/` - the core Alembic chain (baseline `68b3947ae14f` -> head `7d16_directoryemployees`). Run `flask db upgrade` to apply.
|