ca-grow-ops-manager/docs/LAYOUT-DESIGNER-SPEC.md
fullsizemalt 32fd739ccf
Some checks failed
Deploy to Production / deploy (push) Failing after 0s
Test / backend-test (push) Failing after 0s
Test / frontend-test (push) Failing after 0s
feat: Complete Phases 8-13 implementation
Phase 8: Visitor Management
- Visitor/VisitorLog/AccessZone models
- Check-in/out with badge generation
- Zone occupancy tracking
- Kiosk and management pages

Phase 9: Messaging & Communication
- Announcements with priority levels
- Acknowledgement tracking
- Shift notes for team handoffs
- AnnouncementBanner component

Phase 10: Compliance & Audit Trail
- Immutable AuditLog model
- Document versioning and approval workflow
- Acknowledgement tracking for SOPs
- CSV export for audit logs

Phase 11: Accessibility & i18n
- WCAG 2.1 AA compliance utilities
- react-i18next with EN/ES translations
- User preferences context (theme, font size, etc)
- High contrast and reduced motion support

Phase 12: Hardware Integration
- QR code generation for batches/plants/visitors
- Printable label system
- Visitor badge printing

Phase 13: Advanced Features
- Environmental monitoring (sensors, readings, alerts)
- Financial tracking (transactions, P&L reports)
- AI/ML insights (yield predictions, anomaly detection)
2025-12-11 00:26:25 -08:00

