# 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
```
### 2. RoomGrid (Position Grid)
```tsx
interface RoomGridProps {
roomId: string;
onPositionClick?: (position: Position) => void;
selectedBatch?: string; // Highlight batch plants
}
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
```
### 4. AddressLookup (Quick Find)
```tsx
// Scan or type address to jump to location
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