fix(transport): wire TemplateFolder FK on imported templates
ApplyTemplatesAsync built the Template entity via BuildTemplate() but never read the DTO's FolderName -- so every imported template landed at the root regardless of which folder it lived in on the source cluster. ApplyTemplateFoldersAsync had already flushed the folder rows by that point; the FK just wasn't being set. Resolve folder-name -> persisted FolderId from the same name table (via _templateRepo.GetAllFoldersAsync after the folder pass), honour TemplateFolder Rename resolutions, and set FolderId on Add / Overwrite / Rename paths alike. The audit-row 'after' state now includes FolderId so the action's effect is visible in the configuration audit log.
This commit is contained in:
@@ -822,9 +822,30 @@ public sealed class BundleImporter : IBundleImporter
|
|||||||
var stubs = await _templateRepo.GetAllTemplatesAsync(ct).ConfigureAwait(false);
|
var stubs = await _templateRepo.GetAllTemplatesAsync(ct).ConfigureAwait(false);
|
||||||
var byName = stubs.ToDictionary(t => t.Name, t => t, StringComparer.Ordinal);
|
var byName = stubs.ToDictionary(t => t.Name, t => t, StringComparer.Ordinal);
|
||||||
|
|
||||||
|
// ApplyTemplateFoldersAsync has already flushed every imported folder
|
||||||
|
// (and target folders pre-exist), so name-keyed lookup resolves to the
|
||||||
|
// persisted FolderId every imported template should reference.
|
||||||
|
var folders = await _templateRepo.GetAllFoldersAsync(ct).ConfigureAwait(false);
|
||||||
|
var folderIdByName = folders.ToDictionary(f => f.Name, f => f.Id, StringComparer.Ordinal);
|
||||||
|
|
||||||
|
// Honour folder renames -- a TemplateFolder resolved as Rename was
|
||||||
|
// written under its new name; templates that reference the old name in
|
||||||
|
// the bundle DTO must map to the renamed folder, not be orphaned.
|
||||||
|
int? ResolveFolderId(string? folderName)
|
||||||
|
{
|
||||||
|
if (folderName is null) return null;
|
||||||
|
var folderResolution = ResolveOrDefault(map, "TemplateFolder", folderName);
|
||||||
|
var lookupName = (folderResolution.Action == ResolutionAction.Rename
|
||||||
|
&& !string.IsNullOrEmpty(folderResolution.RenameTo))
|
||||||
|
? folderResolution.RenameTo
|
||||||
|
: folderName;
|
||||||
|
return folderIdByName.TryGetValue(lookupName, out var fid) ? fid : (int?)null;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var dto in dtos)
|
foreach (var dto in dtos)
|
||||||
{
|
{
|
||||||
var resolution = ResolveOrDefault(map, "Template", dto.Name);
|
var resolution = ResolveOrDefault(map, "Template", dto.Name);
|
||||||
|
var folderId = ResolveFolderId(dto.FolderName);
|
||||||
switch (resolution.Action)
|
switch (resolution.Action)
|
||||||
{
|
{
|
||||||
case ResolutionAction.Skip:
|
case ResolutionAction.Skip:
|
||||||
@@ -834,17 +855,19 @@ public sealed class BundleImporter : IBundleImporter
|
|||||||
{
|
{
|
||||||
var name = resolution.RenameTo ?? dto.Name;
|
var name = resolution.RenameTo ?? dto.Name;
|
||||||
var t = BuildTemplate(dto, overrideName: name);
|
var t = BuildTemplate(dto, overrideName: name);
|
||||||
|
t.FolderId = folderId;
|
||||||
await _templateRepo.AddTemplateAsync(t, ct).ConfigureAwait(false);
|
await _templateRepo.AddTemplateAsync(t, ct).ConfigureAwait(false);
|
||||||
await _auditService.LogAsync(user, "Create", "Template", "0", name,
|
await _auditService.LogAsync(user, "Create", "Template", "0", name,
|
||||||
new { Name = name, dto.Description, RenamedFrom = dto.Name }, ct).ConfigureAwait(false);
|
new { Name = name, dto.Description, FolderId = folderId, RenamedFrom = dto.Name }, ct).ConfigureAwait(false);
|
||||||
summary.Renamed++;
|
summary.Renamed++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ResolutionAction.Overwrite when byName.TryGetValue(dto.Name, out var ex):
|
case ResolutionAction.Overwrite when byName.TryGetValue(dto.Name, out var ex):
|
||||||
ex.Description = dto.Description;
|
ex.Description = dto.Description;
|
||||||
|
ex.FolderId = folderId;
|
||||||
await _templateRepo.UpdateTemplateAsync(ex, ct).ConfigureAwait(false);
|
await _templateRepo.UpdateTemplateAsync(ex, ct).ConfigureAwait(false);
|
||||||
await _auditService.LogAsync(user, "Update", "Template", ex.Id.ToString(), ex.Name,
|
await _auditService.LogAsync(user, "Update", "Template", ex.Id.ToString(), ex.Name,
|
||||||
new { ex.Name, ex.Description }, ct).ConfigureAwait(false);
|
new { ex.Name, ex.Description, ex.FolderId }, ct).ConfigureAwait(false);
|
||||||
summary.Overwritten++;
|
summary.Overwritten++;
|
||||||
break;
|
break;
|
||||||
case ResolutionAction.Add:
|
case ResolutionAction.Add:
|
||||||
@@ -852,9 +875,10 @@ public sealed class BundleImporter : IBundleImporter
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
var t = BuildTemplate(dto, overrideName: null);
|
var t = BuildTemplate(dto, overrideName: null);
|
||||||
|
t.FolderId = folderId;
|
||||||
await _templateRepo.AddTemplateAsync(t, ct).ConfigureAwait(false);
|
await _templateRepo.AddTemplateAsync(t, ct).ConfigureAwait(false);
|
||||||
await _auditService.LogAsync(user, "Create", "Template", "0", t.Name,
|
await _auditService.LogAsync(user, "Create", "Template", "0", t.Name,
|
||||||
new { t.Name, t.Description }, ct).ConfigureAwait(false);
|
new { t.Name, t.Description, t.FolderId }, ct).ConfigureAwait(false);
|
||||||
summary.Added++;
|
summary.Added++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user