Add print badges, pagination, route splitting, JWT auth fixes, and list page alignment

- Fix equipment badge barcode not rendering (loading race condition)
- Fix printer QR code not rendering on initial load (same race condition)
- Add model image to equipment badge via imageurl from Model table
- Fix white-on-white machine number text on badge, tighten barcode spacing
- Add PaginationBar component used across all list pages
- Split monolithic router into per-plugin route modules
- Fix 25 GET API endpoints returning 401 (jwt_required -> optional=True)
- Align list page columns across Equipment, PCs, and Network pages
- Add print views: EquipmentBadge, PrinterQRSingle, PrinterQRBatch, USBLabelBatch
- Add PC Relationships report, migration docs, and CLAUDE.md project guide
- Various plugin model, API, and frontend refinements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-02-04 07:32:44 -05:00
parent c4bfdc2db2
commit 9efdb5f52d
89 changed files with 3951 additions and 1138 deletions

View File

@@ -0,0 +1,165 @@
# Production Migration Guide
## Overview
This guide documents the process for migrating data from the legacy VBScript ShopDB site to the new Flask-based ShopDB.
## Database Architecture
### Legacy System (VBScript)
- Single `machines` table containing all equipment, PCs, printers
- `machinetypes` table for classification
- `models` table with `machinetypeid` reference
### New System (Flask)
- Core `assets` table (unified asset registry)
- Plugin-specific extension tables:
- `equipment` (equipmenttypeid → equipmenttypes)
- `computers` (computertypeid → computertypes)
- `printers` (printertypeid → printertypes)
- `network_device` (networkdevicetypeid → networkdevicetypes)
## Key Mappings
### Asset Type Mapping
| Legacy Category | New Asset Type | Extension Table |
|-----------------|---------------|-----------------|
| Equipment machines | Equipment | equipment |
| PC/Computer | Computer | computers |
| Printer | Printer | printers |
| Network (IDF, Switch, AP) | Network Device | network_device |
### Type ID Alignment
The `equipmenttypes` table IDs match `machinetypes` IDs for easy migration:
- equipmenttypeid = machinetypeid (where applicable)
## Migration Steps
### Step 1: Export from Legacy Database
```sql
-- Export machines with all related data
SELECT
m.*,
mt.machinetype,
mo.modelnumber,
mo.machinetypeid as model_typeid,
v.vendor,
bu.businessunit,
s.status
FROM machines m
LEFT JOIN machinetypes mt ON mt.machinetypeid = m.machinetypeid
LEFT JOIN models mo ON mo.modelnumberid = m.modelnumberid
LEFT JOIN vendors v ON v.vendorid = m.vendorid
LEFT JOIN businessunits bu ON bu.businessunitid = m.businessunitid
LEFT JOIN statuses s ON s.statusid = m.statusid;
```
### Step 2: Create Assets
For each machine, create an asset record:
```sql
INSERT INTO assets (assetnumber, name, assettypeid, statusid, locationid, businessunitid, mapleft, maptop)
SELECT
CONCAT(machinenumber, '-', machineid), -- Unique asset number
alias,
CASE
WHEN category = 'PC' THEN 2 -- Computer
WHEN category = 'Printer' THEN 4 -- Printer
ELSE 1 -- Equipment
END,
statusid,
locationid,
businessunitid,
mapleft,
maptop
FROM machines;
```
### Step 3: Create Extension Records
```sql
-- For Equipment
INSERT INTO equipment (assetid, equipmenttypeid, vendorid, modelnumberid)
SELECT
a.assetid,
COALESCE(mo.machinetypeid, m.machinetypeid), -- Use model's type if available!
m.vendorid,
m.modelnumberid
FROM machines m
JOIN assets a ON a.assetnumber = CONCAT(m.machinenumber, '-', m.machineid)
LEFT JOIN models mo ON mo.modelnumberid = m.modelnumberid
WHERE m.category = 'Equipment' OR m.category IS NULL;
```
### Step 4: Post-Migration Fixes
#### Fix LocationOnly Equipment Types
Equipment imported with LocationOnly type should inherit type from their model:
```sql
-- Fix equipment that has a model with a proper type
UPDATE equipment e
JOIN assets a ON a.assetid = e.assetid
JOIN machines m ON m.machinenumber = SUBSTRING_INDEX(a.assetnumber, '-', 1)
JOIN models mo ON mo.modelnumberid = m.modelnumberid
SET e.equipmenttypeid = mo.machinetypeid
WHERE e.equipmenttypeid = 1 -- LocationOnly
AND mo.machinetypeid != 1; -- Model has real type
```
## Validation Queries
### Check for Orphaned Assets
```sql
SELECT a.* FROM assets a
LEFT JOIN equipment e ON e.assetid = a.assetid
LEFT JOIN computers c ON c.assetid = a.assetid
LEFT JOIN printers p ON p.assetid = a.assetid
WHERE a.assettypeid = 1 -- Equipment type
AND e.assetid IS NULL;
```
### Check LocationOnly with Models
```sql
-- Should return 0 after migration fix
SELECT COUNT(*)
FROM equipment e
JOIN assets a ON a.assetid = e.assetid
JOIN machines m ON m.machinenumber = SUBSTRING_INDEX(a.assetnumber, '-', 1)
JOIN models mo ON mo.modelnumberid = m.modelnumberid
WHERE e.equipmenttypeid = 1
AND mo.machinetypeid != 1;
```
### Verify Type Distribution
```sql
SELECT et.equipmenttype, COUNT(*) as count
FROM equipment e
JOIN equipmenttypes et ON et.equipmenttypeid = e.equipmenttypeid
GROUP BY et.equipmenttype
ORDER BY count DESC;
```
## Common Issues
### Issue: Equipment marked as LocationOnly but has model
**Cause**: Migration copied machinetypeid from machines table instead of using model's type
**Fix**: See FIX_LOCATIONONLY_EQUIPMENT_TYPES.md
### Issue: Missing model relationship
**Cause**: Equipment table modelnumberid not populated during migration
**Fix**: Link through machines table using asset number pattern
### Issue: Duplicate asset numbers
**Cause**: Asset number generation didn't account for existing duplicates
**Fix**: Use unique suffix or check before insert
## Scripts Location
- `/migrations/FIX_LOCATIONONLY_EQUIPMENT_TYPES.md` - Fix for LocationOnly type issue
- `/scripts/import_from_mysql.py` - Original import script (may need updates)
- `/scripts/migration/` - Migration utilities
## Notes
- Always backup before running migration fixes
- Test on staging/dev before production
- Verify counts before and after each fix
- Keep legacy `machines` table for reference during transition
## Date Created
2026-01-27