Skip to content

Models

Metrc Models | Cannlytics

This module contains common Metrc models.

Employee

An organization's employee or team member.

    {
        "FullName": "Keegan Skeate",
        "License": None
    }

Facility

A Facility represents a building licensed for the growing, processing, and/or selling of product. Facilities are created and have their permissions determined by a state.

{
    "HireDate": "0001-01-01",
    "IsOwner": false,
    "IsManager": true,
    "Occupations": [],
    "Name": "Cultivation LLC",
    "Alias": "Cultivation on Road St",
    "DisplayName": "Cultivation on Road St",
    "CredentialedDate": "1969-08-15",
    "SupportActivationDate": null,
    "SupportExpirationDate": null,
    "SupportLastPaidDate": null,
    "FacilityType": null,
    "License": {
        "Number": "403-X0001",
        "StartDate": "2013-06-28",
        "EndDate": "2015-12-28",
        "LicenseType": "Medical Cultivation"
    }
}

license_number property readonly

The facilities license number.

create_locations(self, names, types)

Create locations at the facility.

Parameters:

Name Type Description Default
names list

A list of location names.

required
types list

A list of location types: default, planting, or packing.

required

delete_location(self, uid)

Delete a location at the facility.

Parameters:

Name Type Description Default
uid str

The UID of a location to delete.

required

get_locations(self, uid='', action='')

Get locations at the facility.

Parameters:

Name Type Description Default
uid str

The UID of a location, takes precedent over action.

''
action str

A specific filter to apply, with options: active, types.

''

update_locations(self, ids, names, types=[])

Update locations at the facility.

Parameters:

Name Type Description Default
ids list

A list of location IDs.

required
names list

A list of location names.

required
types list

A list of location types: default, planting, or packing.

[]

Harvest

A class that represents a cannabis harvest.

A harvest batch is created and given a unique Harvest Name when plants or plant material are harvested.

A. Harvest Name – Harvests must be strain specific. The Harvest Name must be unique. It is a best practice for the harvest name to include the Strain Name and Harvest Date, but it is not required by the State.

B. Weight – The plant is weighed individually in its entirety after being cut from root ball (stem, stalk, bud/flower, leaves, trim leaves, etc.).

C. Waste – This can be recorded using multiple entries but must be reported within three days of destruction.

D. Package – Package and tag the product from the Harvest Batch (Fresh Cannabis Plant, Flower, Leaf or Kief). These packages must be strain specific.

E. Transfer – Licensee must create transfer manifest to move product to a Processor, Distributor, or Manufacturer.

F. Finish – When the Harvest Batch (HB) has been fully packaged, there should be remaining wet weight to account for moisture loss. Selecting Finish Harvest will attribute any remaining weight to moisture loss.

  1. A Harvest Batch package of Flower, Leaf, Kief or Fresh Cannabis Plant can only be created from the Harvested Tab using a single strain from plants harvested at the same time.

create_packages(self, data)

Create packages from a harvest.

Parameters:

Name Type Description Default
data list

The package data.

required

create_testing_packages(self, data)

Create testing packages from a harvest.

Parameters:

Name Type Description Default
data list

The package data.

required

finish(self)

Finish a harvest.

move(self, destination, harvest_name=None)

Move a harvest.

Parameters:

Name Type Description Default
destination str

THe name of the destination location.

required
harvest_name str

An optional harvest name.

None

remove_waste(self, weight, waste_type='Waste', uom='Grams')

Remove waste from the harvest.

Parameters:

Name Type Description Default
weight float

Required harvest weight.

required
waste_type str

The type of waste.

'Waste'
uom str

The unit of measure.

'Grams'

unfinish(self)

Unfinish a harvest.

Item

