Skip to main content

RoboPack

Overview

The Robopack system is a specialized automated printing station designed for printing EIFS (Exterior Insulation and Finish System) product labels directly onto bags. This feature integrates with the Print Maestro printer system to automatically print stickers for EIFS bags with specific customer information, dimensions, lot numbers, and product specifications.

Purpose

Robopack streamlines the EIFS bag labeling process by:

  • Automating label printing for EIFS production jobs
  • Creating EIFS bag inventory automatically upon successful print job submission
  • Tracking print jobs to enable reprinting if labels are damaged or misprinted
  • Managing multiple bag specifications including bag type, size (with fractional sizes), drainage options, and pieces per bag
  • Reducing manual entry errors through structured data validation and editable tables

Key Features

  1. Job Selection Interface - Users select from active EIFS jobs in progress, filtered by sales order, customer, and lot number
  2. Interactive Print Table - Tabulator-based editable table allowing operators to specify:
    • Quantity of bags to print
    • Product type (EPS or GPS)
    • Bag type selection from available inventory
    • Size specifications (whole numbers and fractional inches)
    • Pieces per bag count
    • Drainage designation (yes/no checkbox)
  3. Real-time Progress Tracking - Dashboard cards display total bags printed vs. target quantities for each bag type
  4. Print Job Management - Each row can be printed individually, with the ability to resend failed or damaged labels
  5. Automatic Inventory Management - System automatically removes stickers and bags from inventory upon successful print job creation

Access Requirements

Access to the Robopack system is restricted to users who are logged in and have appropriate production floor permissions. The system is accessed from the home page via navigation to specific EIFS jobs.

Workflow Overview

  1. User navigates to Robopack Jobs page (/robopack/jobs)
  2. System displays all active EIFS jobs that are in progress (not yet completed)
  3. User selects a job to begin printing labels
  4. System displays the Robo Pack In Progress page with:
    • Job information (sales order, customer, lot number)
    • Editable table for specifying print specifications
    • Progress cards showing printed quantity vs. target quantity
  5. User fills in print specifications for each bag size/type needed
  6. User clicks Print button for each row
  7. System validates the data, creates EIFS bags in the database, removes inventory, and sends the print job to Print Maestro
  8. Labels print at the Robopack station
  9. User can resend labels if needed or exit the station when complete

![INSERT IMAGE HERE: Screenshot of the Robopack Jobs page showing available EIFS jobs with job IDs, sales orders, customers, and start dates]

![INSERT IMAGE HERE: Screenshot of the Robo Pack In Progress page showing the editable table, progress cards, and print buttons]


Note: The Robopack feature occasionally experiences issues where table rows do not populate correctly. A Refresh Page button is provided in the top-right corner to reload the data if this occurs.


Front-End Behavior

Page 1: Robopack Jobs (/robopack/jobs)

File Location: src/app/Views/robopack/robo_pack_jobs.php

Page Layout

The jobs selection page provides a simple interface for choosing which EIFS job to work on:

Header Section:

  • Go Back button (top-left) - Returns to /user/view (home page)
  • Search bar - "Search job by sales order..." with real-time filtering

Jobs Display:

  • White card-based layout with shadow effect
  • Header: "Jobs in progress..."
  • Each job card displays:
    • Job ID
    • Sales Order number
    • Customer name
    • Start Date (formatted as M/D/YYYY h:mm A)
    • Start Job button (blue, right-aligned)

Empty State:

  • If no EIFS jobs are in progress: "No EIFS jobs are in progress at this time."

![INSERT IMAGE HERE: Screenshot showing the Robopack Jobs page with multiple job cards, each displaying job details and a Start Job button]

Interactive Elements

Search Functionality:

  • Real-time search using search_jobs() function
  • Filters job cards by sales order number
  • Uses jQuery to show/hide cards based on search input
  • Each card has ID: sales_order_\{sales_order_label\}

Job Card Click:

  • Clicking Start Job button navigates to /robopack/in_progress/\{job_id\}
  • Loads the in-progress page for the selected job

Page 2: Robo Pack In Progress (/robopack/in_progress/\{job_id\})

File Location: src/app/Views/robopack/robo_pack_in_progress.php JavaScript: src/public/js/robopack/robo_pack_in_progress.js CSS: src/public/css/eifs/robo_pack_in_progress.css

