Skip to content

Job Management

Understanding the Job Model

In CoCore, a Job is the central unit of work in print production, similar to a JDF Job Ticket. However, unlike JDF's hierarchical node structure, CoCore uses a flatter, more flexible model that's easier to query and manage.

Job Hierarchy

Job (Overall print job)
├── Component (Physical print parts - cover, content, insert)
│   ├── ComponentMedia (Substrate specifications)
│   ├── ComponentLayout (Imposition details)
│   └── ComponentFileUsage (Content files)
├── Operation (Production steps)
│   └── Milestone (Key checkpoints)
└── JobProduct (Intermediate products during manufacturing)
    └── Examples: printed signatures, folded sheets, incomplete book blocks

Job States and Lifecycle

Job State Enum

Jobs progress through a defined state machine:

graphql
enum JobStateEnum {
  DRAFT           # Initial creation, not ready for production
  PENDING         # Ready for production, awaiting start
  PROOFING        # In the proofing process
  PENDING_APPROVAL # Awaiting customer approval
  APPROVED        # Customer approved, ready for production
  IN_PRODUCTION   # Active production
  COMPLETED       # Production finished
  SHIPPED         # Delivered to customer
  CANCELLED       # Job cancelled
  ON_HOLD         # Temporarily paused
}

State Transition Rules

Not all state transitions are allowed. The system enforces valid workflows:

DRAFT → PENDING → PROOFING → PENDING_APPROVAL → APPROVED → IN_PRODUCTION → COMPLETED → SHIPPED
         ↓         ↓            ↓                 ↓           ↓              ↓
      CANCELLED  ON_HOLD    CANCELLED        CANCELLED   CANCELLED      CANCELLED

Creating Jobs

Basic Job Creation

Start with minimal required fields:

graphql
mutation CreateBasicJob {
  createJob(input: {
    name: "Business Cards - ACME Corp"
    quantity: 1000
    externalId: "ORD-2024-001"  # Your system's reference
  }) {
    result {
      id
      jobNumber  # Auto-generated unique identifier
      name
      state      # Starts as DRAFT
      createdAt
    }
    errors {
      field
      message
    }
  }
}

Complete Job Creation

Create a job with full details:

graphql
mutation CreateCompleteJob {
  createJob(input: {
    # Basic Information
    name: "Premium Brochures - Spring Campaign"
    description: "Tri-fold brochures with spot UV coating"
    externalId: "MIS-2024-0423"

    # Quantities and Dates
    quantity: 5000
    dueDate: "2024-03-15T17:00:00Z"
    requestedDeliveryDate: "2024-03-18T09:00:00Z"

    # Priority and Classification
    priority: 7  # 1-10 scale
    rushOrder: false

    # Customer Reference
    customerId: "customer-abc-123"

    # Production Instructions
    productionNotes: "Use press #3 for color consistency with previous run"
    specialInstructions: "Pack in boxes of 500, shrink-wrap each box"

    # Initial State (optional, defaults to DRAFT)
    state: PENDING
  }) {
    result {
      id
      jobNumber
      name
      state
      priority
      dueDate
      customer {
        id
        name
        contactName
      }
    }
    errors {
      field
      message
      code
    }
  }
}

Creating Job with Components

Build the complete job structure in multiple steps:

graphql
# Step 1: Create the job
mutation Step1_CreateJob {
  createJob(input: {
    name: "Annual Report 2024"
    quantity: 2000
    customerId: "customer-xyz"
  }) {
    result {
      id
      jobNumber
    }
  }
}

# Step 2: Add components directly to the job
mutation Step2_CreateCoverComponent {
  createComponent(input: {
    jobId: "job-123"  # Components belong directly to jobs
    kind: COVER
    name: "Annual Report Cover"
    description: "4-page cover on heavy stock"

    # Media specifications
    media: {
      name: "Premium Coated Cover"
      type: PAPER
      kind: SHEET
      weight: { value: 300, unit: GSM }
      width: { value: 8.5, unit: INCH }
      height: { value: 11, unit: INCH }
      stockType: COATED
      coating: GLOSS
      opacity: OPAQUE
    }

    # Layout specifications
    layout: {
      pages: 4
      sides: TWO_SIDED_HEAD_TO_HEAD
      closedDimensions: {
        width: { value: 8.5, unit: INCH }
        height: { value: 11, unit: INCH }
      }
      bleed: {
        top: { value: 0.125, unit: INCH }
        bottom: { value: 0.125, unit: INCH }
        left: { value: 0.125, unit: INCH }
        right: { value: 0.125, unit: INCH }
      }
    }
  }) {
    result {
      id
      kind
      media { name, type }
      layout { pages }
    }
  }
}

