feat(management): handlers for native alarm source CRUD
This commit is contained in:
@@ -183,6 +183,7 @@ public class ManagementActor : ReceiveActor
|
||||
or DeleteDataConnectionCommand
|
||||
or AddTemplateAttributeCommand or UpdateTemplateAttributeCommand or DeleteTemplateAttributeCommand
|
||||
or AddTemplateAlarmCommand or UpdateTemplateAlarmCommand or DeleteTemplateAlarmCommand
|
||||
or AddTemplateNativeAlarmSourceCommand or UpdateTemplateNativeAlarmSourceCommand or DeleteTemplateNativeAlarmSourceCommand
|
||||
or AddTemplateScriptCommand or UpdateTemplateScriptCommand or DeleteTemplateScriptCommand
|
||||
or AddTemplateCompositionCommand or DeleteTemplateCompositionCommand
|
||||
or CreateSharedScriptCommand or UpdateSharedScriptCommand or DeleteSharedScriptCommand
|
||||
@@ -204,6 +205,7 @@ public class ManagementActor : ReceiveActor
|
||||
or MgmtDisableInstanceCommand or MgmtDeleteInstanceCommand
|
||||
or SetConnectionBindingsCommand or SetInstanceOverridesCommand or SetInstanceAreaCommand
|
||||
or SetInstanceAlarmOverrideCommand or DeleteInstanceAlarmOverrideCommand
|
||||
or SetInstanceNativeAlarmSourceOverrideCommand or DeleteInstanceNativeAlarmSourceOverrideCommand
|
||||
or GetDeploymentDiffCommand
|
||||
or MgmtDeployArtifactsCommand
|
||||
or QueryDeploymentsCommand
|
||||
@@ -233,6 +235,10 @@ public class ManagementActor : ReceiveActor
|
||||
AddTemplateAlarmCommand cmd => await HandleAddAlarm(sp, cmd, user.Username),
|
||||
UpdateTemplateAlarmCommand cmd => await HandleUpdateAlarm(sp, cmd, user.Username),
|
||||
DeleteTemplateAlarmCommand cmd => await HandleDeleteAlarm(sp, cmd, user.Username),
|
||||
AddTemplateNativeAlarmSourceCommand cmd => await HandleAddNativeAlarmSource(sp, cmd),
|
||||
UpdateTemplateNativeAlarmSourceCommand cmd => await HandleUpdateNativeAlarmSource(sp, cmd),
|
||||
DeleteTemplateNativeAlarmSourceCommand cmd => await HandleDeleteNativeAlarmSource(sp, cmd),
|
||||
ListTemplateNativeAlarmSourcesCommand cmd => await HandleListNativeAlarmSources(sp, cmd),
|
||||
AddTemplateScriptCommand cmd => await HandleAddScript(sp, cmd, user.Username),
|
||||
UpdateTemplateScriptCommand cmd => await HandleUpdateScript(sp, cmd, user.Username),
|
||||
DeleteTemplateScriptCommand cmd => await HandleDeleteScript(sp, cmd, user.Username),
|
||||
@@ -261,6 +267,9 @@ public class ManagementActor : ReceiveActor
|
||||
SetInstanceAlarmOverrideCommand cmd => await HandleSetInstanceAlarmOverride(sp, cmd, user),
|
||||
DeleteInstanceAlarmOverrideCommand cmd => await HandleDeleteInstanceAlarmOverride(sp, cmd, user),
|
||||
ListInstanceAlarmOverridesCommand cmd => await HandleListInstanceAlarmOverrides(sp, cmd, user),
|
||||
SetInstanceNativeAlarmSourceOverrideCommand cmd => await HandleSetInstanceNativeAlarmSourceOverride(sp, cmd, user),
|
||||
DeleteInstanceNativeAlarmSourceOverrideCommand cmd => await HandleDeleteInstanceNativeAlarmSourceOverride(sp, cmd, user),
|
||||
ListInstanceNativeAlarmSourceOverridesCommand cmd => await HandleListInstanceNativeAlarmSourceOverrides(sp, cmd, user),
|
||||
|
||||
// Sites
|
||||
ListSitesCommand => await HandleListSites(sp, user),
|
||||
@@ -765,6 +774,58 @@ public class ManagementActor : ReceiveActor
|
||||
return await repo.GetAlarmOverridesByInstanceIdAsync(cmd.InstanceId);
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleSetInstanceNativeAlarmSourceOverride(
|
||||
IServiceProvider sp, SetInstanceNativeAlarmSourceOverrideCommand cmd, AuthenticatedUser user)
|
||||
{
|
||||
await EnforceSiteScopeForInstance(sp, user, cmd.InstanceId);
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
|
||||
var existing = await repo.GetNativeAlarmSourceOverrideAsync(cmd.InstanceId, cmd.SourceCanonicalName);
|
||||
if (existing == null)
|
||||
{
|
||||
var ovr = new InstanceNativeAlarmSourceOverride(cmd.SourceCanonicalName)
|
||||
{
|
||||
InstanceId = cmd.InstanceId,
|
||||
ConnectionNameOverride = cmd.ConnectionNameOverride,
|
||||
SourceReferenceOverride = cmd.SourceReferenceOverride,
|
||||
ConditionFilterOverride = cmd.ConditionFilterOverride
|
||||
};
|
||||
await repo.AddInstanceNativeAlarmSourceOverrideAsync(ovr);
|
||||
await repo.SaveChangesAsync();
|
||||
return ovr;
|
||||
}
|
||||
|
||||
existing.ConnectionNameOverride = cmd.ConnectionNameOverride;
|
||||
existing.SourceReferenceOverride = cmd.SourceReferenceOverride;
|
||||
existing.ConditionFilterOverride = cmd.ConditionFilterOverride;
|
||||
await repo.UpdateInstanceNativeAlarmSourceOverrideAsync(existing);
|
||||
await repo.SaveChangesAsync();
|
||||
return existing;
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleDeleteInstanceNativeAlarmSourceOverride(
|
||||
IServiceProvider sp, DeleteInstanceNativeAlarmSourceOverrideCommand cmd, AuthenticatedUser user)
|
||||
{
|
||||
await EnforceSiteScopeForInstance(sp, user, cmd.InstanceId);
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
|
||||
var existing = await repo.GetNativeAlarmSourceOverrideAsync(cmd.InstanceId, cmd.SourceCanonicalName);
|
||||
if (existing != null)
|
||||
{
|
||||
await repo.DeleteInstanceNativeAlarmSourceOverrideAsync(existing.Id);
|
||||
await repo.SaveChangesAsync();
|
||||
}
|
||||
return cmd.SourceCanonicalName;
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleListInstanceNativeAlarmSourceOverrides(
|
||||
IServiceProvider sp, ListInstanceNativeAlarmSourceOverridesCommand cmd, AuthenticatedUser user)
|
||||
{
|
||||
await EnforceSiteScopeForInstance(sp, user, cmd.InstanceId);
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
return await repo.GetNativeAlarmSourceOverridesByInstanceIdAsync(cmd.InstanceId);
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleGetDeploymentDiff(IServiceProvider sp, GetDeploymentDiffCommand cmd, AuthenticatedUser user)
|
||||
{
|
||||
await EnforceSiteScopeForInstance(sp, user, cmd.InstanceId);
|
||||
@@ -1449,6 +1510,55 @@ public class ManagementActor : ReceiveActor
|
||||
return result.IsSuccess ? result.Value : throw new ManagementCommandException(result.Error);
|
||||
}
|
||||
|
||||
// ── Native alarm source bindings (read-only mirror; repository-direct CRUD) ──
|
||||
|
||||
private static async Task<object?> HandleAddNativeAlarmSource(IServiceProvider sp, AddTemplateNativeAlarmSourceCommand cmd)
|
||||
{
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
var source = new TemplateNativeAlarmSource(cmd.Name)
|
||||
{
|
||||
TemplateId = cmd.TemplateId,
|
||||
ConnectionName = cmd.ConnectionName,
|
||||
SourceReference = cmd.SourceReference,
|
||||
ConditionFilter = cmd.ConditionFilter,
|
||||
Description = cmd.Description,
|
||||
IsLocked = cmd.IsLocked
|
||||
};
|
||||
await repo.AddTemplateNativeAlarmSourceAsync(source);
|
||||
await repo.SaveChangesAsync();
|
||||
return source;
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleUpdateNativeAlarmSource(IServiceProvider sp, UpdateTemplateNativeAlarmSourceCommand cmd)
|
||||
{
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
var source = await repo.GetTemplateNativeAlarmSourceByIdAsync(cmd.NativeAlarmSourceId)
|
||||
?? throw new ManagementCommandException($"Native alarm source {cmd.NativeAlarmSourceId} not found.");
|
||||
source.Name = cmd.Name;
|
||||
source.ConnectionName = cmd.ConnectionName;
|
||||
source.SourceReference = cmd.SourceReference;
|
||||
source.ConditionFilter = cmd.ConditionFilter;
|
||||
source.Description = cmd.Description;
|
||||
source.IsLocked = cmd.IsLocked;
|
||||
await repo.UpdateTemplateNativeAlarmSourceAsync(source);
|
||||
await repo.SaveChangesAsync();
|
||||
return source;
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleDeleteNativeAlarmSource(IServiceProvider sp, DeleteTemplateNativeAlarmSourceCommand cmd)
|
||||
{
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
await repo.DeleteTemplateNativeAlarmSourceAsync(cmd.NativeAlarmSourceId);
|
||||
await repo.SaveChangesAsync();
|
||||
return cmd.NativeAlarmSourceId;
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleListNativeAlarmSources(IServiceProvider sp, ListTemplateNativeAlarmSourcesCommand cmd)
|
||||
{
|
||||
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
||||
return await repo.GetNativeAlarmSourcesByTemplateIdAsync(cmd.TemplateId);
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleAddScript(IServiceProvider sp, AddTemplateScriptCommand cmd, string user)
|
||||
{
|
||||
var svc = sp.GetRequiredService<TemplateService>();
|
||||
|
||||
@@ -1416,4 +1416,85 @@ public class ManagementActorTests : TestKit, IDisposable
|
||||
// earlier Modified row's Overwrite action.
|
||||
Assert.Equal(Commons.Types.Transport.ResolutionAction.Skip, dupResolutions[0].Action);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Native alarm source CRUD (Task 21)
|
||||
// ========================================================================
|
||||
|
||||
[Fact]
|
||||
public void AddTemplateNativeAlarmSource_WithDesignRole_ReturnsSuccess()
|
||||
{
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(
|
||||
new AddTemplateNativeAlarmSourceCommand(1, "Pressure", "Opc", "ns=2;s=T01", null, "desc", false),
|
||||
"Design");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
_templateRepo.ReceivedWithAnyArgs(1).AddTemplateNativeAlarmSourceAsync(default!, default);
|
||||
_templateRepo.ReceivedWithAnyArgs(1).SaveChangesAsync(default);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTemplateNativeAlarmSource_WithDeploymentRole_ReturnsUnauthorized()
|
||||
{
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(
|
||||
new AddTemplateNativeAlarmSourceCommand(1, "Pressure", "Opc", "ns=2;s=T01", null, null, false),
|
||||
"Deployment");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
var response = ExpectMsg<ManagementUnauthorized>(TimeSpan.FromSeconds(5));
|
||||
Assert.Contains("Design", response.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListTemplateNativeAlarmSources_ReturnsData()
|
||||
{
|
||||
_templateRepo.GetNativeAlarmSourcesByTemplateIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(new List<TemplateNativeAlarmSource>
|
||||
{
|
||||
new("Pressure") { Id = 1, TemplateId = 1, ConnectionName = "Opc", SourceReference = "ns=2;s=T01" }
|
||||
});
|
||||
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(new ListTemplateNativeAlarmSourcesCommand(1));
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
var response = ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
Assert.Contains("Pressure", response.JsonData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetInstanceNativeAlarmSourceOverride_WithDeploymentRole_ReturnsSuccess()
|
||||
{
|
||||
// No prior override → Add path.
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(
|
||||
new SetInstanceNativeAlarmSourceOverrideCommand(1, "Pressure", "Opc2", "ns=2;s=NEW", null),
|
||||
"Deployment");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
_templateRepo.ReceivedWithAnyArgs(1).AddInstanceNativeAlarmSourceOverrideAsync(default!, default);
|
||||
_templateRepo.ReceivedWithAnyArgs(1).SaveChangesAsync(default);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetInstanceNativeAlarmSourceOverride_WithDesignRole_ReturnsUnauthorized()
|
||||
{
|
||||
var actor = CreateActor();
|
||||
var envelope = Envelope(
|
||||
new SetInstanceNativeAlarmSourceOverrideCommand(1, "Pressure", "Opc2", "ns=2;s=NEW", null),
|
||||
"Design");
|
||||
|
||||
actor.Tell(envelope);
|
||||
|
||||
var response = ExpectMsg<ManagementUnauthorized>(TimeSpan.FromSeconds(5));
|
||||
Assert.Contains("Deployment", response.Message);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user