fix(native-alarms): a 4-column CSV import keeps stored MES overrides on the CLI path too (ScadaBridge#104)

The bulk SetInstanceNativeAlarmSourceOverridesCommand handler always wrote the
entry's IsMesReportableOverride, so a CLI import of a legacy 4-column CSV (no
MesReportable column) reset every imported source's MES override to inherit. The
Central UI avoided it only by looking up the stored flag client-side.

NativeAlarmSourceOverrideEntry gains an additive trailing KeepStoredMesReportable
flag: when set, the server leaves an existing row's MES override untouched (a new
row inherits) and ignores IsMesReportableOverride; unset keeps the old meaning
(null = clear to inherit), so older senders are unaffected. The CLI and the Central
UI now build their entries through one rule (ToOverrideEntry on each row type):
no MesReportable column => KeepStoredMesReportable. CLI README and
Component-CentralUI updated.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 15:41:33 -05:00
parent a81dac76ed
commit 063fb21815
11 changed files with 197 additions and 16 deletions
@@ -102,6 +102,25 @@ public class InstanceConfigureNativeAlarmCsvImportTests
Assert.Null(outcome.Rows[1].MesReportable);
}
/// <summary>
/// ScadaBridge#104: the UI sends the same entry as the CLI — a 4-column file leaves the MES
/// flag to the server (keep stored), a 5-column file specifies it.
/// </summary>
[Fact]
public void ImportRows_MapToTheSameEntriesAsTheCli()
{
var legacy = InstanceConfigure.BuildNativeAlarmSourceCsvImport(
NativeAlarmSourceOverrideCsvParser.Parse("SourceName,Connection,SourceReference,Filter\nBoilerAlarms,,,\n"),
Sources());
var withMes = InstanceConfigure.BuildNativeAlarmSourceCsvImport(
NativeAlarmSourceOverrideCsvParser.Parse("SourceName,Connection,SourceReference,Filter,MesReportable\nBoilerAlarms,,,,\n"),
Sources());
Assert.True(legacy.Rows[0].ToOverrideEntry().KeepStoredMesReportable);
Assert.False(withMes.Rows[0].ToOverrideEntry().KeepStoredMesReportable);
Assert.Null(withMes.Rows[0].ToOverrideEntry().IsMesReportableOverride);
}
/// <summary>Verifies that a row with all fields blank is marked as a clear.</summary>
[Fact]
public void AllBlankRow_IsMarkedAsClear()