fix(transport): carry TemplateAlarm.OnTriggerScript by name in bundle DTO

This commit is contained in:
Joseph Doherty
2026-05-24 06:10:59 -04:00
parent 79d74ee59c
commit cef77e1378
3 changed files with 74 additions and 41 deletions

View File

@@ -78,7 +78,8 @@ public sealed record TemplateAlarmDto(
int PriorityLevel,
AlarmTriggerType TriggerType,
string? TriggerConfiguration,
bool IsLocked);
bool IsLocked,
string? OnTriggerScriptName);
public sealed record TemplateScriptDto(
string Name,

View File

@@ -29,37 +29,53 @@ public sealed class EntitySerializer
Name: f.Name,
ParentName: f.ParentFolderId is { } pid && folderNameById.TryGetValue(pid, out var pname) ? pname : null,
SortOrder: f.SortOrder)).ToList(),
Templates: aggregate.Templates.Select(t => new TemplateDto(
Name: t.Name,
FolderName: t.FolderId is { } fid && folderNameById.TryGetValue(fid, out var fname) ? fname : null,
BaseTemplateName: t.ParentTemplateId is { } btid && templateNameById.TryGetValue(btid, out var bname) ? bname : null,
Description: t.Description,
Attributes: t.Attributes.Select(a => new TemplateAttributeDto(
Name: a.Name,
Value: a.Value,
DataType: a.DataType,
IsLocked: a.IsLocked,
Description: a.Description,
DataSourceReference: a.DataSourceReference)).ToList(),
Alarms: t.Alarms.Select(a => new TemplateAlarmDto(
Name: a.Name,
Description: a.Description,
PriorityLevel: a.PriorityLevel,
TriggerType: a.TriggerType,
TriggerConfiguration: a.TriggerConfiguration,
IsLocked: a.IsLocked)).ToList(),
Scripts: t.Scripts.Select(s => new TemplateScriptDto(
Name: s.Name,
Code: s.Code,
TriggerType: s.TriggerType,
TriggerConfiguration: s.TriggerConfiguration,
ParameterDefinitions: s.ParameterDefinitions,
ReturnDefinition: s.ReturnDefinition,
IsLocked: s.IsLocked,
MinTimeBetweenRuns: s.MinTimeBetweenRuns)).ToList(),
Compositions: t.Compositions.Select(c => new TemplateCompositionDto(
InstanceName: c.InstanceName,
ComposedTemplateName: templateNameById.TryGetValue(c.ComposedTemplateId, out var cn) ? cn : string.Empty)).ToList())).ToList(),
Templates: aggregate.Templates.Select(t =>
{
// Build per-template script-id → name lookup once so the alarm
// projection below resolves OnTriggerScriptId by name in O(1).
// Scripts can only target sibling scripts on the same template
// (TemplateAlarm.OnTriggerScriptId FK is scoped to TemplateId),
// so we don't need a global script index.
var scriptNameById = t.Scripts.ToDictionary(s => s.Id, s => s.Name);
return new TemplateDto(
Name: t.Name,
FolderName: t.FolderId is { } fid && folderNameById.TryGetValue(fid, out var fname) ? fname : null,
BaseTemplateName: t.ParentTemplateId is { } btid && templateNameById.TryGetValue(btid, out var bname) ? bname : null,
Description: t.Description,
Attributes: t.Attributes.Select(a => new TemplateAttributeDto(
Name: a.Name,
Value: a.Value,
DataType: a.DataType,
IsLocked: a.IsLocked,
Description: a.Description,
DataSourceReference: a.DataSourceReference)).ToList(),
Alarms: t.Alarms.Select(a => new TemplateAlarmDto(
Name: a.Name,
Description: a.Description,
PriorityLevel: a.PriorityLevel,
TriggerType: a.TriggerType,
TriggerConfiguration: a.TriggerConfiguration,
IsLocked: a.IsLocked,
// Carry the on-trigger script by NAME — the importer resolves
// this back to a script id once the parent template's scripts
// have been persisted and assigned ids. If the FK doesn't
// 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(),
Scripts: t.Scripts.Select(s => new TemplateScriptDto(
Name: s.Name,
Code: s.Code,
TriggerType: s.TriggerType,
TriggerConfiguration: s.TriggerConfiguration,
ParameterDefinitions: s.ParameterDefinitions,
ReturnDefinition: s.ReturnDefinition,
IsLocked: s.IsLocked,
MinTimeBetweenRuns: s.MinTimeBetweenRuns)).ToList(),
Compositions: t.Compositions.Select(c => new TemplateCompositionDto(
InstanceName: c.InstanceName,
ComposedTemplateName: templateNameById.TryGetValue(c.ComposedTemplateId, out var cn) ? cn : string.Empty)).ToList());
}).ToList(),
SharedScripts: aggregate.SharedScripts.Select(s => new SharedScriptDto(
Name: s.Name,
Code: s.Code,