- Clarifies METRC as source of truth - Defines data model with metrc fields - Feature overlap matrix (supplement vs add value) - UI integration points - Compliance alerts workflow - Implementation phases
451 lines
13 KiB
Markdown
451 lines
13 KiB
Markdown
# METRC Integration Specification
|
|
|
|
## Overview
|
|
|
|
This document defines how CA Grow Ops Manager integrates with California's METRC (Metrc LLC) track-and-trace system. METRC compliance is **mandatory** for all licensed cannabis operations in California.
|
|
|
|
> **Critical Note**: Our application is a **supplementary management tool** that works alongside METRC, NOT a replacement. All legally required data MUST be entered into METRC according to DCC regulations.
|
|
|
|
---
|
|
|
|
## Integration Approach
|
|
|
|
### Philosophy: METRC as Source of Truth
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ METRC (State System) │
|
|
│ ═══ SOURCE OF TRUTH ═══ │
|
|
│ • Official plant/package tracking │
|
|
│ • State compliance reporting │
|
|
│ • Manifests & transfers │
|
|
│ • Required weight logs │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
▲ ▲
|
|
SYNC ────┘ └──── SYNC
|
|
│
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ CA Grow Ops Manager │
|
|
│ ═══ OPERATIONAL LAYER ═══ │
|
|
│ • Enhanced day-to-day management │
|
|
│ • Photo documentation │
|
|
│ • Staff scheduling & timekeeping │
|
|
│ • IPM tracking & analytics │
|
|
│ • SOPs & training │
|
|
│ • Real-time environment monitoring │
|
|
│ • Facility 3D visualization │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Integration Levels
|
|
|
|
| Level | Description | Implementation |
|
|
|-------|-------------|----------------|
|
|
| **L1: Reference** | Store METRC IDs for cross-reference | ✅ Implemented |
|
|
| **L2: Sync (Read)** | Pull data from METRC API | 🔄 Planned |
|
|
| **L3: Sync (Write)** | Push data to METRC API | 🔄 Planned |
|
|
| **L4: Real-time** | Live bi-directional sync | 🔮 Future |
|
|
|
|
---
|
|
|
|
## Data Model: METRC Fields
|
|
|
|
### Batch Model
|
|
|
|
```prisma
|
|
model Batch {
|
|
// ... existing fields ...
|
|
|
|
// METRC Integration
|
|
metrcPlantBatchId String? // METRC Plant Batch ID
|
|
metrcGroupId String? // METRC Group ID
|
|
metrcLicenseNumber String? // Source license
|
|
metrcSyncedAt DateTime? // Last sync timestamp
|
|
metrcSyncStatus METRCSyncStatus @default(NOT_SYNCED)
|
|
}
|
|
|
|
enum METRCSyncStatus {
|
|
NOT_SYNCED
|
|
SYNCING
|
|
SYNCED
|
|
SYNC_ERROR
|
|
MANUAL_OVERRIDE
|
|
}
|
|
```
|
|
|
|
### Weight Log Model
|
|
|
|
```prisma
|
|
model WeightLog {
|
|
// ... existing fields ...
|
|
|
|
metrcHarvestId String? // METRC Harvest ID
|
|
metrcPackageId String? // METRC Package ID
|
|
metrcWasteId String? // METRC Waste event ID
|
|
metrcReported Boolean @default(false)
|
|
metrcReportedAt DateTime?
|
|
}
|
|
```
|
|
|
|
### Room Model
|
|
|
|
```prisma
|
|
model Room {
|
|
// ... existing fields ...
|
|
|
|
metrcLocationId String? // METRC Location ID
|
|
metrcLocationName String? // METRC Location Name
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Feature Overlap Matrix
|
|
|
|
### Where We SUPPLEMENT METRC
|
|
|
|
| Feature | METRC Does | We Do | Integration |
|
|
|---------|------------|-------|-------------|
|
|
| **Plant Tracking** | Official counts, tags | Daily observations, photos | Link via `metrcPlantBatchId` |
|
|
| **Weight Logging** | Legal wet/dry weights | Operational weights, notes | Push to METRC, store locally |
|
|
| **Transfers** | Manifests, chain of custody | Prep checklists, photos | Reference `metrcManifestId` |
|
|
| **Waste** | Waste disposal logging | Waste tracking triggers | Push to METRC on disposal |
|
|
| **Room Location** | Official location names | Visual layout, sensors | Link via `metrcLocationId` |
|
|
|
|
### Where We ADD VALUE (Not in METRC)
|
|
|
|
| Feature | What We Provide |
|
|
|---------|-----------------|
|
|
| **Daily Walkthroughs** | Structured inspections with photos |
|
|
| **IPM Schedules** | Preventive pest management tracking |
|
|
| **Touch Points** | Granular activity logging (feed, water, prune) |
|
|
| **Environment Data** | VPD, temperature, humidity trends |
|
|
| **Staff Management** | Time clock, task assignment |
|
|
| **SOPs & Training** | Document management, acknowledgments |
|
|
| **Visitor Management** | Check-in, NDA tracking |
|
|
| **3D Visualization** | Facility layout, sensor placement |
|
|
| **Financial Tracking** | Labor costs, supply expenses |
|
|
| **Analytics** | Yield predictions, efficiency reports |
|
|
|
|
---
|
|
|
|
## METRC Data Mapping
|
|
|
|
### Plant Batch → Our Batch
|
|
|
|
```typescript
|
|
interface METRCPlantBatch {
|
|
Id: number; // → metrcPlantBatchId
|
|
Name: string; // → strain + batch code comparison
|
|
PlantCount: number; // → plantCount (validate)
|
|
RoomName: string; // → room.metrcLocationName
|
|
StrainName: string; // → strain
|
|
PlantedDate: string; // → startDate
|
|
TrackedDate: string; // Reference
|
|
GrowthPhase: string; // → stage mapping
|
|
}
|
|
|
|
// Stage Mapping
|
|
const METRC_TO_STAGE = {
|
|
'Immature': 'CLONE_IN',
|
|
'Vegetative': 'VEGETATIVE',
|
|
'Flowering': 'FLOWERING',
|
|
'InactiveImmature': 'FINISHED',
|
|
'InactiveVegetative': 'FINISHED',
|
|
'InactiveFlowering': 'FINISHED',
|
|
};
|
|
```
|
|
|
|
### Location → Our Room
|
|
|
|
```typescript
|
|
interface METRCLocation {
|
|
Id: number; // → metrcLocationId
|
|
Name: string; // → metrcLocationName
|
|
LocationTypeName: string; // → type inference
|
|
}
|
|
```
|
|
|
|
### Harvest → Our Weight Log
|
|
|
|
```typescript
|
|
interface METRCHarvest {
|
|
Id: number; // → metrcHarvestId
|
|
HarvestName: string; // Reference
|
|
WetWeight: number; // → weight (WET type)
|
|
DryWeight: number; // → weight (FINAL_DRY type)
|
|
UnitOfWeight: string; // → unit conversion
|
|
LabResultStatus: string; // → compliance status
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## UI Integration Points
|
|
|
|
### Batch Card
|
|
|
|
```tsx
|
|
<BatchCard>
|
|
<div className="flex items-center gap-2">
|
|
<span className="badge">B007</span>
|
|
<h3>Zkittlez</h3>
|
|
{batch.metrcPlantBatchId && (
|
|
<Badge variant="success" className="text-[10px]">
|
|
<CloudCheck size={10} />
|
|
METRC
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
{batch.metrcSyncStatus === 'SYNC_ERROR' && (
|
|
<Alert variant="warning">
|
|
METRC sync error - verify data in METRC portal
|
|
</Alert>
|
|
)}
|
|
</BatchCard>
|
|
```
|
|
|
|
### Weight Log Entry
|
|
|
|
```tsx
|
|
<WeightLogForm>
|
|
<Input label="Weight (g)" value={weight} />
|
|
<Select label="Type" options={['WET', 'FINAL_DRY', 'TRIM', 'WASTE']} />
|
|
|
|
<Divider />
|
|
|
|
<div className="metrc-section bg-yellow-50 p-3 rounded">
|
|
<h4 className="font-medium text-yellow-800">
|
|
⚠️ METRC Reporting Required
|
|
</h4>
|
|
<p className="text-sm text-yellow-700">
|
|
This weight must be reported to METRC within 24 hours.
|
|
</p>
|
|
<Checkbox
|
|
label="I will report this in METRC"
|
|
required
|
|
/>
|
|
</div>
|
|
</WeightLogForm>
|
|
```
|
|
|
|
### Room Assignment
|
|
|
|
```tsx
|
|
<RoomSelector>
|
|
<Select
|
|
label="Room"
|
|
options={rooms.map(r => ({
|
|
value: r.id,
|
|
label: r.name,
|
|
metrc: r.metrcLocationName
|
|
}))}
|
|
/>
|
|
{selectedRoom?.metrcLocationId && (
|
|
<p className="text-xs text-tertiary">
|
|
METRC Location: {selectedRoom.metrcLocationName}
|
|
</p>
|
|
)}
|
|
</RoomSelector>
|
|
```
|
|
|
|
---
|
|
|
|
## Sync Workflows
|
|
|
|
### Daily Sync Routine (Planned)
|
|
|
|
```
|
|
06:00 AM - Pull overnight data from METRC
|
|
- Compare plant counts
|
|
- Flag discrepancies
|
|
|
|
During Day - Local operations logged
|
|
- Touch points, weights, etc.
|
|
|
|
11:00 PM - Generate METRC report summary
|
|
- Show items needing METRC entry
|
|
- Export CSV if supported
|
|
```
|
|
|
|
### Manual Sync Trigger
|
|
|
|
```typescript
|
|
// API Endpoint
|
|
POST /api/metrc/sync
|
|
{
|
|
type: 'PULL' | 'PUSH' | 'VALIDATE',
|
|
scope: 'ALL' | 'BATCHES' | 'ROOMS' | 'HARVESTS',
|
|
batchIds?: string[] // Optional specific batches
|
|
}
|
|
|
|
// Response
|
|
{
|
|
status: 'SUCCESS' | 'PARTIAL' | 'FAILED',
|
|
synced: 47,
|
|
errors: 2,
|
|
discrepancies: [
|
|
{ batchId: 'xxx', field: 'plantCount', ours: 280, metrc: 278 }
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Compliance Alerts & Reminders
|
|
|
|
### Weight Reporting Alerts
|
|
|
|
```typescript
|
|
// Trigger: Weight log created without METRC ID
|
|
{
|
|
type: 'METRC_WEIGHT_PENDING',
|
|
message: 'Wet weight (42,000g) for Batch B004 needs METRC entry',
|
|
deadline: '24 hours from harvest',
|
|
action: 'Open METRC to report harvest weight'
|
|
}
|
|
```
|
|
|
|
### Plant Movement Alerts
|
|
|
|
```typescript
|
|
// Trigger: Room assignment changed
|
|
{
|
|
type: 'METRC_LOCATION_CHANGE',
|
|
message: 'Batch B002 moved to Flower Room A - update METRC location',
|
|
action: 'Record location change in METRC'
|
|
}
|
|
```
|
|
|
|
### Stage Transition Alerts
|
|
|
|
```typescript
|
|
// Trigger: Batch stage changed to FLOWERING
|
|
{
|
|
type: 'METRC_PHASE_CHANGE',
|
|
message: 'Batch B005 transitioned to Flowering - update METRC growth phase',
|
|
action: 'Change growth phase in METRC'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## API Configuration
|
|
|
|
### Environment Variables
|
|
|
|
```bash
|
|
# METRC API (when implemented)
|
|
METRC_ENABLED=false
|
|
METRC_API_URL=https://api-ca.metrc.com
|
|
METRC_VENDOR_KEY=your_vendor_api_key
|
|
METRC_USER_KEY=your_user_api_key
|
|
METRC_LICENSE_NUMBER=CCL21-0001234
|
|
|
|
# Sync Settings
|
|
METRC_AUTO_SYNC=false
|
|
METRC_SYNC_INTERVAL=6h
|
|
METRC_ALERT_PENDING_ITEMS=true
|
|
```
|
|
|
|
### Required METRC API Permissions
|
|
|
|
- `plants` - Read/Write plant batches
|
|
- `plantbatches` - Read/Write batch operations
|
|
- `harvests` - Read/Write harvest data
|
|
- `packages` - Read package information
|
|
- `locations` - Read location data
|
|
- `labresults` - Read lab test results
|
|
|
|
---
|
|
|
|
## Reporting & Audits
|
|
|
|
### METRC Compliance Report
|
|
|
|
```
|
|
Weekly METRC Sync Report - 2025-12-09 to 2025-12-15
|
|
═══════════════════════════════════════════════════
|
|
|
|
✓ Batches in METRC: 7
|
|
✓ Batches in App: 7 (100% linked)
|
|
|
|
✓ Weight entries pending METRC: 0
|
|
✓ Location changes pending: 0
|
|
✓ Phase changes pending: 0
|
|
|
|
⚠️ Discrepancies Found: 1
|
|
- Batch B001: Plant count (280 local vs 278 METRC)
|
|
Action: Verify physical count, correct appropriate system
|
|
|
|
Last Full Sync: Dec 15, 2025 at 06:00 AM
|
|
```
|
|
|
|
### Audit Trail
|
|
|
|
All METRC-related fields are immutable once synced:
|
|
|
|
- Before sync: Editable locally
|
|
- After sync: Read-only, requires override permission
|
|
- Override: Creates audit log entry with reason
|
|
|
|
---
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Reference IDs (Current)
|
|
|
|
- [x] Add METRC ID fields to schema
|
|
- [x] Display METRC sync status indicators
|
|
- [ ] Manual ID entry UI
|
|
|
|
### Phase 2: Compliance Alerts
|
|
|
|
- [ ] Pending entry reminders
|
|
- [ ] Discrepancy flagging
|
|
- [ ] Deadline tracking
|
|
|
|
### Phase 3: Read Sync
|
|
|
|
- [ ] Pull batches from METRC
|
|
- [ ] Pull locations from METRC
|
|
- [ ] Discrepancy detection
|
|
|
|
### Phase 4: Write Sync
|
|
|
|
- [ ] Push weight logs to METRC
|
|
- [ ] Push waste events to METRC
|
|
- [ ] Location change sync
|
|
|
|
### Phase 5: Real-time Integration
|
|
|
|
- [ ] Webhook support
|
|
- [ ] Live sync status
|
|
- [ ] Auto-correction suggestions
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- [METRC API Documentation](https://api-ca.metrc.com/Documentation)
|
|
- [DCC Regulations](https://cannabis.ca.gov/cannabis-laws/laws-and-regulations/)
|
|
- [METRC Training](https://www.metrc.com/california)
|
|
|
|
---
|
|
|
|
## Internal vs METRC: Quick Reference
|
|
|
|
| Need to do | METRC | Our App |
|
|
|------------|-------|---------|
|
|
| Report plant counts | ✅ Required | 📝 Reference |
|
|
| Log wet weight at harvest | ✅ Required | 📝 Mirror weight |
|
|
| Record waste disposal | ✅ Required | 📝 Track trigger |
|
|
| Create manifests | ✅ Required | ❌ Not applicable |
|
|
| Log package creation | ✅ Required | 📝 Reference |
|
|
| Log lab results | ✅ Required | 📝 Reference |
|
|
| Daily plant observations | ❌ Not tracked | ✅ Primary function |
|
|
| IPM treatments | ❌ Not tracked | ✅ Primary function |
|
|
| Staff time tracking | ❌ Not tracked | ✅ Primary function |
|
|
| Environment data | ❌ Not tracked | ✅ Primary function |
|
|
| Photo documentation | ❌ Not tracked | ✅ Primary function |
|
|
| SOPs & Training | ❌ Not tracked | ✅ Primary function |
|