feat(native-alarms): per-binding IsMesReportable on native alarm source bindings (ScadaBridge#59)
TemplateNativeAlarmSource.IsMesReportable + tri-state InstanceNativeAlarmSourceOverride .IsMesReportableOverride flatten onto ResolvedNativeAlarmSource; NativeAlarmActor stamps every mirrored condition and InstanceActor the quiet-binding placeholder, so ScriptAlarm, Alarms.MesReportableAsync() and the #60 wire fields carry it. Additive to the 900-999 severity band. Migration AddNativeAlarmSourceMesReportable. Management commands, CLI --mes-reportable, Central UI (template dialog checkbox, instance override select), Transport DTOs/importer/diff and the revision hash (true-only, so existing hashes are unchanged) carry it. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -4706,6 +4706,37 @@ public class ManagementActorTests : TestKit, IDisposable
|
||||
_templateRepo.ReceivedWithAnyArgs(1).SaveChangesAsync(default);
|
||||
}
|
||||
|
||||
/// <summary>Gitea #59: the instance override command carries IsMesReportableOverride onto the persisted row.</summary>
|
||||
[Fact]
|
||||
public void SetInstanceNativeAlarmSourceOverride_CarriesIsMesReportableOverride()
|
||||
{
|
||||
var pipeline = Substitute.For<IFlatteningPipeline>();
|
||||
var flattened = new FlattenedConfiguration
|
||||
{
|
||||
NativeAlarmSources = new List<ResolvedNativeAlarmSource>
|
||||
{
|
||||
new() { CanonicalName = "Pressure", IsLocked = false, Source = "Template" }
|
||||
}
|
||||
};
|
||||
pipeline.FlattenAndValidateAsync(1, Arg.Any<CancellationToken>(), Arg.Any<bool>())
|
||||
.Returns(Result<FlatteningPipelineResult>.Success(
|
||||
new FlatteningPipelineResult(flattened, "hash", ValidationResult.Success())));
|
||||
_services.AddScoped(_ => pipeline);
|
||||
|
||||
InstanceNativeAlarmSourceOverride? added = null;
|
||||
_templateRepo
|
||||
.When(r => r.AddInstanceNativeAlarmSourceOverrideAsync(Arg.Any<InstanceNativeAlarmSourceOverride>(), Arg.Any<CancellationToken>()))
|
||||
.Do(ci => added = ci.Arg<InstanceNativeAlarmSourceOverride>());
|
||||
|
||||
CreateActor().Tell(Envelope(
|
||||
new SetInstanceNativeAlarmSourceOverrideCommand(1, "Pressure", null, null, null, IsMesReportableOverride: true),
|
||||
"Deployer"));
|
||||
|
||||
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
Assert.NotNull(added);
|
||||
Assert.True(added!.IsMesReportableOverride);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that set instance native alarm source override, when with design role, returns unauthorized.</summary>
|
||||
[Fact]
|
||||
public void SetInstanceNativeAlarmSourceOverride_WithDesignRole_ReturnsUnauthorized()
|
||||
|
||||
+19
@@ -50,6 +50,25 @@ public class NativeAlarmSourceNameValidationTests : TestKit
|
||||
_repo.DidNotReceive().AddTemplateNativeAlarmSourceAsync(Arg.Any<TemplateNativeAlarmSource>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
/// <summary>Gitea #59: the update command carries IsMesReportable onto the persisted binding.</summary>
|
||||
[Fact]
|
||||
public void Update_CarriesIsMesReportable()
|
||||
{
|
||||
TemplateNativeAlarmSource? updated = null;
|
||||
_repo.When(r => r.UpdateTemplateNativeAlarmSourceAsync(Arg.Any<TemplateNativeAlarmSource>(), Arg.Any<CancellationToken>()))
|
||||
.Do(ci => updated = ci.Arg<TemplateNativeAlarmSource>());
|
||||
_services.AddScoped<ZB.MOM.WW.ScadaBridge.TemplateEngine.TemplateService>();
|
||||
|
||||
CreateActor().Tell(Designer(new UpdateTemplateNativeAlarmSourceCommand(
|
||||
4, "Pressure", "Opc", "ns=2;s=T01", null, null, false, IsMesReportable: true)));
|
||||
|
||||
// The reconcile that follows needs TemplateService collaborators this harness does not
|
||||
// wire, so only the persisted binding is asserted (the Update call precedes the reconcile).
|
||||
ExpectMsg<object>(TimeSpan.FromSeconds(5));
|
||||
Assert.NotNull(updated);
|
||||
Assert.True(updated!.IsMesReportable);
|
||||
}
|
||||
|
||||
/// <summary>Renaming a source to an illegal actor name is rejected before any write.</summary>
|
||||
[Fact]
|
||||
public void Update_RenameToInvalidActorName_IsRejected()
|
||||
|
||||
Reference in New Issue
Block a user