fix: Ignore employment overlaps at the same company
Sequential roles at the same company (promotions, transfers) should not be flagged as suspicious overlaps. Only flag overlaps between different companies. - Add IsSameCompany() check before flagging overlaps - Normalize company names to handle variations like "BMW" vs "BMW UK" - Remove common suffixes (Ltd, PLC, Group, etc.) for comparison 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,15 @@ public sealed class TimelineAnalyserService : ITimelineAnalyserService
|
||||
var earlier = sortedEmployment[i];
|
||||
var later = sortedEmployment[j];
|
||||
|
||||
// Skip overlaps at the same company (internal promotions/transfers)
|
||||
if (IsSameCompany(earlier.CompanyName, later.CompanyName))
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"Ignoring overlap at same company: {Company1} -> {Company2}",
|
||||
earlier.CompanyName, later.CompanyName);
|
||||
continue;
|
||||
}
|
||||
|
||||
var overlap = CalculateOverlap(earlier, later);
|
||||
|
||||
if (overlap is not null && overlap.Value.Months > AllowedOverlapMonths)
|
||||
@@ -143,6 +152,59 @@ public sealed class TimelineAnalyserService : ITimelineAnalyserService
|
||||
return overlaps;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if two company names refer to the same company.
|
||||
/// Handles variations like "BMW" vs "BMW UK" vs "BMW Group".
|
||||
/// </summary>
|
||||
private static bool IsSameCompany(string? company1, string? company2)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(company1) || string.IsNullOrWhiteSpace(company2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Normalize names for comparison
|
||||
var name1 = NormalizeCompanyName(company1);
|
||||
var name2 = NormalizeCompanyName(company2);
|
||||
|
||||
// Exact match after normalization
|
||||
if (name1.Equals(name2, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if one contains the other (for "BMW" vs "BMW UK" cases)
|
||||
if (name1.Length >= 3 && name2.Length >= 3)
|
||||
{
|
||||
if (name1.StartsWith(name2, StringComparison.OrdinalIgnoreCase) ||
|
||||
name2.StartsWith(name1, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string NormalizeCompanyName(string name)
|
||||
{
|
||||
// Remove common suffixes and normalize
|
||||
var normalized = name.Trim();
|
||||
|
||||
string[] suffixes = ["Ltd", "Ltd.", "Limited", "PLC", "Plc", "Inc", "Inc.",
|
||||
"Corporation", "Corp", "Corp.", "UK", "Group", "(UK)", "& Co", "& Co."];
|
||||
|
||||
foreach (var suffix in suffixes)
|
||||
{
|
||||
if (normalized.EndsWith(" " + suffix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
normalized = normalized[..^(suffix.Length + 1)].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static (DateOnly Start, DateOnly End, int Months)? CalculateOverlap(
|
||||
EmploymentEntry earlier,
|
||||
EmploymentEntry later)
|
||||
|
||||
Reference in New Issue
Block a user