Items are used to track a licensee's inventory at a given facility. Items belong to a single facility Each item has a unique item name, category, and strain. Item Names are used for identification, so an item name should not simply be a category name. Item names are specific to the item in that package or production batch. Categories are pre-defined. The item name identifies what is in the package and categories are used for grouping similar items for reporting purposes.
An item will retain its name unless it is re-packaged.

    {
        "Id": 1,
        "Name": "Buds",
        "ProductCategoryName": "Buds",
        "ProductCategoryType": "Buds",
        "QuantityType": "WeightBased",
        "DefaultLabTestingState": "NotSubmitted",
        "UnitOfMeasureName": "Ounces",
        "ApprovalStatus": "Approved",
        "ApprovalStatusDateTime": "0001-01-01T00:00:00+00:00",
        "StrainId": 1,
        "StrainName": "Spring Hill Kush",
        "AdministrationMethod": null,
        "UnitCbdPercent": null,
        "UnitCbdContent": null,
        "UnitCbdContentUnitOfMeasureName": null,
        "UnitCbdContentDose": null,
        "UnitCbdContentDoseUnitOfMeasureName": null,
        "UnitThcPercent": null,
        "UnitThcContent": null,
        "UnitThcContentUnitOfMeasureName": null,
        "UnitThcContentDose": null,
        "UnitThcContentDoseUnitOfMeasureName": null,
        "UnitVolume": null,
        "UnitVolumeUnitOfMeasureName": null,
        "UnitWeight": null,
        "UnitWeightUnitOfMeasureName": null,
        "ServingSize": null,
        "SupplyDurationDays": null,
        "NumberOfDoses": null,
        "UnitQuantity": null,
        "UnitQuantityUnitOfMeasureName": null,
        "PublicIngredients": null,
        "Description": null,
        "IsUsed": false
    }

create(self, license_number)

Create an item record in Metrc.

create_from_json(client, license_number, json) classmethod

Initiate a class instance from a dictionary.

delete(self)

Delete the item.

update(self, **kwargs)

Update the item given parameters as keyword arguments.

LabResult

A class that represents a cannabis lab result.

The Lab Results tab displays the details of each individual lab test performed on the package. A Document Download button is available on each row on the Lab Results tab to view the associated certificate of analysis (COA), which the laboratory staff uploads when test results are recorded. The test results and COA are available on the source package and any related packages only after the laboratory staff releases the results

create_from_json(client, license_number, json) classmethod

Initiate a class instance from a dictionary.

post(self, data={})

Post lab result data.

release(self, data={})

Release lab results.

upload_coa(self, data={})

Upload lab result CoA.

Location

A class that represents a cannabis-production location.

    {
        "Id": 1,
        "Name": "Harvest Location",
        "LocationTypeId": 1,
        "LocationTypeName": "Default",
        "ForPlantBatches": True,
        "ForPlants": True,
        "ForHarvests": True,
        "ForPackages": True
    }

delete(self)

Delete location.

update(self, **kwargs)

Update location.

Model

Base class for all Metrc models.

uid property readonly

The model's unique ID.

__init__(self, client, context, license_number='', function=<function camel_to_snake at 0x000001CD54C66EE0>) special

Initialize the model, setting keys as properties.

from_fb(client, ref) classmethod

Initialize a class from Firebase data.

Parameters:

Name Type Description Default
client Client

A Metrc client instance.

required
ref str

The reference to the document in Firestore.

required

to_dict(self)

Returns the model's properties as a dictionary.

to_fb(self, ref='', col='')

Upload the model's properties as a dictionary to Firestore.

Parameters:

Name Type Description Default
ref str

The Firestore document reference.

''
col str

A Firestore collection, with the UID as document ID.

''

Package

A class that represents a cannabis package.

Immature plants and seeds can be packaged by a nursery and transported by a distributor to a cultivator, distributor or retailer for sale.

  1. When a manufacturer is creating a concentrate that will then be used in multiple infused production batches, the concentrate must be created as a new package. The infused production batches will then be created from the concentrate package.

A. The new package of concentrate is a production batch and will then be partially used in an infused product or sold to a customer.

B. This makes it more easily recorded as connected to the finished infused product package.

  1. Packages made at a manufacturer facility that creates concentrates must be created by pulling from other packages.

  2. A package must exist in order for it to be selected for transfer. Transfers are realtime inventory dependent.

  3. There must be a contents section for each new package created from an existing package.

  4. When adjusting a package, use the appropriate adjustment reason.

  5. In order for a distributor to send a sample for testing, a test sample package must be created. A new test sample must have a new RFID package tag and be pulled from an existing package.

  6. Package tags may only be used once and may not be reused.

adjust(self, weight, note='', reason='Mandatory State Destruction', uom='Grams')

Adjust the package.

Parameters:

Name Type Description Default
weight float

