chore: organize solution into module folders (Core/Server/Drivers/Client/Tooling)
Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Per Phase 7 plan decision #14 — persistent runtime state for each scripted alarm.
|
||||
/// Survives process restart so operators don't re-ack and ack history survives for
|
||||
/// GxP / 21 CFR Part 11 compliance. Keyed on <c>ScriptedAlarmId</c> logically (not
|
||||
/// per-generation) because ack state follows the alarm's stable identity across
|
||||
/// generations — a Modified alarm keeps its ack history.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <c>ActiveState</c> is deliberately NOT persisted — it rederives from the current
|
||||
/// predicate evaluation on startup. Only operator-supplied state (<see cref="AckedState"/>,
|
||||
/// <see cref="ConfirmedState"/>, <see cref="ShelvingState"/>) + audit trail persist.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <see cref="CommentsJson"/> is an append-only JSON array of <c>{user, utc, text}</c>
|
||||
/// tuples — one per operator comment. Core.ScriptedAlarms' <c>AlarmConditionState.Comments</c>
|
||||
/// serializes directly into this column.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class ScriptedAlarmState
|
||||
{
|
||||
/// <summary>Logical FK — matches <see cref="ScriptedAlarm.ScriptedAlarmId"/>. One row per alarm identity.</summary>
|
||||
public required string ScriptedAlarmId { get; set; }
|
||||
|
||||
/// <summary>Enabled/Disabled. Persists across restart per plan decision #14.</summary>
|
||||
public required string EnabledState { get; set; } = "Enabled";
|
||||
|
||||
/// <summary>Unacknowledged / Acknowledged.</summary>
|
||||
public required string AckedState { get; set; } = "Unacknowledged";
|
||||
|
||||
/// <summary>Unconfirmed / Confirmed.</summary>
|
||||
public required string ConfirmedState { get; set; } = "Unconfirmed";
|
||||
|
||||
/// <summary>Unshelved / OneShotShelved / TimedShelved.</summary>
|
||||
public required string ShelvingState { get; set; } = "Unshelved";
|
||||
|
||||
/// <summary>When a TimedShelve expires — null if not shelved or OneShotShelved.</summary>
|
||||
public DateTime? ShelvingExpiresUtc { get; set; }
|
||||
|
||||
/// <summary>User who last acknowledged. Null if never acked.</summary>
|
||||
public string? LastAckUser { get; set; }
|
||||
|
||||
/// <summary>Operator-supplied ack comment. Null if no comment or never acked.</summary>
|
||||
public string? LastAckComment { get; set; }
|
||||
|
||||
public DateTime? LastAckUtc { get; set; }
|
||||
|
||||
/// <summary>User who last confirmed.</summary>
|
||||
public string? LastConfirmUser { get; set; }
|
||||
|
||||
public string? LastConfirmComment { get; set; }
|
||||
|
||||
public DateTime? LastConfirmUtc { get; set; }
|
||||
|
||||
/// <summary>JSON array of operator comments, append-only (GxP audit).</summary>
|
||||
public string CommentsJson { get; set; } = "[]";
|
||||
|
||||
/// <summary>Row write timestamp — tracks last state change.</summary>
|
||||
public DateTime UpdatedAtUtc { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user