4.1.4 Production Run Summary
https://chatgpt.com/canvas/shared/6930610a9424819180379069e4baad0f
4.1.4.1 Purpose & Scope
The Production Run Summary view is the final step of the operator workflow for a production run.
Its purpose is to let the operator:
Review the system-calculated results of the run.
Make controlled manual adjustments to:
Final good quantity
Final waste quantity
Waste breakdown (per event)
Downtime categories and reasons
Confirm and close the run.
When the operator presses Confirm & Close Run, the system will:
Write final values into the run table.
Insert adjustment records into count_history.
Update downtime categorisation and comments in state_history.
Recalculate Availability, Performance, Quality, and OEE at the run level and store them in the run table.
Reset the “active run” tag to -1 to indicate that there is no longer an active run on this line.
This view is a separate page / popup reached from Production Run Monitoring after the operator presses “End Run / Summary”.
4.1.4.2 Entry Conditions & Exit Conditions
Entry Conditions
The view is available when all of the following are true:
There is an active run on the current line:
UI/Edge tag (example):
UI/Run/ActiveRunId (integer)
> 0 means an active run
Corresponding record exists in run with run.id = ActiveRunId.
The run has been stopped in the monitoring view (machine is not running).
The operator has permission to perform run closing / adjustments.
Exit Conditions
Confirm & Close Run
run record is updated with final quantities and OEE.
Adjustment rows are written to count_history.
Downtime categorization and comments are saved to state_history.
run.closed is set to true (1).
Active run tag is set to -1.
Navigation returns to Production Run Monitoring (run list / idle state).
Cancel · Back to Monitoring
No database or tag changes.
Navigation returns to Production Run Monitoring with the same active run still open.
4.1.4.3 UI Layout Overview
The React mockup you provided is the visual reference. In Ignition Perspective, the layout should be replicated using Flex / Coordinate containers and standard components.
1. Top Header Bar
Purpose: Context for the operator.
Elements:
Application identity: “Nova MFG · Operator Interface”.
Page title: “Production Run Summary”.
Subtitle: “Review and finalize production data before closing the run.”
Theme toggle (Light / Dark)
In real Ignition it can be:
A session property (e.g. session.custom.theme)
Used to select a style class set.
Line info:
Example: Line A · Press 103
Source: line table (name, short_name) via the schedule.line_id relationship.
Operator info:
Example: OPR-001 · Somchai
Source: current logged-in user / Identity Provider.
Status pill:
Text: “Review & Adjust Before Closing”
Color indicates “pending confirmation”.
2. Run Header Summary (Read-Only)
Grid of read-only fields:
Work Order
Example: WO-000123
Source: work_order.work_order.
Product
Example: P-1001 · Housing 12mm
Source: product_code.product_code, product_code.description.
Scheduled Qty
Source: work_order.quantity.
Run Window
Example: 08:00 — 10:15
Source: run.run_start_datetime, run.run_stop_datetime.
Final Good / Waste / Total
Display from adjusted values:
Good: run.good_count
Waste: run.waste_count
Total: run.total_count = good_count + waste_count.
Only the Run Adjustments section is editable; this header should always reflect the current adjusted values.
3. Left Column
3.1 Section 1 – Run Adjustments
Fields:
System good count (read-only)
Initial source: run.total_count or run.good_count as calculated by Dispatch logic before operator adjustment.
Shown as “System good count”.
Final good (adjusted) (editable numeric)
Operator input.
On load, prefilled with current run.good_count.
Delta vs system (good)
UI-computed value:
good_delta = final_good_adjusted - system_good_count.
Displayed as +10 pcs vs system style.
System waste (read-only)
Initial source: system waste before adjustment, usually run.waste_count or computed from count_history.
Final waste (adjusted) (editable numeric)
Operator input.
On load, prefilled with current run.waste_count.
Delta vs system (waste)
UI-computed:
waste_delta = final_waste_adjusted - system_waste.
Informational note:
“These adjustments will be written to the run table and logged as count history when you confirm.”
3.2 Section 2 – Waste / Reject Details
Table of per-event waste entries:
Columns:
Time (from count event timestamp or derived event time).
Qty (pieces).
Reason (operator-selected text).
Comment (free text).
Actions (Edit / Delete).
Buttons:
+ Add Waste Entry
Opens a small popup or inline row to add a new waste record (quantity, reason, comment).
4. Right Column
4.1 Section 3 – Downtime Review & Categorization
Table listing downtime events for the run:
Source: state_history where run_id = :activeRunId.
Columns:
Start (datetime)
End (datetime)
Duration (calculated in UI)
Category (Planned / Unplanned / Setup – select)
Reason (select list)
Comment (editable text)
Above the table, an indicator:
“X events uncategorized”
Count of state_history rows where state_reason_id is null/unknown or mapped to “Unknown” reason.
Reason selection:
Dropdown values from state_reason where:
line_id = current line
operator_selectable = true
When the operator changes Category or Reason, the row is marked “dirty” and will be written back on Confirm.
4.2 Section 4 – Final Totals & OEE
Read-only KPIs derived from adjusted values and existing run timing:
Fields:
Good (final) → run.good_count
Reject (final) → run.waste_count
Total output → run.total_count
Run duration → run.runtime or derived from run_start_datetime / run_stop_datetime.
OEE breakdown (run-level):
Availability (A) → run.availability
Performance (P) → run.performance
Quality (Q) → run.quality
OEE → run.oee
These are recalculated in the UI logic (see section 4.1.4.6) and written back to the run record at confirmation time.
5. Bottom Action Bar
Text:
Description of what Confirm will do (write to run, log count history, update downtime reasons, recalc OEE, reset Run ID to -1).
Buttons:
Cancel · Back to Monitoring
Discard unsaved changes.
Navigate back to Production Run Monitoring.
Confirm & Close Run
Execute the save logic (section 4.1.4.6) then navigate back.
4.1.4.4 Data Model & Source Mapping
Core Tables Involved
From MES_Core_V1.0 schema:
run
id (PK)
schedule_id
Timing fields: run_start_datetime, run_stop_datetime, runtime, total_time, unplanned_downtime, planned_downtime
Counts: total_count, waste_count, good_count
OEE: availability, performance, quality, oee
Status: closed
schedule
id, line_id, work_order_id, schedule_start_datetime, schedule_finish_datetime, quantity, etc.
work_order
id, product_code_id, work_order, quantity, closed, hide
product_code
id, product_code, description
product_code_line
id, line_id, product_code_id, idealcycletime
line
id, name, short_name, tagpath
count_type
id, count_type (values like infeed, outfeed, waste)
count_tag
id, line_id, tag_path
count_history
id, count_tag_id, count_type_id, run_id, count, timestamp
state_history
id, line_id, state_reason_id, run_id, start_datetime, end_datetime,
reason_name, reason_code, note
state_reason
id, line_id, reason_name, reason_code, record_downtime,
planned_downtime, operator_selectable, sub_reason_of, reason_color
Tag Involved
Active Run ID Tag (example path)
UI/Run/ActiveRunId (Int)
> 0 → current run id
-1 → no active run (after closing)
Note: actual tag path to be aligned with your UI UDT design.
4.1.4.5 Suggested SQL (Conceptual)
Below is indicative SQL – devs can convert to Named Queries.
1) Load Run Header
SELECT
r.id AS run_id,
r.run_start_datetime,
r.run_stop_datetime,
r.total_count,
r.good_count,
r.waste_count,
r.runtime,
r.total_time,
r.availability,
r.performance,
r.quality,
r.oee,
wo.work_order,
wo.quantity AS work_order_quantity,
pc.product_code,
pc.description AS product_description,
s.quantity AS schedule_quantity,
s.schedule_start_datetime,
s.schedule_finish_datetime,
l.name AS line_name,
l.short_name AS line_short_name
FROM run r
JOIN schedule s ON s.id = r.schedule_id
JOIN work_order wo ON wo.id = s.work_order_id
JOIN product_code pc ON pc.id = wo.product_code_id
JOIN line l ON l.id = s.line_id
WHERE r.id = :runId;
2) Load Waste Events (Per-Run)
We model waste events as count_history rows with count_type = 'waste':
SELECT
ch.id,
ch.timestamp,
ch.count,
ct.count_type,
ch.count_tag_id
FROM count_history ch
JOIN count_type ct ON ct.id = ch.count_type_id
WHERE ch.run_id = :runId
AND ct.count_type = 'waste'
ORDER BY ch.timestamp;
3) Load Downtime Events (Per-Run)
SELECT
sh.id,
sh.start_datetime,
sh.end_datetime,
sh.state_reason_id,
sh.reason_name,
sh.reason_code,
sh.note
FROM state_history sh
WHERE sh.run_id = :runId
ORDER BY sh.start_datetime;
4) Load Available Downtime Reasons for the Line
SELECT
sr.id,
sr.reason_name,
sr.reason_code,
sr.planned_downtime,
sr.record_downtime
FROM state_reason sr
WHERE sr.line_id = :lineId
AND sr.operator_selectable = TRUE
ORDER BY sr.reason_code;
4.1.4.6 Behaviour on Confirm & Close Run
When the operator presses Confirm & Close Run, execute the following steps (in a gateway script or transaction):
Validate inputs
All required downtime events have a valid state_reason_id (not “Unknown” if you enforce it).
Final good and waste values are numeric and non-negative.
Compute final totals
final_good = value from UI
final_waste = value from UI
final_total = final_good + final_waste
Compute deltas vs system
Let:
system_good = original good count used to prefill.
system_waste = original waste count.
Then:
delta_good = final_good - system_good
delta_waste = final_waste - system_waste
Update run table
good_count = final_good
waste_count = final_waste
total_count = final_total
Optionally update run_stop_datetime and runtime if not finalised.
closed = 1
Insert adjustment rows into count_history (if deltas ≠ 0)
For each non-zero delta:
Locate proper count_type_id:
For good count delta: count_type.count_type = 'outfeed' (or equivalent business rule).
For waste delta: count_type.count_type = 'waste'.
Determine count_tag_id:
Use the same count_tag_id that was used for this run and type (e.g. last matching count_history entry).
Insert row(s):
INSERT INTO count_history (count_tag_id, count_type_id, run_id, count, timestamp) VALUES (:countTagId, :countTypeId, :runId, :deltaValue, NOW());
where :deltaValue is delta_good or delta_waste.
Persist downtime categorization
For each edited downtime row in the UI:
Given state_history.id = :stateHistoryId
And selected state_reason.id = :stateReasonId
UPDATE state_history SET state_reason_id = :stateReasonId, reason_name = :reasonName, -- from state_reason reason_code = :reasonCode, -- from state_reason note = :comment -- from operator input WHERE id = :stateHistoryId;
Recalculate OEE (run-level) and update run
Inputs:
total_time → from run.total_time (seconds or minutes, consistent with your design)
runtime → from run.runtime
good_count → final_good
total_count → final_total
idealcycletime → from product_code_line.idealcycletime for the specific line + product.
Formulas (in UI or script):
Availability (A)
A = runtime / total_time
Performance (P)
Let ideal_output = total_time / idealcycletime (adjust for units).
P = total_count / ideal_output
Quality (Q)
Q = good_count / total_count
OEE
OEE = A * P * Q
Round as appropriate (e.g. to 0.1%).
Then update:
UPDATE run SET availability = :A, performance = :P, quality = :Q, oee = :OEE WHERE id = :runId;
Reset Active Run ID tag
Write -1 to the UI tag that represents the active run:
Example: system.tag.writeAsync("UI/Run/ActiveRunId", -1)
Navigate back
Redirect the operator to Production Run Monitoring for the same line.
The monitoring view should now show “no active run” state.
4.1.4.7 Validation & Error Handling
If final_total = 0, show a warning and optionally block confirmation.
If any downtime row lacks a valid reason and your policy requires it:
Show “All downtime events must be categorized before closing the run.”
If database writes fail:
Show error message and keep the view open.
Do not reset ActiveRunId to -1 in this case.
If someone else already closed the run (concurrency):
Reload data and show “Run already closed by another user.”
4.1.4.8 Developer Checklist
Implement the Run Summary view in Perspective following the sections above.
Create Named Queries (or scripts) for:
Load run header
Load waste events (count_history with count_type = 'waste')
Load downtime list (state_history)
Load downtime reasons (state_reason)
Save adjustments (+ OEE) transaction.
Implement gateway script / project library function to:
Validate, update run, insert into count_history, update state_history, recalc OEE, and reset tag.
Ensure the End Run button in Production Run Monitoring navigates to this view with runId and lineId parameters bound from:
UI/Run/ActiveRunId
line context.