mutation Step3_CreateContentComponent {
  createComponent(input: {
    jobId: "job-123"  # Components belong directly to jobs
    kind: CONTENT
    name: "Annual Report Interior"
    description: "60 interior pages"

    media: {
      name: "Silk Text"
      type: PAPER
      kind: SHEET
      weight: { value: 100, unit: GSM }
      width: { value: 8.5, unit: INCH }
      height: { value: 11, unit: INCH }
      stockType: SILK
      opacity: OPAQUE
    }

    layout: {
      pages: 60
      sides: TWO_SIDED_HEAD_TO_HEAD
      closedDimensions: {
        width: { value: 8.5, unit: INCH }
        height: { value: 11, unit: INCH }
      }
    }
  }) {
    result {
      id
      kind
    }
  }
}

# Step 4: Create JobProducts for intermediate manufacturing products
mutation Step4_CreateJobProducts {
  # Create a job product for printed sheets from the cover component
  coverSheets: createJobProduct(input: {
    jobId: "job-123"
    componentId: "component-cover-456"  # Links to the cover component
    name: "Printed Cover Sheets"
    metadata: "{\"quantity\": 500, \"sheetsPerSignature\": 4}"
  }) {
    result {
      id
      name
      component { kind }
    }
  }

  # Create a job product for printed and folded signatures
  contentSignatures: createJobProduct(input: {
    jobId: "job-123"
    componentId: "component-content-789"  # Links to the content component
    name: "Folded Content Signatures"
    metadata: "{\"quantity\": 125, \"pagesPerSignature\": 16}"
  }) {
    result {
      id
      name
      component { kind }
    }
  }

  # Create a job product for the assembled but unbound book block
  bookBlock: createJobProduct(input: {
    jobId: "job-123"
    componentId: null  # No specific component - represents assembled work
    name: "Assembled Book Block (Unbound)"
    metadata: "{\"quantity\": 2000, \"ready_for_binding\": true}"
  }) {
    result {
      id
      name
    }
  }
}

Updating Jobs

Basic Updates

Update job properties:

graphql
mutation UpdateJobDetails {
  updateJob(
    id: "job-123"
    input: {
      name: "Business Cards - ACME Corp (Revised)"
      priority: 9
      rushOrder: true
      dueDate: "2024-03-10T17:00:00Z"
      productionNotes: "Customer requested earlier delivery"
    }
  ) {
    result {
      id
      name
      priority
      rushOrder
      dueDate
      updatedAt
    }
    errors {
      field
      message
    }
  }
}

State Transitions

Change job state with validation:

graphql
mutation MoveToProduction {
  transitionJobState(
    id: "job-123"
    state: IN_PRODUCTION
  ) {
    result {
      id
      state
      stateChangedAt
      currentOperation {
        name
        state
      }
    }
    errors {
      message  # e.g., "Cannot transition from DRAFT to IN_PRODUCTION"
    }
  }
}

Bulk State Updates

Process multiple jobs:

graphql
mutation BulkApprove {
  job1: transitionJobState(id: "job-1", state: APPROVED) {
    result { id, state }
    errors { message }
  }

  job2: transitionJobState(id: "job-2", state: APPROVED) {
    result { id, state }
    errors { message }
  }

  job3: transitionJobState(id: "job-3", state: APPROVED) {
    result { id, state }
    errors { message }
  }
}

Querying Jobs

Get Single Job with Full Details

