- 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
13 KiB
13 KiB
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
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
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
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
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
interface METRCLocation {
Id: number; // → metrcLocationId
Name: string; // → metrcLocationName
LocationTypeName: string; // → type inference
}
Harvest → Our Weight Log
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
<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
<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
<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
// 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
// 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
// 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
// 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
# 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 batchesplantbatches- Read/Write batch operationsharvests- Read/Write harvest datapackages- Read package informationlocations- Read location datalabresults- 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)
- Add METRC ID fields to schema
- 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
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 |