458 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Facility Layout Designer & Plant Addressing System
## 🎯 Vision
A Figma-like visual layout editor for designing facility layouts with precise plant addressing. Every plant gets a unique, hierarchical address that maps to physical location:
```
PROPERTY → BUILDING → ROOM → SECTION → ROW → COLUMN → POSITION
```
Example: `MAIN.GROW1.VEG-A.LEFT.R3.C5.P1` = Main Property, Grow Building 1, Veg Room A, Left Section, Row 3, Column 5, Position 1
---
## 📐 Data Model
```prisma
// Hierarchical Location Structure
model Property {
id String @id @default(uuid())
name String
address String?
licenseNum String? // DCC License Number
buildings Building[]
createdAt DateTime @default(now())
}
model Building {
id String @id @default(uuid())
property Property @relation(fields: [propertyId], references: [id])
propertyId String
name String // "Grow Building 1", "Processing"
code String // Short code: "GROW1"
type String // CULTIVATION, PROCESSING, DRYING, STORAGE
rooms Room[]
layout Json? // Visual layout data (x, y, width, height)
createdAt DateTime @default(now())
}
model Room {
id String @id @default(uuid())
building Building @relation(fields: [buildingId], references: [id])
buildingId String
name String
code String // "VEG-A"
type String // VEG, FLOWER, CLONE, DRY, CURE, TRIM
sections Section[]
layout Json? // Position within building
createdAt DateTime @default(now())
}
model Section {
id String @id @default(uuid())
room Room @relation(fields: [roomId], references: [id])
roomId String
name String // "Left Side", "Center Aisle"
code String // "LEFT", "CENTER"
type String // FLOOR, TABLE, RACK, HANGER, TRAY
rows Row[]
layout Json? // Position within room, dimensions
createdAt DateTime @default(now())
}
model Row {
id String @id @default(uuid())
section Section @relation(fields: [sectionId], references: [id])
sectionId String
number Int // Row 1, 2, 3...
positions Position[]
layout Json? // Position within section
}
model Position {
id String @id @default(uuid())
row Row @relation(fields: [rowId], references: [id])
rowId String
column Int // Column number
slot Int @default(1) // For multi-plant positions
plant Plant? @relation(fields: [plantId], references: [id])
plantId String? @unique
status String @default("EMPTY") // EMPTY, OCCUPIED, RESERVED, DAMAGED
}
model Plant {
id String @id @default(uuid())
tagNumber String @unique // METRC tag
batch Batch @relation(fields: [batchId], references: [id])
batchId String
position Position?
address String // Full hierarchical address
status String // ACTIVE, HARVESTED, DESTROYED, TRANSFERRED
history PlantLocationHistory[]
createdAt DateTime @default(now())
}
model PlantLocationHistory {
id String @id @default(uuid())
plant Plant @relation(fields: [plantId], references: [id])
plantId String
fromAddress String?
toAddress String
movedBy String // User ID
movedAt DateTime @default(now())
reason String? // TRANSPLANT, REORGANIZE, HARVEST
}
```
---
## 🎨 Layout Editor UI
### Canvas Features (Figma-like)
- **Drag & Drop** - Add rooms, sections, rows to canvas
- **Resize Handles** - Adjust dimensions
- **Grid Snap** - Align to grid
- **Zoom & Pan** - Navigate large layouts
- **Layers** - Show/hide different elements
- **Templates** - Pre-built room layouts
### Element Types
#### 1. Floor Plan Elements
```
┌─────────────────────────────────────────────────────────┐
│ BUILDING: Grow 1 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ VEG ROOM A │ │ VEG ROOM B │ │
│ │ ┌───┬───┬───┐ │ │ │ │
│ │ │ T1│ T2│ T3│ │ │ │ │
│ │ ├───┼───┼───┤ │ │ │ │
│ │ │ T4│ T5│ T6│ │ │ │ │
│ │ └───┴───┴───┘ │ │ │ │
│ └─────────────────┘ └─────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ FLOWER ROOM A │ │
│ │ [====] [====] [====] [====] │ 4 ft aisles │
│ │ [====] [====] [====] [====] │ │
│ │ [====] [====] [====] [====] │ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
#### 2. Grow Table/Bed (Grid-based)
```
┌────────────────────────────────────────┐
│ TABLE T1 - VEG-A.LEFT.T1 │
│ Capacity: 6 rows × 8 columns = 48 │
│ ┌──┬──┬──┬──┬──┬──┬──┬──┐ │
│ │🌱│🌱│🌱│🌱│🌱│🌱│🌱│🌱│ R1 │
│ ├──┼──┼──┼──┼──┼──┼──┼──┤ │
│ │🌱│🌱│🌱│🌱│ │ │🌱│🌱│ R2 │
│ ├──┼──┼──┼──┼──┼──┼──┼──┤ │
│ │🌱│🌱│🌱│🌱│🌱│🌱│🌱│🌱│ R3 │
│ ├──┼──┼──┼──┼──┼──┼──┼──┤ │
│ │ │ │ │ │ │ │ │ │ R4 (empty) │
│ └──┴──┴──┴──┴──┴──┴──┴──┘ │
│ C1 C2 C3 C4 C5 C6 C7 C8 │
└────────────────────────────────────────┘
```
#### 3. Drying Rack (Hanger-based)
```
┌────────────────────────────────────────┐
│ DRY RACK 1 - DRY.MAIN.RACK1 │
│ Type: Vertical Hangers │
│ │
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
│ │H1│ │H2│ │H3│ │H4│ │H5│ │H6│ Level 1│
│ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ │
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
│ │H1│ │H2│ │H3│ │H4│ │H5│ │H6│ Level 2│
│ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ │
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
│ │H1│ │H2│ │H3│ │H4│ │H5│ │ │ Level 3│
│ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ │
└────────────────────────────────────────┘
```
---
## 🔧 API Endpoints
### Layout Management
```
POST /api/layout/property
POST /api/layout/building
POST /api/layout/room
POST /api/layout/section
POST /api/layout/row
PUT /api/layout/:entityType/:id
DELETE /api/layout/:entityType/:id
GET /api/layout/property/:id/full # Full hierarchy
GET /api/layout/room/:id/positions # All positions with status
```
### Plant Placement
```
POST /api/plants
Body: { tagNumber, batchId, positionId }
POST /api/plants/:id/move
Body: { toPositionId, reason }
POST /api/plants/bulk-place
Body: { batchId, positionIds[] } # Place batch into positions
GET /api/plants/by-address/:address # Lookup by address string
```
### Position Status
```
GET /api/positions/available
Query: ?roomId=x&count=48 # Find 48 available positions
POST /api/positions/reserve
Body: { positionIds[], batchId, until }
GET /api/rooms/:id/occupancy
Returns: { total, occupied, empty, reserved }
```
---
## 🎯 METRC Integration Requirements
### Address Format for METRC
METRC requires precise location tracking. Our address format maps to:
| Our Field | METRC Field |
|-----------|-------------|
| Property | License Premises |
| Building | Area |
| Room | Room |
| Section + Row + Column | Location (free text) |
### Sync Strategy
```
1. Plant created → Sync to METRC with location
2. Plant moved → Update METRC location
3. Plant harvested → Report harvest location
4. Audit → Generate location report matching METRC
```
---
## 🖥️ Frontend Components
### 1. LayoutEditor (Canvas)
```tsx
interface LayoutEditorProps {
propertyId: string;
mode: 'view' | 'edit';
onSave?: (layout: Layout) => void;
}
// Uses react-konva or @tldraw/tldraw for canvas
<LayoutEditor
propertyId={propertyId}
mode="edit"
onSave={handleSave}
/>
```
### 2. RoomGrid (Position Grid)
```tsx
interface RoomGridProps {
roomId: string;
onPositionClick?: (position: Position) => void;
selectedBatch?: string; // Highlight batch plants
}
<RoomGrid
roomId={roomId}
selectedBatch={batchId}
onPositionClick={(pos) => showPlantDetails(pos.plant)}
/>
```
### 3. PlantPlacer (Batch Placement Tool)
```tsx
interface PlantPlacerProps {
batchId: string;
plantCount: number;
onComplete: (placements: Placement[]) => void;
}
// Select multiple positions to place plants
<PlantPlacer
batchId={batch.id}
plantCount={48}
onComplete={handlePlacement}
/>
```
### 4. AddressLookup (Quick Find)
```tsx
// Scan or type address to jump to location
<AddressLookup
onFound={(plant) => navigateToPlant(plant)}
/>
// Input: "MAIN.GROW1.VEG-A.LEFT.R3.C5"
// Output: Highlights position, shows plant details
```
---
## 📱 Mobile Flow
1. **Scan Plant Tag** → Shows current position + batch info
2. **Move Plant** → Scan new position QR → Confirm move
3. **Quick Place** → Scan batch → Scan position → Repeat
4. **Audit Walk** → Show expected vs actual by position
---
## 🗓️ Implementation Phases
### Phase 1: Data Model & API (1 week)
- [ ] Create Prisma models
- [ ] Migrate database
- [ ] Build CRUD endpoints
- [ ] Address generation logic
### Phase 2: Basic Layout Editor (2 weeks)
- [ ] Canvas with react-konva
- [ ] Add/edit rooms, sections
- [ ] Grid generator for positions
- [ ] Save/load layouts
### Phase 3: Plant Placement (1 week)
- [ ] Place plants in positions
- [ ] Move plants (with history)
- [ ] Bulk placement tool
- [ ] Position reservation
### Phase 4: Visualization (1 week)
- [ ] Room grid view
- [ ] Color coding (by batch, stage, health)
- [ ] Occupancy heatmaps
- [ ] Print floor plans
### Phase 5: METRC Sync (2 weeks)
- [ ] Location format mapping
- [ ] Sync on plant create/move
- [ ] Audit report generation
- [ ] Discrepancy detection
---
## 📦 Tech Stack
| Component | Technology |
|-----------|------------|
| Canvas Editor | `react-konva` or `@tldraw/tldraw` |
| Grid Display | Custom React + CSS Grid |
| Address Parser | Regex + validation |
| QR Codes | `qrcode.react` |
| Mobile Scan | `@zxing/browser` |
| State Mgmt | Zustand (for editor state) |
---
## 🎨 Example Layouts
### Vegetative Room - Tables
```json
{
"type": "ROOM",
"code": "VEG-A",
"layout": {
"width": 40, // feet
"height": 30,
"sections": [
{
"code": "LEFT",
"type": "TABLE",
"x": 0, "y": 0,
"rows": 6,
"columns": 8,
"spacing": 12 // inches between plants
},
{
"code": "RIGHT",
"type": "TABLE",
"x": 20, "y": 0,
"rows": 6,
"columns": 8
}
],
"aisles": [
{ "x": 18, "y": 0, "width": 4, "height": 30 }
]
}
}
```
### Drying Room - Racks
```json
{
"type": "ROOM",
"code": "DRY-A",
"layout": {
"width": 20,
"height": 30,
"sections": [
{
"code": "RACK1",
"type": "HANGER",
"x": 0, "y": 0,
"levels": 4,
"hangersPerLevel": 20
},
{
"code": "RACK2",
"type": "HANGER",
"x": 10, "y": 0,
"levels": 4,
"hangersPerLevel": 20
}
]
}
}
```
---
## ✅ Deliverables
1. **Prisma schema** with full hierarchy
2. **API endpoints** for CRUD + plant placement
3. **Layout Editor** component (Figma-like)
4. **Room Grid Viewer** with plant status
5. **Mobile placement flow** with scanning
6. **METRC-compatible address format**
7. **Audit reports** by location