using IceImportDAL.DTO.IceImportPipeline; namespace IceImportBLL.FieldResolvers; // ValueType = 5 (Name -> Id lookup). See CodeToIdLookupResolver — identical dispatch, distinct // dictionary slice populated by IEntityLookupService for Name-based lookups. public class NameToIdLookupResolver : IIceFieldValueResolver { public int ValueType => 5; public Task ResolveAsync(FieldResolutionContext ctx, CancellationToken ct) { var fieldName = ctx.DetailConfig.IceMapDetailsSourceFieldName?.Trim().ToUpperInvariant(); string? raw = null; if (!string.IsNullOrEmpty(fieldName) && ctx.SourceRow.Table.Columns.Contains(fieldName)) raw = ctx.SourceRow[fieldName]?.ToString()?.Trim(); else if (ctx.DetailConfig.IceMapDetailsIsOptional == 0) // Optional field whose source column isn't present in this file — fall back to the // configured default name, then resolve it through the same Name -> Id lookup below. raw = ctx.DetailConfig.IceMapDetailsOptionalFiledValue?.Trim(); if (string.IsNullOrEmpty(raw)) return Task.FromResult(FieldResolutionResult.Ok(null)); if (ctx.Lookups.TryGetValue(ctx.DetailConfig.EntityId, out var byName) && byName.TryGetValue(raw, out var id)) return Task.FromResult(FieldResolutionResult.Ok(id)); // Error, not Warning — an unresolved Name -> Id lookup means this field would otherwise be // committed with a null/invalid FK (e.g. GcmTypeId), so the whole row must be rejected // rather than silently saved with bad data. var error = new IceImportFieldErrorDTO { RowNumber = ctx.RowNumber, EntityCode = ctx.DetailConfig.EntityCode ?? string.Empty, FieldName = ctx.DetailConfig.IceMapDetailsSourceFieldName ?? fieldName ?? string.Empty, Message = $"Name '{raw}' could not be resolved to an existing {ctx.DetailConfig.EntityCode ?? "record"}.", Severity = IceImportSeverity.Error, Value = raw }; return Task.FromResult(FieldResolutionResult.WithWarning(null, error)); } }