graphql
query GetJobComplete {
  getJob(id: "job-123") {
    # Basic Information
    id
    jobNumber
    externalId
    name
    description
    state

    # Quantities and Dates
    quantity
    quantityProduced
    quantityShipped
    createdAt
    updatedAt
    dueDate
    completedAt

    # Customer Information
    customer {
      id
      name
      contactName
      email
      phone
      creditStatus
    }

    # Components
    components {
      results {
        id
        kind
        name
        description
        media {
          name
          type
          weight { value, unit }
        }
        layout {
          pages
          sides
        }
        componentFileUsages {
          results {
            id
            fileName
            fileType
            fileSize
            pageRange
          }
        }
      }
    }

    # Job Products (intermediate manufacturing products)
    jobProducts {
      results {
        id
        name
        metadata
        component {  # Which component these products came from
          id
          kind
          name
        }
        # Products can be inputs/outputs of operations
        operationInputs {
          operation { name, state }
        }
        operationOutputs {
          operation { name, state }
        }
      }
    }

    # Production Operations
    operations(
      sort: [{ field: SEQUENCE, order: ASC }]
    ) {
      results {
        id
        name
        state
        sequence
        startedAt
        completedAt
        device {
          id
          name
          status
        }
      }
    }

    # Milestones
    milestones {
      results {
        id
        name
        type
        status
        dueDate
        completedAt
      }
    }
  }
}

Search and Filter Jobs

Find jobs matching specific criteria:

graphql
query SearchJobs {
  listJobs(
    filter: {
      # Text search
      name: { ilike: "%business card%" }

      # State filtering
      state: { in: [PENDING, IN_PRODUCTION, PROOFING] }

      # Date ranges
      createdAt: {
        greaterThanOrEqual: "2024-01-01T00:00:00Z"
        lessThan: "2024-02-01T00:00:00Z"
      }

      # Customer filtering
      customer: {
        creditStatus: { eq: APPROVED }
      }

      # Quantity ranges
      quantity: {
        greaterThanOrEqual: 1000
        lessThanOrEqual: 10000
      }
    }
    sort: [
      { field: PRIORITY, order: DESC }
      { field: DUE_DATE, order: ASC }
    ]
    first: 20
  ) {
    count
    results {
      id
      jobNumber
      name
      state
      priority
      dueDate
      customer { name }
    }
    endKeyset
  }
}

Get Jobs by External ID

Find jobs from your external system:

graphql
query GetJobByExternalId {
  getJobByExternalId(externalId: "MIS-2024-0423") {
    id
    jobNumber
    name
    state
    externalId
  }
}

Dashboard Queries

Get job statistics for dashboards:

graphql
query DashboardStats {
  # Jobs due today
  dueToday: listJobs(
    filter: {
      dueDate: {
        greaterThanOrEqual: "2024-02-15T00:00:00Z"
        lessThan: "2024-02-16T00:00:00Z"
      }
      state: { notIn: [COMPLETED, SHIPPED, CANCELLED] }
    }
  ) {
    count
    results {
      id
      jobNumber
      name
      priority
      customer { name }
    }
  }

  # Rush orders
  rushJobs: listJobs(
    filter: {
      rushOrder: { eq: true }
      state: { in: [PENDING, IN_PRODUCTION] }
    }
    sort: [{ field: PRIORITY, order: DESC }]
  ) {
    count
    results {
      id
      jobNumber
      name
      dueDate
    }
  }

  # Jobs awaiting approval
  pendingApproval: listJobs(
    filter: {
      state: { eq: PENDING_APPROVAL }
    }
    sort: [{ field: CREATED_AT, order: ASC }]
  ) {
    count
    results {
      id
      jobNumber
      name
      customer { name, email }
      proofUrl
    }
  }
}

Managing Job Relationships

Linking Files to Components

graphql
mutation AttachFilesToComponent {
  createComponentFileUsage(input: {
    componentId: "component-789"
    fileName: "annual_report_cover.pdf"
    fileType: "application/pdf"
    fileSize: 15728640  # bytes
    pageRange: "1-4"
    fileUrl: "https://storage.example.com/files/annual_report_cover.pdf"
    purpose: PRINT_READY
    colorSpace: CMYK
    resolution: 300
  }) {
    result {
      id
      fileName
      component {
        id
        kind
      }
    }
  }
}

Managing Job Operations

Create and sequence production operations:

graphql
mutation CreateProductionOperations {
  # Prepress operation
  op1: createOperation(input: {
    jobId: "job-123"
    name: "Prepress"
    type: PREPRESS
    sequence: 1
    estimatedDuration: 30  # minutes
    instructions: "Check files, create plates"
  }) {
    result { id, sequence }
  }

  # Printing operation
  op2: createOperation(input: {
    jobId: "job-123"
    name: "Print Cover"
    type: PRINTING
    sequence: 2
    deviceId: "device-press-1"
    estimatedDuration: 120
    instructions: "4-color process + spot UV"
  }) {
    result { id, sequence }
  }

  # Finishing operation
  op3: createOperation(input: {
    jobId: "job-123"
    name: "Perfect Binding"
    type: FINISHING
    sequence: 3
    deviceId: "device-binder-1"
    estimatedDuration: 90
    instructions: "Perfect bind with 3mm spine"
  }) {
    result { id, sequence }
  }
}

Job Subscriptions

Real-time updates for job changes:

graphql
subscription WatchJobUpdates {
  jobUpdated(jobId: "job-123") {
    id
    state
    updatedAt
    quantityProduced
    currentOperation {
      name
      state
      percentComplete
    }
  }
}

subscription WatchJobStateChanges {
  jobStateChanged(
    filter: { customerId: { eq: "customer-abc" } }
  ) {
    id
    jobNumber
    previousState
    newState
    changedAt
    changedBy {
      name
      email
    }
  }
}

Common Workflows

1. Quick Reorder

Clone an existing job:

graphql
mutation QuickReorder {
  cloneJob(
    sourceJobId: "job-original"
    input: {
      name: "Business Cards - Reorder March 2024"
      quantity: 2000
      dueDate: "2024-03-20T17:00:00Z"
    }
  ) {
    result {
      id
      jobNumber
      name
      # Components and settings copied from original
      components {
        count
      }
    }
  }
}

2. Gang Run Management

Group multiple jobs for efficient production:

graphql
mutation CreateGangRun {
  createGangRun(input: {
    name: "Business Cards Gang Run - Week 10"
    jobIds: ["job-1", "job-2", "job-3", "job-4"]
    deviceId: "device-press-2"
    scheduledDate: "2024-03-11T08:00:00Z"
  }) {
    result {
      id
      jobs {
        results {
          id
          jobNumber
          customer { name }
          quantity
        }
      }
      totalSheets
      estimatedRunTime
    }
  }
}

3. Proof Approval Workflow

graphql
# Generate proof
mutation GenerateProof {
  generateJobProof(jobId: "job-123") {
    result {
      id
      proofUrl
      generatedAt
    }
  }
}

# Send for approval
mutation SendForApproval {
  transitionJobState(id: "job-123", state: PENDING_APPROVAL) {
    result { state }
  }

  sendProofEmail(input: {
    jobId: "job-123"
    recipientEmail: "customer@example.com"
    message: "Please review and approve your proof"
  }) {
    result { sentAt }
  }
}

# Record approval
mutation RecordApproval {
  approveJob(input: {
    jobId: "job-123"
    approverEmail: "customer@example.com"
    comments: "Looks great, please proceed"
  }) {
    result {
      id
      state  # Now APPROVED
      approvalDetails {
        approvedBy
        approvedAt
        comments
      }
    }
  }
}

Best Practices

1. Use External IDs

Always set externalId to maintain links to your MIS/ERP system:

graphql
externalId: "YOUR-SYSTEM-ID-12345"

2. Set Realistic Priorities

Use the 1-10 priority scale consistently:

  • 1-3: Low priority, flexible deadlines
  • 4-6: Normal production
  • 7-9: High priority, tight deadlines
  • 10: Emergency/rush jobs

3. Include Production Notes

Add clear instructions for operators:

graphql
productionNotes: "Match color to sample #4523. Use fresh ink batch."
specialInstructions: "Call customer before shipping: 555-0100"

4. Track Component Relationships

Understand the correct hierarchy:

Job → Component (design/specification) → ComponentFileUsage (artwork/content)
     ↘ JobProduct (physical items during production - sheets, signatures, blocks)

Components define WHAT to print (specifications), while JobProducts track the physical items created during manufacturing.

5. Monitor State Transitions

Subscribe to state changes for critical jobs to ensure smooth workflow.

Next Steps

Connect. Combine. Collaborate.
The pioneering open integration platform, dedicated to transforming connectivity in the printing industry.