Carbon LogoCarbon

Traceability

Learn about the traceability system in Carbon

Carbon's traceability system tracks the complete lineage of materials and products through the manufacturing process. The system is built around two core concepts:

  • Tracked Entities - Physical items, batches, or lots that need to be tracked (nodes in the graph)
  • Tracked Activities - Transformations or processes that consume inputs and produce outputs (nodes in the graph)
  • Tracked Activity Inputs - Links activities to their input entities (edges in the graph)
  • Tracked Activity Outputs - Links activities to their output entities (edges in the graph)

Together, these form a directed acyclic graph (DAG) that represents material flow from raw materials through transformations to finished products.

Core Tables

trackedEntity

Represents a physical item, batch, or lot that needs to be tracked through the system.

Schema:

CREATE TABLE "trackedEntity" (
  "id" TEXT NOT NULL DEFAULT id(),
  "quantity" NUMERIC NOT NULL,
  "status" "trackedEntityStatus" NOT NULL DEFAULT 'Available',
  "sourceDocument" TEXT NOT NULL,
  "sourceDocumentId" TEXT NOT NULL,
  "sourceDocumentReadableId" TEXT,
  "attributes" JSONB NOT NULL DEFAULT '{}',
  "companyId" TEXT NOT NULL,
  "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
  "createdBy" TEXT NOT NULL
)

Key Fields:

  • id - Unique identifier (xid)
  • quantity - Current quantity of this entity
  • status - Enum: 'Available', 'Reserved', 'On Hold', 'Consumed'
  • sourceDocument - Type of document that created this entity (e.g., "Receipt", "Manufacturing")
  • sourceDocumentId - UUID of the specific revision that created this entity
  • sourceDocumentReadableId - Human-readable ID of the source document
  • attributes - JSONB containing:
    • Serial numbers
    • Batch numbers
    • Manufacturing dates
    • Expiration dates
    • Receipt/supplier info
    • Custom properties

Relationship to Item Ledger:

  • itemLedger.trackedEntityIdtrackedEntity.id
  • Each inventory transaction can be linked to a specific tracked entity
  • On deletion: SET NULL, On update: CASCADE

trackedActivity

Represents a transformation or process that converts input entities into output entities.

Schema:

CREATE TABLE "trackedActivity" (
  "id" TEXT NOT NULL DEFAULT id(),
  "type" TEXT NOT NULL,
  "sourceDocument" TEXT,
  "sourceDocumentId" TEXT,
  "sourceDocumentReadableId" TEXT,
  "attributes" JSONB NOT NULL DEFAULT '{}',
  "companyId" TEXT NOT NULL,
  "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
  "createdBy" TEXT NOT NULL
)

Key Fields:

  • id - Unique identifier
  • type - Describes the transformation (e.g., "Manufacturing", "Assembly", "Conversion")
  • sourceDocument - Document type that triggered this activity
  • sourceDocumentId - Specific document instance
  • attributes - Additional metadata about the transformation

Bridge Tables: trackedActivityInput & trackedActivityOutput

These tables link activities to entities and define the graph structure.

trackedActivityInput:

CREATE TABLE "trackedActivityInput" (
  "trackedActivityId" TEXT NOT NULL,
  "trackedEntityId" TEXT NOT NULL,
  "quantity" NUMERIC NOT NULL,
  "entityType" TEXT,
  "companyId" TEXT NOT NULL,
  "createdBy" TEXT NOT NULL,
  "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
)

trackedActivityOutput:

CREATE TABLE "trackedActivityOutput" (
  "trackedActivityId" TEXT NOT NULL,
  "trackedEntityId" TEXT NOT NULL,
  "quantity" NUMERIC NOT NULL,
  "companyId" TEXT NOT NULL,
  "createdBy" TEXT NOT NULL,
  "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
)

Graph Construction

Graph Structure

The traceability system forms a directed acyclic graph (DAG) where:

Nodes: TrackedEntity records

  • Represent physical items, batches, or lots
  • Have a status ('Available', 'Reserved', 'On Hold', 'Consumed')
  • Contain attributes specific to the entity

Edges: TrackedActivity records with Input/Output relationships

  • Represent transformations or processes
  • Link consumed entities (inputs) to produced entities (outputs)
  • Create parent-child relationships in the lineage

