ca-grow-ops-manager/specs/metrc-integration.md
fullsizemalt 9897e73de1
Some checks are pending
Deploy to Production / deploy (push) Waiting to run
Test / backend-test (push) Waiting to run
Test / frontend-test (push) Waiting to run
docs: add METRC integration specification
- 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
2025-12-12 20:52:44 -08:00

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 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)

  • 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