M-TRACK Manufacturing Control System - Complete Application Summary
Purpose
M-TRACK is an internal manufacturing control system for a shop floor environment. It manages jobs, components (parts), operations (work steps), inventory, and worker task assignments. The app is designed for two user types: Admins (managers who create jobs, assign work, and monitor production) and Workers (shop floor operators who execute tasks).
The system is self-hosted on a Windows machine and accessed remotely via web browser (including mobile devices on the shop floor).
Deployment
Self-hosted on a Windows machine
Remote web access via browser (desktop and mobile)
PostgreSQL database for data persistence
Single server process serves both the API and the frontend
Environment variable DATABASE_URL for database connection
Environment variable SESSION_SECRET for session encryption
Authentication & Access Control
Two-Tier Login System
Workers: Select their name from a dropdown on the landing page. No password required. Instant login for minimal friction on the shop floor.
Admins: Select their name, then must enter a 4-6 digit numeric PIN.
PIN Management
PINs are stored as bcrypt-hashed values in the database
Admins can set, reset, and initialize PINs for other admin users
A "Bootstrap" mode exists for first-time setup: if no admin has a PIN configured, the landing page shows a setup dialog to create/initialize the first admin account
Sessions
Express-session based with 24-hour expiration
Session data stored server-side (MemoryStore for development, database-backed sessions table available for production)
Role-Based Access
Two roles: admin and worker
Workers can only use the simplified login flow (no PIN)
Workers have an assignedProcesses array (e.g., ["cutting", "welding"]) that filters which operations they see in their work queue
Admin-only features: User management, inventory deletion, PIN management, time study reports, process type configuration, viewing all workers' queues
Core Data Model
Jobs
A job represents a manufacturing order (e.g., building a specific machine for a customer).
Fields:
Product name (the thing being built)
Customer name
Order number
Machine serial number
Description and details (free text)
Status: planned, in_progress, completed
Quantity (how many units to build, default 1)
Priority: integer 1-5 (1 = highest)
Due date
Is template flag (templates are reusable job blueprints)
Archived at timestamp (soft delete)
BOM file name and BOM file data (stored for re-download)
Components
A component is a part or subassembly within a job. Components form a tree hierarchy (parent-child relationships).
Fields:
Name
Type: "material" (raw part) or "assembly" (subassembly containing other parts)
Processes: array of strings (e.g., ["cutting", "bending", "welding"])
Status: pending, in_progress, completed
Quantity (default 1)
Job ID (belongs to a job)
Parent ID (self-referencing for hierarchy: assemblies contain sub-components)
Assigned to (user ID)
Notes (free text)
Thickness (e.g., '0.125"', '3mm')
Material (e.g., "Mild Steel", "Aluminum 6061")
Thumbnail data (base64 image extracted from BOM file)
Blueprint URL
Order index (display ordering)
Priority weight (1-100, default 50, higher = more important within the job)
Ready for assembly flag
Operations
An operation is a specific work step on a component (e.g., "Cut this part", "Weld this part").
Fields:
Component ID (belongs to a component)
Name (descriptive task name)
Process type (e.g., "cutting", "Sheetmetal cutting", "bending", "welding", "machining", "assembly")
Priority tiers assigned by days until due: hot (<=2 days), urgent (<=5 days), normal (<=14 days), backlog (>14 days)
Recalculation can be triggered manually via API
5. Batch Task Grouping (Cutting Operations Only)
What Gets Batched:
ONLY operations where the process type contains "cutting" or "cut" (case-insensitive), or equals "material"
Examples that batch: "cutting", "Sheetmetal cutting", "Steel Tube cutting", "material"
Examples that do NOT batch: "bending", "welding", "machining", "assembly"
Grouping Criteria:
Operations are grouped by: Process Type + Material + Thickness + Job ID
All operations sharing these attributes become a single batch that workers can start/complete together
Why Batching Exists:
In manufacturing, cutting is often done on a single machine for all parts of the same material and thickness
A worker sets up the machine once and cuts all parts, rather than switching materials repeatedly
Batch Display:
Batches show a count of operations (e.g., "12 parts")
Individual parts within a batch are listed for reference
6. Task Naming Format (Two-Line Display)
All work items (batches and individual operations) are displayed in a consistent two-line format:
Line 1 (Title):[Process] [Product] [Main Assembly] [Sub-Assembly]
Process: "Cut" for cutting/material operations, otherwise the capitalized process name
Product: The job's product name
Main Assembly: The top-level assembly name (if the component has a parent hierarchy)
Sub-Assembly: The intermediate assembly name (if applicable)
Line 2 (Subtitle):[Thickness] [Material] - [Customer] - [Serial Number]
Parts are separated by " - " dash separators
Empty parts are omitted
Thickness: Displayed exactly as it comes from the BOM, with " in" suffix converted to double-quote (") for inches
7. Worker Queue / "Next Work" View
Purpose:
Shows each worker a prioritized list of tasks they should work on next
Filtered to only show operations matching the worker's assigned processes
Three Sections:
In Progress: Tasks the worker has already started
Stalled: Tasks that are paused with a reason
Pending: Tasks available to start, ordered by priority
Mixed Content:
Cutting batches (grouped by material + thickness + job) appear as single items
All other operations (welding, bending, machining, assembly) appear as individual items
Both types are interleaved in a single prioritized list
Priority Ordering:
In-progress items appear at the top
Higher job priority (lower number) comes first
Earlier due dates come first (no due date goes to bottom)
Blocked items are pushed to the bottom with a reason displayed
Worker Actions:
Start: Moves operation(s) from pending to in_progress, assigns to the current worker, records a time study "start" event
Stalled: Pauses work; worker MUST provide a reason (e.g., "missing hardware", "machine down"). Records a time study "stalled" event
Done (Complete): Marks operation(s) as completed with timestamp. Records a time study "completed" event. For batches, all operations in the batch are completed simultaneously
Resume: Moves stalled tasks back to in_progress
Admin View:
Admins can select any worker from a dropdown to view their queue
Admins can reassign batches to different workers
8. Shop Floor View
Two Modes:
Batch View (Task-Based):
Shows all cutting batches grouped by material + thickness
Filter by process type
Mark batches as complete or stalled
Shows in-progress work at the top
Kanban Board (Component-Based):
Three columns: Pending, In Progress, Completed
Drag-and-drop components between columns to update status
Uses @hello-pangea/dnd library
Filter by process type
Expand components to view and manage subtasks
9. Dashboard
Stat Cards (Clickable):
Active Jobs: Count of in_progress jobs (click to see list)
Completed Units: Count of completed jobs (click to see list)
Low Stock Alert: Count of consumables below reorder level (click to see list)
Total Jobs: Total job count (click to see list)
Charts:
Job Status Bar Chart: Planned vs In Progress vs Completed job counts (using Recharts)
Recent Jobs List: 5 most recent jobs with status badges
Work Management:
Workers see their assigned "Next Work" items
Admins see a global view of all in-progress and stalled work
Admins can select specific workers to view their assigned work
Start/Stall/Done actions available directly from the dashboard
In-progress work section highlighted at the top
Job Detail Dialog:
Click a job to see metadata (quantity, due date, serial number)
Breakdown of incomplete vs completed tasks
10. Inventory Management
Three Categories (Tabs):
Materials: Raw materials (steel, aluminum, etc.)
Manufactured Parts: Parts produced in-house (machined parts with stock tracking)
Cutting operations batch together by material + thickness + job. All other processes are individual operations.
Operation blocking prevents workers from starting work out of sequence. Sequential order within a component, assembly hierarchy, and explicit cross-component dependencies all contribute to blocking.
BOM updates preserve existing work. Re-importing a BOM updates metadata but does not delete operations that have already been started or completed.
Machined parts can be fulfilled from inventory instead of re-machining, saving production time.
Reorder alerts fire automatically when stock hits the reorder point, but can also be triggered manually via QR scan.
Priority scoring is automatic based on due date and component weight, but jobs also have a manual priority override (1-5).
Workers only see operations matching their assigned processes. A worker assigned to "cutting" and "bending" won't see welding tasks.
Admins can override operation blocking with a reason and optional expiration time.
Time study events are created automatically whenever a worker starts, stalls, or completes an operation.
Process types are configurable - admins can add new process types without code changes.
API Overview
Authentication
POST /api/login - Worker login (select user, no PIN)
POST /api/auth/login-with-pin - Admin login with PIN
GET /api/auth/user - Get current session user
POST /api/logout - End session
GET /api/auth/bootstrap-status - Check if first-time setup needed
POST /api/auth/bootstrap-initialize - Create/initialize first admin
GET /api/auth/check-pin/:userId - Check if user requires PIN
POST /api/auth/set-pin - Set own PIN
POST /api/auth/reset-pin/:userId - Admin reset another user's PIN
POST /api/auth/initialize-pin/:userId - Admin set PIN for another user
POST /api/auth/complete-tutorial - Mark tutorial complete
POST /api/auth/reset-tutorial - Reset tutorial for current user
Users
GET /api/users - List all users
POST /api/users - Create user (username, role, assignedProcesses)
PATCH /api/users/:id - Update user
Jobs
GET /api/jobs - List jobs (query: isTemplate=true/false)
GET /api/jobs/:id - Get single job
POST /api/jobs - Create job
PATCH /api/jobs/:id - Update job
DELETE /api/jobs/:id - Delete job
POST /api/jobs/:id/archive - Soft delete
POST /api/jobs/:id/unarchive - Restore archived job
GET /api/jobs/archived - List archived jobs
POST /api/jobs/:id/instantiate - Create job from template
POST /api/jobs/:id/save-template - Save job as template
POST /api/jobs/import-bom - Import BOM file (multipart/form-data)
GET /api/jobs/:id/bom - Download original BOM file
POST /api/jobs/:id/bom/update - Re-import BOM preserving existing work
Components
GET /api/components - List (query: jobId, assignedTo)
POST /api/components - Create component
PATCH /api/components/:id - Update component
DELETE /api/components/:id - Delete component
POST /api/components/move - Move component to new parent
Operations
GET /api/operations - List (query: componentId)
GET /api/operations/:id - Get single operation
POST /api/operations - Create operation
PATCH /api/operations/:id - Update operation
DELETE /api/operations/:id - Delete operation
POST /api/operations/reorder - Reorder operations within a component
POST /api/operations/bulk - Bulk create operations across components
The "isCuttingProcess" helper must use case-insensitive matching. Check if processType.toLowerCase() includes "cutting" or "cut", OR equals "material". This is critical for batch grouping to work with process types like "Sheetmetal cutting" or "Steel Tube cutting".
BOM import uses two libraries: xlsx for reading spreadsheet data, and exceljs for extracting embedded images (thumbnails). They serve different purposes and both are needed.
The worker queue mixes batched and individual items in a single prioritized list. Cutting operations are grouped into batches; everything else is individual. This is the "Next Work" endpoint.
Operation status transitions: pending -> in_progress -> completed (or stalled from in_progress, then resumed back to in_progress). The "skipped" status exists for operations bypassed via inventory fulfillment.
The task naming two-line format must use " (double quote character) instead of "in" for inches in thickness. The thickness value should be displayed as it comes from the BOM with this one normalization.
Subtitle parts are joined with " - " (space dash space) as separators. Empty parts are omitted entirely.
Assembly blocking: An operation on an "assembly" type component is blocked until ALL child components (and their children, recursively) have status "completed".
Session-based auth means the server must support sessions. The worker login flow explicitly prevents admin role users from using it (they must use PIN).
Inventory auto-numbering assigns the next available number in the category range when creating new items.
Reorder alerts deduplicate - the system should check for existing pending alerts before creating duplicates.
BOM update (re-import) preserves work - when updating a BOM, existing operations with status in_progress or completed must not be deleted. Only add new components, remove components that no longer exist in the BOM, and update metadata on existing ones.
The priority recalculation processes all active (non-template, non-archived) jobs and updates every operation's priorityScore and priorityTier based on current date vs. due date.