Graph Traversal

SQL Functions

Two key functions enable bidirectional graph traversal:

Get Descendants (Forward Tracing):

get_direct_descendants_of_tracked_entity_strict(entity_id TEXT)
  • Follows: Entity → Activity Input → Activity → Activity Output → Descendant Entity
  • Returns all entities produced from the given entity
  • Used for forward tracing (where did this material go?)

Get Ancestors (Backward Tracing):

get_direct_ancestors_of_tracked_entity_strict(entity_id TEXT)
  • Follows: Entity → Activity Output → Activity → Activity Input → Ancestor Entity
  • Returns all entities consumed to produce the given entity
  • Used for backward tracing (where did this come from?)

Graph Visualization

The traceability graph is visualized in apps/erp/app/routes/x+/traceability+/graph.tsx:

  • Constructs nodes and links from entities and activities
  • Supports ancestor/descendant traversal
  • Provides interactive visualization of material lineage

Common Workflows

Creating Tracked Entities

Tracked entities are created during various operations:

  1. Receipt (post-receipt/index.ts)

    • Creates trackedEntity for received materials
    • Links to receipt document
    • Stores supplier info, batch numbers, etc. in attributes
  2. Manufacturing (post-production/index.ts, MES operations)

    • Creates trackedActivity
    • Links input materials via trackedActivityInput
    • Creates output entities via trackedActivityOutput
    • Updates entity statuses (inputs → 'Consumed', outputs → 'Available')
  3. Shipment (post-shipment/index.ts)

    • May create activities for shipped items
    • Tracks what entities left the facility
  4. Stock Transfer (post-stock-transfer/index.ts)

    • Transfers entities between locations
    • Maintains traceability across locations

Conversion Pattern

Step-by-step process for converting tracked entities (e.g., material → part):

  1. Create a trackedActivity record describing the transformation
  2. Create trackedActivityInput records for consumed entities
  3. Create trackedActivityOutput records for produced items
  4. Update item ledgers with deductions (inputs) and additions (outputs)
  5. Update entity statuses (consumed entities → 'Consumed')

Example from revision-system.md:

-- 1. Create the activity
INSERT INTO "trackedActivity" (id, type, sourceDocument, sourceDocumentId, ...)
VALUES ('activity_123', 'Manufacturing', 'ProductionOrder', 'po_456', ...);

-- 2. Link consumed entities
INSERT INTO "trackedActivityInput" (trackedActivityId, trackedEntityId, quantity, ...)
VALUES ('activity_123', 'material_entity_1', 10, ...);

-- 3. Link produced entities
INSERT INTO "trackedActivityOutput" (trackedActivityId, trackedEntityId, quantity, ...)
VALUES ('activity_123', 'part_entity_1', 5, ...);

-- 4. Update ledgers and statuses
UPDATE "trackedEntity" SET status = 'Consumed' WHERE id = 'material_entity_1';

Key Service Functions

ERP Inventory Service

apps/erp/app/modules/inventory/inventory.service.ts:

  • getTrackedEntities() - Get entities for an item
  • getTrackedEntitiesByMakeMethodId() - Get entities produced by a make method
  • getTrackedEntitiesByOperationId() - Get entities produced by an operation

MES Operations Service

apps/mes/app/services/operations.service.ts:

  • getTrackedEntitiesByMakeMethodId() - Get available entities for production
  • getTrackedEntity() - Get specific entity details
  • getTrackedInputs() - Get consumed inputs for an activity
  • startProductionEvent() - Creates activities and links during production

QR Code Integration

Tracked entities can have QR codes generated for labeling:

  • ProductLabelPDF uses generateQRCode(item.trackedEntityId, size)
  • Enables scanning for instant traceability lookup
  • Reference: llm/cache/pdf-generation-patterns.md:43

Common Queries

Get Tracked Entities for an Item (All Revisions)

SELECT te.*
FROM "trackedEntity" te
JOIN "item" i ON i.id = te."sourceDocumentId"
WHERE i."readableId" = 'ITEM-001'
  AND te."sourceDocument" = 'Item';

Get Tracked Entities for Specific Revision

SELECT *
FROM "trackedEntity"
WHERE "sourceDocumentId" = '<item-revision-uuid>'
  AND "sourceDocument" = 'Item';