fix(transport): transport LockedInDerived on template attributes/alarms/scripts (additive DTO fields)
Adds a trailing optional `bool LockedInDerived = false` to TemplateAttributeDto, TemplateAlarmDto and TemplateScriptDto (mirrors the ExecutionTimeoutSeconds additive precedent — no schemaVersion bump). Populated at export (ToBundleContent), consumed on import (FromBundleContent, BuildTemplate, and all three SyncTemplate*Async changed-predicate + copy + new-entity paths, incl. audit payloads). Old-form bundles that lack the property still deserialize to false. Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
@@ -135,7 +135,13 @@ public sealed record TemplateAttributeDto(
|
||||
bool IsLocked,
|
||||
string? Description,
|
||||
string? DataSourceReference,
|
||||
DataType? ElementDataType = null);
|
||||
DataType? ElementDataType = null,
|
||||
// Whether this member is locked against override in derived templates.
|
||||
// Additive trailing field; false on bundles written before it existed
|
||||
// (dropped from JSON by WhenWritingNull? — no, bool is a value type, so it
|
||||
// is always emitted; older bundles simply lack the property and deserialize
|
||||
// to the default false).
|
||||
bool LockedInDerived = false);
|
||||
|
||||
public sealed record TemplateAlarmDto(
|
||||
string Name,
|
||||
@@ -144,7 +150,9 @@ public sealed record TemplateAlarmDto(
|
||||
AlarmTriggerType TriggerType,
|
||||
string? TriggerConfiguration,
|
||||
bool IsLocked,
|
||||
string? OnTriggerScriptName);
|
||||
string? OnTriggerScriptName,
|
||||
// Derived-lock flag; additive trailing field (see TemplateAttributeDto).
|
||||
bool LockedInDerived = false);
|
||||
|
||||
public sealed record TemplateScriptDto(
|
||||
string Name,
|
||||
@@ -157,7 +165,9 @@ public sealed record TemplateScriptDto(
|
||||
TimeSpan? MinTimeBetweenRuns,
|
||||
// Per-script execution timeout (seconds). Additive trailing field;
|
||||
// null on bundles written before this field existed.
|
||||
int? ExecutionTimeoutSeconds = null);
|
||||
int? ExecutionTimeoutSeconds = null,
|
||||
// Derived-lock flag; additive trailing field (see TemplateAttributeDto).
|
||||
bool LockedInDerived = false);
|
||||
|
||||
public sealed record TemplateCompositionDto(
|
||||
string InstanceName,
|
||||
|
||||
@@ -61,7 +61,8 @@ public sealed class EntitySerializer
|
||||
IsLocked: a.IsLocked,
|
||||
Description: a.Description,
|
||||
DataSourceReference: a.DataSourceReference,
|
||||
ElementDataType: a.ElementDataType)).ToList(),
|
||||
ElementDataType: a.ElementDataType,
|
||||
LockedInDerived: a.LockedInDerived)).ToList(),
|
||||
Alarms: t.Alarms.Select(a => new TemplateAlarmDto(
|
||||
Name: a.Name,
|
||||
Description: a.Description,
|
||||
@@ -75,7 +76,8 @@ public sealed class EntitySerializer
|
||||
// resolve in this aggregate (e.g. corrupt/orphan row), the
|
||||
// name comes through as null and the importer leaves the
|
||||
// FK null on the imported alarm.
|
||||
OnTriggerScriptName: a.OnTriggerScriptId is { } sid && scriptNameById.TryGetValue(sid, out var sn) ? sn : null)).ToList(),
|
||||
OnTriggerScriptName: a.OnTriggerScriptId is { } sid && scriptNameById.TryGetValue(sid, out var sn) ? sn : null,
|
||||
LockedInDerived: a.LockedInDerived)).ToList(),
|
||||
Scripts: t.Scripts.Select(s => new TemplateScriptDto(
|
||||
Name: s.Name,
|
||||
Code: s.Code,
|
||||
@@ -85,7 +87,8 @@ public sealed class EntitySerializer
|
||||
ReturnDefinition: s.ReturnDefinition,
|
||||
IsLocked: s.IsLocked,
|
||||
MinTimeBetweenRuns: s.MinTimeBetweenRuns,
|
||||
ExecutionTimeoutSeconds: s.ExecutionTimeoutSeconds)).ToList(),
|
||||
ExecutionTimeoutSeconds: s.ExecutionTimeoutSeconds,
|
||||
LockedInDerived: s.LockedInDerived)).ToList(),
|
||||
Compositions: t.Compositions.Select(c => new TemplateCompositionDto(
|
||||
InstanceName: c.InstanceName,
|
||||
ComposedTemplateName: templateNameById.TryGetValue(c.ComposedTemplateId, out var cn) ? cn : string.Empty)).ToList());
|
||||
@@ -318,6 +321,7 @@ public sealed class EntitySerializer
|
||||
Description = a.Description,
|
||||
DataSourceReference = a.DataSourceReference,
|
||||
ElementDataType = a.ElementDataType,
|
||||
LockedInDerived = a.LockedInDerived,
|
||||
});
|
||||
}
|
||||
foreach (var al in dto.Alarms)
|
||||
@@ -330,6 +334,7 @@ public sealed class EntitySerializer
|
||||
TriggerType = al.TriggerType,
|
||||
TriggerConfiguration = al.TriggerConfiguration,
|
||||
IsLocked = al.IsLocked,
|
||||
LockedInDerived = al.LockedInDerived,
|
||||
});
|
||||
}
|
||||
foreach (var s in dto.Scripts)
|
||||
@@ -344,6 +349,7 @@ public sealed class EntitySerializer
|
||||
IsLocked = s.IsLocked,
|
||||
MinTimeBetweenRuns = s.MinTimeBetweenRuns,
|
||||
ExecutionTimeoutSeconds = s.ExecutionTimeoutSeconds,
|
||||
LockedInDerived = s.LockedInDerived,
|
||||
});
|
||||
}
|
||||
return t;
|
||||
|
||||
Reference in New Issue
Block a user