Page Layout

Header Section:

  • Title: "Robo Pack in Progress" (h2)
  • Refresh Page button (top-right) - Reloads the entire page to fix table population issues
  • Toast notification container (top-right) for alerts

Job Information Table: A bordered table displays current job details (some columns hidden with d-none class):

ColumnVisibleContent
Job IDNoHidden (used by JavaScript)
EIFS Job IDNoHidden (used by JavaScript)
Bag TypeYesEIFS bag type label
Sales OrderYesSales order number
CustomerYesCustomer name
LotYesLot number

Action Buttons:

  • Add Row button (blue outline) - Adds a new empty row to the print table

Print Specifications Table: The main interactive table (#robo_pack_table) built with Tabulator.js:

ColumnTypeBehavior
Print ButtonAction"Print" (blue) or "Resend" (yellow) button
QuantityNumberEditable, min: 0, required
TypeDropdownEPS or GPS selection, required
BagDropdownList of available bag types for job type 7
SizeNumberWhole number size in inches, min: 0, required
Fraction (if any)Modal TriggerClick to open fraction editor modal
PC / BagNumberPieces per bag count, min: 0, required
DrainageCheckboxTick/cross formatter, toggles drainage designation

Table Row Coloring:

  • Green background (rgba(125,255,99,0.54)) - Row has been printed successfully (done === 1)
  • White background - Row not yet printed or pending

Progress Cards: Bottom section displays real-time progress tracking cards:

  1. Total Bags Card:

    • Header: "Total Bags"
    • Display: \{printed\}/\{target\} in 50px font
    • Background: Gray (bg-secondary) initially
    • Changes to green (bg-success) when target met
  2. Individual Bag Type Cards:

    • One card per EIFS bag type target
    • Header: Bag type label (e.g., "2x4x8 EPS")
    • Display: \{printed\}/\{target\} for that specific type
    • Background: Gray initially, green when target met
    • Cards generated dynamically from $targets array
    • Only shows bag types with quantity > 0

Exit Button:

  • Exit Robo Pack Station button (blue) - Returns to /robopack/jobs

![INSERT IMAGE HERE: Close-up of the editable Tabulator print table showing columns for Quantity, Type, Bag, Size, Fraction, PC/Bag, and Drainage with both Print and Resend buttons]

![INSERT IMAGE HERE: Progress cards section showing the Total Bags card and individual bag type cards with printed/target counts]

Interactive Elements

1. Loading States:

The table uses a loading overlay during AJAX operations:

.loader-overlay {
position: absolute;
background: rgba(255, 255, 255, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
}
  • Shows spinner icon during data loading
  • Appears when fetching print job info
  • Automatically removed on success/error

2. Table Editing:

Type Selection:

  • Dropdown with "EPS" or "GPS" options
  • On change:
    • Sets label_name to "LotStickerGPS" or "LotStickerEPS"
    • Resets fraction data
    • Resets drainage flag
    • Redraws table

Bag Type Selection:

  • Populated from API call to /api/bag/get_types with job_type_id: 7
  • Lists all available bag type labels
  • Allows custom bag entry

Size Input:

  • Numeric input for whole inches
  • Displays with " suffix in table
  • Combined with fraction for total size

Fraction Editor:

  • Click "Fraction" cell to open modal
  • Modal contains:
    • Numerator input (top)
    • Visual divider line
    • Denominator input (bottom)
    • Cancel button (gray)
    • Remove Fraction button (red) - Clears fraction data
    • Save Fraction button (blue) - Saves and updates label name

Validation:

  • Numerator and denominator must be > 0
  • Displays as \{numerator\} / \{denominator\} " in table
  • Updates label_name to include "Frac" suffix (e.g., "LotStickerEPSFrac")

Drainage Checkbox:

  • Visual tick/cross formatter
  • Click to toggle between true/false
  • When true, appends "DB" to label name

3. Print Job Workflow:

Initial Print:

  1. User fills in row data
  2. Clicks Print button
  3. Button becomes disabled with text "Printing..."
  4. JavaScript validates data via validate_print_job():
    • All PC/Bag, Quantity, and Size values must be > 0
    • Type must be selected
    • Calculates total print size: size_value + (numerator / denominator)
  5. System shows "Sending..." notification
  6. Calls post_print_job() with resend: 0
  7. On success:
    • Button changes to yellow Resend button
    • Row background turns green
    • Notification: "Successfully sent order to printer"
    • Progress cards update via update_eifs_targets()
  8. On error:
    • Shows API error notification
    • Button re-enables

Resend Print Job:

  1. User clicks Resend button
  2. System calls show_resend_modal() with row position
  3. Modal displays current row data in read-only table:
    • Quantity, Type, Bag, Size, Fraction, PC/Bag, Drainage
  4. User clicks Resend Job button in modal
  5. System validates and calls post_print_job() with resend: 1
  6. Modal closes and print job re-submits

4. Progress Card Updates:

Function update_eifs_targets(job_id) polls /api/eifs_bag/get_job_totals:

  • Updates #total_\{bag_type_id\} with current count
  • Updates #total with overall count
  • Compares printed vs. target:
    • If printed >= target: Changes card to green (bg-success)
    • If printed < target: Keeps gray (bg-secondary)
  • Called after each successful print job

5. Add Row Functionality:

  • Add Row button calls add_table_row()
  • Adds new empty row to Tabulator table
  • User can fill in specifications for additional print jobs
  • Allows printing multiple label types for same job

6. Refresh Page:

  • Top-right Refresh Page button uses window.location.reload()
  • Workaround for occasional table population issues
  • Reloads entire page with fresh data from server

User Experience Notes

Visual Feedback:

  • Notifications appear in top-right corner (toast style)
  • Color coding (green = complete, gray = in progress)
  • Button state changes (Print → Printing... → Resend)
  • Row highlighting for completed prints

Error Handling:

  • Validation messages via $.notify() notifications
  • API errors displayed with details
  • Prevents invalid data submission
  • User-friendly error messages

Responsive Design:

  • Table uses layout: "fitColumns" to adapt to screen width
  • Progress cards use flexbox layout
  • Cards stack on smaller screens

![INSERT IMAGE HERE: Screenshot of the Fraction Editor modal showing numerator and denominator inputs with Cancel, Remove Fraction, and Save Fraction buttons]

![INSERT IMAGE HERE: Screenshot of the Resend Job modal displaying a previously printed job's details in a read-only table]


Back-End Logic

Controller: Robopack

File Location: src/app/Controllers/Robopack.php

The Robopack controller manages the two main pages for the Robopack printing station.

Method: jobs()

Route: /robopack/jobs

Displays the job selection page showing all active EIFS jobs.

public function jobs(): string
{
$title['title'] = "Robo Pack";
$data['jobs'] = Job_model::has('eifs_jobs')->where('finish', NULL)
->with('eifs_jobs.sales_order')->get();
$data['warning'] = json_encode($_SESSION);

return view('templates/header', $title) .
view('robopack/robo_pack_jobs', $data) .
view('templates/footer');
}

Logic:

  1. Queries job table for jobs with associated eifs_jobs records
  2. Filters to only incomplete jobs (finish is NULL)
  3. Eager loads eifs_jobs.sales_order relationship for display
  4. Passes jobs array to view for rendering
  5. Returns rendered view with header and footer

Method: in_progress(int $job_id)

Route: /robopack/in_progress/\{job_id\}

Displays the main Robopack printing interface for a specific EIFS job.

public function in_progress(int $job_id): string|RedirectResponse
{
$this->validation->setRule("job_id", "Job ID",
"required|numeric|is_not_unique[job.id]");

if(!$this->validation->run(['job_id' => $job_id])) {
log_message("error", __CLASS__ . "::" . __FUNCTION__ .
"() - Validation errors: " .
json_encode($this->validation->getErrors(), JSON_PRETTY_PRINT));
return redirect()->back()->withInput()
->with('errors', $this->validation->getErrors());
}

$job = Job_model::with('eifs_job')->find($job_id);

if($job['finish'] !== NULL) {
log_message('warning', 'Attempted to start a ROBOPACK/EIFS job with ID : '
. $job_id . ' that was already complete');
return redirect()->with("messages",
["Robopack job with ID" . $job_id . " already complete"])
->to('/robopack/jobs');
}
else {
$data['user'] = auth()->user();
$data['job'] = $job;
$data['target_total'] = Eifs_bag_target_model::getJobTargetTotal($job_id);
$data['targets'] = Eifs_bag_target_model::with('eifs_bag_type')
->where('job_id', $job_id)
->where('quantity', '>', 0)->get();

$title['title'] = "Robo Pack In Progress";

return view('templates/header', $title) .
view('robopack/robo_pack_in_progress', $data) .
view('templates/footer');
}
}

Logic:

  1. Validates job_id parameter exists in database
  2. Loads job with EIFS job relationship from database
  3. Checks if job is already complete:
    • If finish is not NULL, redirects back to jobs page with warning
    • Logs warning message about attempted access to completed job
  4. Prepares data for view:
    • Current authenticated user
    • Job record with EIFS job details
    • Total target quantity across all bag types
    • Individual targets for each EIFS bag type (only where quantity > 0)
  5. Returns rendered view with data

API Controller: PrintJob

File Location: src/app/Controllers/Api/PrintJob.php

The PrintJob API controller handles the creation and management of print jobs sent to the Print Maestro system.

Method: send()

Route: /api/print_job/send (POST)

Creates a single print job for Robopack printing and manages associated EIFS bag creation.

Validation Rules:

'resend'            => 'required|numeric|in_list[0,1]'
'size_value' => 'required|numeric|greater_than_equal_to[0]'
'size_numerator' => 'required|numeric|greater_than_equal_to[0]'
'size_denominator' => 'required|numeric|greater_than_equal_to[0]'
'quantity' => 'required|numeric|greater_than[0]'
'job_id' => 'required|numeric|is_not_unique[job.id]'
'label_name' => 'required|alpha_numeric_punct|max_length[255]'
'type' => 'required|string|in_list[eps,EPS,gps,GPS]'
'bag_type' => 'required|alpha_numeric_punct|min_length[2]|max_length[255]'
'is_drainage' => 'required|alpha|in_list[true,false]'

Processing Flow:

  1. Validate Input - Ensures all required parameters are present and valid

  2. Load Job Data:

    $job = Job_model::with('eifs_job')->find($valid_data['job_id']);
  3. Find EIFS Bag Type ID:

    $eifs_bag_type_id = find_eifs_bag_type(
    $valid_data['size_value'],
    $valid_data['size_numerator'],
    $valid_data['size_denominator'],
    $valid_data['type']
    );
    • Constructs label like "EPS 2 1/2"" or "GPS 4""
    • Searches eifs_bag_type table for matching record
    • Returns -1 if not found (triggers error response)
  4. Handle Resend (if resend === 1):

    delete_previous_print_job($valid_data, $job->eifs_job->id, $eifs_bag_type->id);
    • Deletes the old print job record to avoid duplicates
  5. Find EIFS Block:

    $eifs_block_id = find_eifs_block_id($job->id, $eifs_bag_type_id);
    • Searches for an EIFS block of matching type with < 12 bags already made
    • Returns -1 if no suitable block found (creates notification)
  6. Calculate Totals:

    • Type Total: Sum of quantity from eifs_bag_target for this specific bag type
    • Job Total: Sum of all quantity values across all bag types for this job
    • Starting Number: Count of previously printed labels for this specific size + 1
    • Job Count: Total number of labels printed so far on entire job
  7. Create EIFS Bags:

    make_eifs_bags(
    $valid_data['bag_type'],
    $valid_data['quantity'],
    $valid_data['job_id'],
    $eifs_bag_type->id,
    $eifs_block_id
    );
    • Creates quantity number of eifs_bag records
    • Associates each bag with:
      • EIFS bag type
      • Bag type (for packaging)
      • EIFS block (if found)
      • Job ID
    • Removes stickers and bags from inventory
    • Logs inventory removal
  8. Create Print Job Record:

    $print_job = new Print_job_model();
    $print_job->fill($valid_data);
    if ($valid_data['is_drainage'] == 'true')
    $print_job->label_name .= 'DB';
    $print_job->copies = $valid_data['quantity'];
    $print_job->size_total = substr(str_repeat(0, 3) . $type_total, -3);
    $print_job->job_total = substr(str_repeat(0, 3) . $total, -3);
    $print_job->job_count = substr(str_repeat(0, 3) . $job_count, -3);
    $print_job->size_count = $starting_number;
    $print_job->print_type = 0; // Robo pack print job
    $print_job->save();
    • Appends "DB" to label name for drainage bags
    • Pads counts with zeros (e.g., 5 becomes "005")
    • Sets print_type = 0 to identify as Robopack job
    • Saves to print_job table
  9. Return Response:

    return $this->respondCreated($print_job);

Method: get_label_info()

Route: /api/print_job/get_label_info (POST)

Retrieves all print job information for a specific EIFS job, including both printed and pending jobs.

Validation Rules:

'job_id' => 'required|numeric|is_not_unique[job.id]'

Processing Flow:

  1. Load Job with Relationships:

    $job = Job_model::with(
    'eifs_targets.eifs_bag_type',
    'eifs_targets.bag_type',
    'eifs_job.sales_order',
    'print_jobs'
    )->find($valid_data['job_id']);
  2. Query Already Printed Jobs:

    SELECT
    SUM(copies) as quantity,
    size_value, size_numerator, size_denominator,
    label_name, bag_type, piece_count as pcs_per_bag,
    eifs_job.lot_number, sales_order.label as sales_order
    FROM print_job
    WHERE print_job.job_id = \{job_id\}
    GROUP BY size_value, size_numerator, size_denominator,
    label_name, bag_type, piece_count
    • Aggregates print jobs by size/type
    • Joins with eifs_job and sales_order for display data
  3. Format Printed Jobs:

    $data['printed_jobs'] = format_printed_jobs($printed_jobs);
    • Sets done = 1 to mark as printed
    • Extracts type ("EPS" or "GPS") from label name
    • Formats fraction as readable string ("1 / 2")
    • Detects drainage designation from label name
  4. Get Pending Print Jobs:

    foreach ($job->eifs_targets as $target) {
    $print_job = get_eifs_target_print_job($target, $job);
    if ($print_job !== []) {
    $data['print_jobs'][] = $print_job;
    }
    }
    • Iterates through each EIFS bag target
    • Creates print job structure if target not yet fully printed
    • Populates with job details (customer, sales order, lot number)
  5. Return Combined Data:

    return $this->respond($data);
    • Returns array with print_jobs (pending) and printed_jobs (completed)

Helper Functions

File Locations:

  • src/app/Helpers/eifs_helper.php
  • src/app/Helpers/print_job_helper.php
  • src/app/Helpers/bag_helper.php
  • src/app/Helpers/sticker_helper.php

find_eifs_bag_type()

Converts size parameters to EIFS bag type ID.

function find_eifs_bag_type(
int $size_num,
int $size_numerator,
int $size_denominator,
string $print_label
): int

Logic:

  1. Calls get_eifs_label() to construct label string
  2. Searches eifs_bag_type table for matching label
  3. Returns ID if found, -1 if not found

get_eifs_label()

Constructs EIFS bag type label string from size components.

function get_eifs_label(
string $type,
int $size,
int $num = -1,
int $denom = -1
): string|null

Examples:

  • get_eifs_label('EPS', 2, 1, 2)"EPS 2 1/2\""
  • get_eifs_label('GPS', 4, 0, 0)"GPS 4\""
  • get_eifs_label('EPS', 3, 3, 4)"EPS 3 3/4\""

find_eifs_block_id()

Finds an available EIFS block for associating with new bags.

function find_eifs_block_id(int $job_id, int $eifs_bag_type_id): int

Logic:

  1. Loads job with eifs_blocks and eifs_bags relationships
  2. Iterates through EIFS blocks looking for:
    • Matching eifs_bag_type_id
    • Less than 12 bags already created from block
  3. Returns first matching block ID, or -1 if none found

Why < 12 bags? Each EIFS block typically yields approximately 12 bags when cut.


make_eifs_bags()

Creates EIFS bag records and removes inventory.

function make_eifs_bags(
string $bag_type_label,
int $quantity,
int $job_id,
int $eifs_bag_type_id,
int $eifs_block_id = null,
int $add_job_id = null
): void

Logic:

  1. Find Bag Type:

    • Searches for bag type by label
    • Falls back to "default" bag type if not found
  2. Create EIFS Bags:

    $eifs_bags_created = create_eifs_bags(
    $eifs_bag_type_id,
    $bag_type->id,
    $quantity,
    $eifs_block_id,
    $add_job_id
    );
    • Creates quantity number of eifs_bag records
    • Associates with EIFS block if provided
  3. Remove Inventory:

    remove_sticker($sticker_type->id, $quantity, $job_id);
    remove_bag($bag_type->id, $quantity, $job_id);
    • Deducts printed stickers from inventory
    • Deducts packaging bags from inventory
    • Logs inventory removal
    • Creates notification if inventory insufficient

find_starting_number()

Calculates the starting sequential number for labels of a specific size.

function find_starting_number(array $data): int

Logic:

  1. Queries print_job table for matching:
    • job_id
    • size_value
    • label_name
    • size_numerator
    • size_denominator
  2. Sums all copies for matching records
  3. Returns sum + 1 (next sequential number)

Example: If 25 labels of "EPS 2"" have been printed, returns 26.


find_print_job_count()

Calculates total labels printed for entire job.

function find_print_job_count(int $job_id): int

Logic:

  1. Queries print_job table for all records with matching job_id
  2. Sums copies across all sizes/types
  3. Returns total count

Example: Job has printed 50 EPS 2", 30 GPS 4", returns 80.


Database Tables

Stores individual print job records sent to Print Maestro.

Key Fields:

  • id - Primary key
  • job_id - Foreign key to job table
  • label_name - Template name (e.g., "LotStickerEPS", "LotStickerGPSFrac", "LotStickerEPSDB")
  • copies - Number of labels to print
  • size_value - Whole number size (e.g., 2, 4)
  • size_numerator - Fraction numerator (0 if no fraction)
  • size_denominator - Fraction denominator (0 if no fraction)
  • bag_type - Packaging bag type label
  • pcs_per_bag / piece_count - Pieces per bag count
  • lot_number - Lot number for tracking
  • sales_order - Sales order number
  • customer - Customer name
  • size_total - Total labels for this specific size (padded: "025")
  • job_total - Total labels for entire job (padded: "150")
  • job_count - Sequential count across entire job (padded: "051")
  • size_count - Sequential count for this size (e.g., 1, 2, 3...)
  • print_type - Print job type:
    • 0 = Robopack print job
    • 1 = Manual EIFS print job
    • 2 = BuildBlock print job
    • 3 = CreteHeat print job
    • 4 = Manual shape mold print job
  • created_at - Timestamp

eifs_bag Table

Stores EIFS bag inventory records.

Key Fields:

  • id - Primary key
  • eifs_bag_type_id - Foreign key to eifs_bag_type (product size/type)
  • bag_type_id - Foreign key to bag_type (packaging bag)
  • eifs_block_id - Foreign key to eifs_block (source block)
  • add_job_id - Foreign key to job (job that created the bag)
  • created_at - Timestamp

Note: Each record represents a single EIFS bag in inventory.


eifs_bag_target Table

Stores production targets for EIFS jobs.

Key Fields:

  • id - Primary key
  • job_id - Foreign key to job
  • bag_type_id - Foreign key to eifs_bag_type
  • quantity - Target number of bags to produce

Note: Targets are set when EIFS job is created and drive the progress tracking.


eifs_block Table

Stores EIFS block records (cut blocks ready for bagging).

Key Fields:

  • id - Primary key
  • eifs_bag_type_id - Size/type this block will be cut into
  • block_id - Foreign key to source block
  • job_id - Job this block was cut for
  • date_used - When block was cut

Note: Each block typically yields ~12 bags.


Authentication & Authorization

Required Permissions:

  • User must be authenticated via CodeIgniter Shield
  • No specific group restrictions on Robopack pages
  • Access is typically available to production floor users

Session Management:

  • Uses CodeIgniter Shield for authentication
  • auth()->user() retrieves current user
  • User information passed to views for audit tracking

Error Handling

Validation Errors:

  • All API endpoints use CodeIgniter validation
  • Validation failures return failValidationErrors() response
  • Errors logged via log_message('error', ...)

Business Logic Errors:

  • EIFS bag type not found → Returns validation error with message
  • Job already complete → Redirects with warning message
  • Block not found → Creates notification but continues processing
  • Insufficient inventory → Logs error and creates notification

Logging:

log_message('info', 'Print job created');
log_message('info', 'Robo Pack EIFS bags created: ' . json_encode($eifs_bags_created));
log_message('info', 'Sticker and bag removed from inventory for print job');
log_message('error', 'EIFS bag type not found');
log_message('warning', 'Attempted to start completed job');