Required adjustment weight.

required
note str

Required note for certain reasons.

''
reason str

The reason for adjustment.

'Mandatory State Destruction'
uom str

The unit of measure.

'Grams'

change_item(self, item_name)

Change the item of the package.

create_package(self, data)

Create a package record in Metrc.

finish(self)

Finish a package.

unfinish(self)

Unfinish a package.

Patient

A class that represents a cannabis patient.

{
    'PatientId': 1,
    'LicenseNumber': '000001',
    'RegistrationDate': '2015-01-08',
    'LicenseEffectiveStartDate': '2014-07-12',
    'LicenseEffectiveEndDate': '2015-07-07',
    'RecommendedPlants': 6,
    'RecommendedSmokableQuantity': 2.0,
    'HasSalesLimitExemption': false,
    'OtherFacilitiesCount': 1
}

create(self)

Create a patient record in Metrc.

create_from_json(client, json) classmethod

Initiate a class instance from a dictionary.

delete(self)

Delete the patient.

update(self, **kwargs)

Update the patient given parameters as keyword arguments.

Plant

A class that represents a cannabis plant.

Plants are tagged at the immature lot growth phase and at the mature / flowering growth phase. A UID number is assigned to an immature plant lot of up to 100 seeds or immature plants. Required corresponding UID number labels will need to be produced by the licensee . Once the immature lot has been established in Metrc, the death of an immature plant(s) must be recorded in Metrc by recording the associated waste amount and reducing the total number of the immature plants in the lot for each immature plant that was destroyed.

Plant tags are assigned to individual plants when they are moved to a designated canopy area, or when the plant begins flowering.

A plant can be destroyed anytime during the growth phases. Any waste produced by the plant should be recorded prior to the destruction. 2. Any waste created during the immature growth phase must be recorded as waste using the Plant Waste function and destroyed. 3. When immature plants begin to flower, select the Change Growth Phase button to record the change and associate the new Plant Tag ID to the plant(s). 4. In Metrc, anytime something is trimmed from a flowering plant during growing with the intent to sell it, process it, or perform a partial harvest, a Manicure batch must be created.

destroy(self, weight, method='Compost', material='Soil', note='n/a', reason='Contamination', uom='grams')

Destroy the plant.

Parameters:

Name Type Description Default
weight float

Required weight of the waste.

required
material str

The waste material, e.g soil.

'Soil'
method str

The mechanism of destruction: Grinder or Compost.

'Compost'
reason str

The reason for destruction: Contamination or Male Plants.

'Contamination'

flower(self, tag, location_name=None)

Change the growth phase of the plant to flowering.

Parameters:

Name Type Description Default
tag str

A tag to assign to the flowering plant.

required
location_name str

An optional new location for the plant.

None

harvest(self, harvest_name, weight, location_name=None, patient_license=None, uom='Grams')

Harvest the plant.

Parameters:

Name Type Description Default
harvest_name str

Required harvest name.

required
weight float

Required harvest weight.

required
location_name str

The harvest location's name.

None
patient_license str

A patient's license number.

None
uom str

The unit of measure.

'Grams'

manicure(self, weight, harvest_name=None, location_name=None, patient_license=None, uom='Grams')

Manicure the plant.

Parameters:

Name Type Description Default
weight float

Required harvest weight.

required
harvest_name str

Optional harvest name.

None
location_name str

The drying location's name.

None
patient_license str

A patient's license number.

None
uom str

The unit of measure

'Grams'

move(self, location_name)

Move the plant to a new location.

Parameters:

Name Type Description Default
location_name str

The destination's name.

required

PlantBatch

A class that represents a cannabis plant batch.

    {
        "Id": 5,
        "Name": "Demo Plant Batch 1",
        "Type": "Seed",
        "LocationId": null,
        "LocationName": null,
        "LocationTypeName": null,
        "StrainId": 1,
        "StrainName": "Spring Hill Kush",
        "PatientLicenseNumber": null,
        "UntrackedCount": 80,
        "TrackedCount": 10,
        "PackagedCount": 0,
        "HarvestedCount": 0,
        "DestroyedCount": 40,
        "SourcePackageId": null,
        "SourcePackageLabel": null,
        "SourcePlantId": null,
        "SourcePlantLabel": null,
        "SourcePlantBatchId": null,
        "SourcePlantBatchName": null,
        "PlantedDate": "2014-10-10",
        "LastModified": "0001-01-01T00:00:00+00:00"
    }
    {
        "Name": "B. Kush 5-30",
        "Type": "Clone",
        "Count": 25,
        "Strain": "Spring Hill Kush",
        "Location": null,
        "PatientLicenseNumber": "X00001",
        "ActualDate": "2015-12-15"
    }

