📌 4.1.4 Production Run Summary
📌

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:

  1. Review the system-calculated results of the run.

  2. Make controlled manual adjustments to:

    • Final good quantity

    • Final waste quantity

    • Waste breakdown (per event)

    • Downtime categories and reasons

  3. 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:

  1. 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.

  2. The run has been stopped in the monitoring view (machine is not running).

  3. 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:

  1. Cancel · Back to Monitoring

    • Discard unsaved changes.

    • Navigate back to Production Run Monitoring.

  2. 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):

  1. 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.

  2. Compute final totals

    • final_good = value from UI

    • final_waste = value from UI

    • final_total = final_good + final_waste

  3. 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

  4. 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

  5. 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.

  6. 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;
    
  7. 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;
    
  8. Reset Active Run ID tag

    • Write -1 to the UI tag that represents the active run:

      • Example: system.tag.writeAsync("UI/Run/ActiveRunId", -1)

  9. 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

  1. Implement the Run Summary view in Perspective following the sections above.

  2. 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.

  3. Implement gateway script / project library function to:

    • Validate, update run, insert into count_history, update state_history, recalc OEE, and reset tag.

  4. 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.