fix(uns): enforce #122 on line reparent across clusters (final review)
v2-ci / build (push) Failing after 4m38s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

This commit is contained in:
Joseph Doherty
2026-06-08 14:12:46 -04:00
parent 1bb7482c3a
commit 8ba64b1d99
2 changed files with 122 additions and 0 deletions
@@ -408,6 +408,41 @@ public sealed class UnsTreeService(IDbContextFactory<OtOpcUaConfigDbContext> dbF
}
db.Entry(entity).Property(e => e.RowVersion).OriginalValue = rowVersion;
// Decision #122: a reparent to a different area must not orphan driver-bound equipment
// from its driver's cluster. Resolve the new area's cluster and check every bound
// equipment item under this line against it.
if (newUnsAreaId != entity.UnsAreaId)
{
var newAreaCluster = await db.UnsAreas
.Where(a => a.UnsAreaId == newUnsAreaId)
.Select(a => (string?)a.ClusterId)
.FirstOrDefaultAsync(ct);
if (newAreaCluster is not null)
{
var boundEquipment = await db.Equipment
.Where(eq => eq.UnsLineId == unsLineId && eq.DriverInstanceId != null)
.Select(eq => new { eq.EquipmentId, eq.DriverInstanceId })
.ToListAsync(ct);
foreach (var eq in boundEquipment)
{
var driverCluster = await db.DriverInstances
.Where(d => d.DriverInstanceId == eq.DriverInstanceId)
.Select(d => d.ClusterId)
.FirstOrDefaultAsync(ct);
if (driverCluster is not null && driverCluster != newAreaCluster)
{
return new UnsMutationResult(
false,
$"Cannot move line to area '{newUnsAreaId}': equipment '{eq.EquipmentId}' is bound to a driver in cluster '{driverCluster}' (decision #122). Re-home or unbind it first.");
}
}
}
}
entity.UnsAreaId = newUnsAreaId;
entity.Name = name;
entity.Notes = string.IsNullOrWhiteSpace(notes) ? null : notes;