change_growth_phase(self, data)

Change the growth phase of the batch.

create(self, license_number)

Create a plant batch record in Metrc.

create_from_json(client, license_number, json) classmethod

Initiate a class instance from a dictionary.

create_package(self, data)

Create a package from the plant batch.

create_package_from_plants(self, data)

Create a package from the plant batch.

destroy_plants(self, count, reason)

Destroy a number of plants for a given reason.

Parameters:

Name Type Description Default
count int

The number of plants to destroy.

required
reason str

The reason for the destruction.

required

Receipt

A class that represents a cannabis sale receipt. Sales are reported to record the transfer of cannabis products to a consumer, patient or caregiver.

When you request receipts you receive the following object.

{
    "Id": 1,
    "ReceiptNumber": null,
    "SalesDateTime": "2016-01-01T17:35:45.000",
    "SalesCustomerType": "Consumer",
    "PatientLicenseNumber": null,
    "CaregiverLicenseNumber": null,
    "IdentificationMethod": null,
    "TotalPackages": 0,
    "TotalPrice": 0.0,
    "Transactions": [],
    "IsFinal": false,
    "ArchivedDate": null,
    "RecordedDateTime": "0001-01-01T00:00:00+00:00",
    "RecordedByUserName": null,
    "LastModified": "0001-01-01T00:00:00+00:00"
}

When you create a receipt, you pass the following object.

{
    "SalesDateTime": "2016-10-04T16:44:53.000",
    "SalesCustomerType": "Consumer",
    "PatientLicenseNumber": null,
    "CaregiverLicenseNumber": null,
    "IdentificationMethod": null,
    "Transactions": [
        {
            "PackageLabel": "ABCDEF012345670000010331",
            "Quantity": 1.0,
            "UnitOfMeasure": "Ounces",
            "TotalAmount": 9.99
        }
    ]
}

create(self)

Create a receipt record in Metrc.

create_from_json(client, json) classmethod

Initiate a class instance from a dictionary.

delete(self)

Delete the receipt.

update(self, **kwargs)

Update the receipt given parameters as keyword arguments.

Strain

A class that represents a cannabis strain.

    {
        "Id": 1,
        "Name": "Old-time Moonshine",
        "TestingStatus": "InHouse",
        "ThcLevel": 0.1865,
        "CbdLevel": 0.1075,
        "IndicaPercentage": 25.0,
        "SativaPercentage": 75.0
    }

create(self)

Create a strain record in Metrc.

create_from_json(client, json) classmethod

Initiate a class instance from a dictionary.

delete(self)

Delete the strain.

update(self, **kwargs)

Update the strain given parameters as keyword arguments.

Transaction

A class that represents a cannabis sale transaction. When you get a transaction you receive an object as follows.

{
    "SalesDate": "2015-01-08",
    "TotalTransactions": 40,
    "TotalPackages": 40,
    "TotalPrice": 399.6
}
A created transaction is as follows.
{
    "PackageId": 71,
    "PackageLabel": "ABCDEF012345670000010331",
    "ProductName": "Shake",
    "ProductCategoryName": null,
    "ItemStrainName": null,
    "ItemUnitCbdPercent": null,
    "ItemUnitCbdContent": null,
    "ItemUnitCbdContentUnitOfMeasureName": null,
    "ItemUnitCbdContentDose": null,
    "ItemUnitCbdContentDoseUnitOfMeasureName": null,
    "ItemUnitThcPercent": null,
    "ItemUnitThcContent": null,
    "ItemUnitThcContentUnitOfMeasureName": null,
    "ItemUnitThcContentDose": null,
    "ItemUnitThcContentDoseUnitOfMeasureName": null,
    "ItemUnitVolume": null,
    "ItemUnitVolumeUnitOfMeasureName": null,
    "ItemUnitWeight": null,
    "ItemUnitWeightUnitOfMeasureName": null,
    "ItemServingSize": null,
    "ItemSupplyDurationDays": null,
    "ItemUnitQuantity": null,
    "ItemUnitQuantityUnitOfMeasureName": null,
    "QuantitySold": 1.0,
    "UnitOfMeasureName": "Ounces",
    "UnitOfMeasureAbbreviation": "oz",
    "TotalPrice": 9.99,
    "SalesDeliveryState": null,
    "ArchivedDate": null,
    "RecordedDateTime": "0001-01-01T00:00:00+00:00",
    "RecordedByUserName": null,
    "LastModified": "0001-01-01T00:00:00+00:00"
}
When you update a transaction, you pass the following object.
{
    "PackageLabel": "ABCDEF012345670000010331",
    "Quantity": 1.0,
    "UnitOfMeasure": "Ounces",
    "TotalAmount": 9.99
}

create(self)

Create a transaction record in Metrc.

create_from_json(client, json) classmethod

Initiate a class instance from a dictionary.

update(self, **kwargs)

Update the transaction given parameters as keyword arguments.

Transfer

A class that represents a cannabis transfer. Transfers are a key component of the chain of custody process.

A transfer must be created anytime a package moves from one licensee to another, even if the two facilities are located on the same property.

Packages can only be transported from one licensee to another by a licensed Distributor. A Testing Laboratory is allowed to transport test samples for official state testing. Distributors and Testing Laboratories are required to record the actual departure time from the origin facility and the actual arrival time at the destination facility in Metrc real-time.

A package must be received in its entirety (the system DOES NOT allow receiving a partial package).

A transfer can be rejected by individual package, or in whole by rejecting all packages.

A rejected package requires the originating Licensee to receive the package back into inventory.

A package must exist in order to be selected for transfer. Transfers are done in real time and are inventory dependent.

When receiving a package, any adjustments to the weight, volume, or count may be reported to the State.

If there are any questions about a transfer, reject it.

A transfer can be modified , or voided, up until the time that the Distributor or Testing Laboratory marks that it has departed the facility. Once the transfer process has begun, the transfer may not be modified except by the Distributor or Testing Laboratory to edit estimated departure and arrival times, or driver and vehicle information (see Edit Transporter Info below).

When modifying transfers, each of the transfer fields may be modified at the same level of detail as when the transfer was created. Edits may be completed for a variety of reasons including: error correction, changes in destination, changes in product, etc.

Voiding a transfer can only be completed by the originating business. Voiding a transfer permanently eliminates it and moves the product back into the originator’s inventory. Once a transfer has been voided, it cannot be reinstated and all associated packages will be returned to the transfer originator’s inventory

Receiving a transfer is the final point of exchange in the chain of custody.

create(self)

Create a transfer record in Metrc.

create_from_json(client, json) classmethod

Initiate a class instance from a dictionary.

delete(self)

Delete the transfer.

update(self, **kwargs)

Update the transfer given parameters as keyword arguments.

TransferTemplate

A class that represents a cannabis transfer template. Transfer templates can be used for transfers to the same destination licensee utilizing the same:

- Planned Route
- Transporter(s)
- Driver(s)
- Vehicle(s)
- Package

The template can be copied to create other templates.

create(self)

Create a transfer template record in Metrc.

create_from_json(client, json) classmethod

Initiate a class instance from a dictionary.

delete(self)

Delete the transfer template.

update(self, **kwargs)

Update the transfer template given parameters as keyword arguments.

Waste

A class that represents cannabis waste.

A harvest batch is created and given a unique Harvest Name when plants or plant material are harvested.

Plant waste must be recorded within three business days of destruction. In Metrc plant waste can be recorded by Immature Plant Lot, Flowering Plant or by Location. 2. Waste can also be recorded by Harvest Batch. See Metrc User Guide for details. 3. When recording Flowering Plant waste, the waste from multiple plants can be recorded as a single waste event but the flowering plants contributing to the waste must be individually identified. 4. If a plant is no longer viable, the waste must be recorded prior to recording its destruction. 5. The reason for the waste must be identified using the Waste Reasons defined by the State of California as listed in Exhibit 38 below. Use of some Waste Reasons may be limited to certain license types, as determined by the State.