Fix CV verification scoring and UI alignment issues

ProcessCVCheckJob:
- Recognize "contract", "contract work", "contract role" as freelance
- Add "various", "various clients" for multiple short-term contracts
- Prevents false matching of contract work to dissolved companies

Report.razor:
- Fix stat blocks centering (icon, number, label now centered)
- Fix employment table column alignment with fixed widths
- Add inline styles to header for consistent centering
- Improve GetPointsForCompany to show -10 for unverified companies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 11:20:38 +00:00
parent 7510ef3670
commit cfe06788e2
2 changed files with 70 additions and 13 deletions

View File

@@ -523,13 +523,22 @@ public sealed class ProcessCVCheckJob
name == "self employed" ||
name == "selfemployed" ||
name == "contractor" ||
name == "contract" || // Working on contract basis
name == "contract work" ||
name == "contract role" ||
name == "various" || // Multiple short-term contracts
name == "various clients" ||
name == "various companies" ||
name.StartsWith("freelance ") ||
name.StartsWith("self-employed ") ||
name.StartsWith("self employed ") ||
name.StartsWith("contract ") ||
name.StartsWith("contracting ") ||
name.Contains("(freelance)") ||
name.Contains("(self-employed)") ||
name.Contains("(self employed)") ||
name.Contains("(contractor)");
name.Contains("(contractor)") ||
name.Contains("(contract)");
}
private static bool IsPublicSectorEmployer(string companyName)

View File

@@ -214,11 +214,11 @@
<div class="card-body p-0">
<div class="employment-list">
<div class="employment-header">
<div></div>
<div style="text-align: center;"></div>
<div>Employer</div>
<div>Period</div>
<div>Match</div>
<div>Pts</div>
<div style="text-align: center;">Period</div>
<div style="text-align: center;">Match</div>
<div style="text-align: center;">Pts</div>
</div>
@for (int i = 0; i < _report.EmploymentVerifications.Count; i++)
{
@@ -573,6 +573,10 @@
/* Stat Items */
.stat-item {
padding: 0.5rem;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.stat-icon {
@@ -641,7 +645,7 @@
.employment-header {
display: grid;
grid-template-columns: 24px 1fr auto 60px 50px;
grid-template-columns: 24px 1fr 120px 60px 50px;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
background-color: #f8fafc;
@@ -651,17 +655,24 @@
color: #64748b;
text-transform: uppercase;
letter-spacing: 0.025em;
align-items: center;
}
.employment-header div {
display: flex;
align-items: center;
}
.employment-header div:nth-child(3),
.employment-header div:nth-child(4),
.employment-header div:nth-child(5) {
justify-content: center;
text-align: center;
}
.employment-row {
display: grid;
grid-template-columns: 24px 1fr auto 60px 50px;
grid-template-columns: 24px 1fr 120px 60px 50px;
gap: 0.5rem;
align-items: center;
padding: 0.5rem 0.75rem;
@@ -690,6 +701,7 @@
.employment-company {
display: flex;
flex-direction: column;
justify-content: center;
gap: 0.125rem;
min-width: 0;
}
@@ -707,18 +719,25 @@
}
.employment-dates {
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
color: #6b7280;
white-space: nowrap;
text-align: right;
text-align: center;
}
.employment-score {
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.employment-points {
text-align: center;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8125rem;
}
@@ -970,7 +989,7 @@
private int GetPointsForCompany(string claimedCompany, string? matchedCompany, int index)
{
if (_report?.Flags is null) return 0;
if (_report?.Flags is null || _report?.EmploymentVerifications is null) return 0;
// Only show points for the first occurrence of each company
if (!_firstOccurrenceIndices.Contains(index))
@@ -978,7 +997,13 @@
return 0;
}
// Sum up all flags that mention this company in their description
var totalPoints = 0;
// Get the verification result for this company
var verification = _report.EmploymentVerifications.ElementAtOrDefault(index);
// Check if there's an "Unverified Company" flag for this company
// Search by both title pattern and description containing company name
var companyFlags = _report.Flags
.Where(f => f.ScoreImpact < 0 &&
((!string.IsNullOrEmpty(f.Description) && f.Description.Contains(claimedCompany, StringComparison.OrdinalIgnoreCase)) ||
@@ -987,6 +1012,29 @@
.Select(g => g.First())
.ToList();
return companyFlags.Sum(f => f.ScoreImpact);
totalPoints = companyFlags.Sum(f => f.ScoreImpact);
// If company is unverified but no flag was found in description search,
// check if there's a generic "Unverified Company" flag that might use different wording
if (verification != null && !verification.IsVerified && totalPoints == 0)
{
// Look for any Unverified Company flag that might apply
var unverifiedFlag = _report.Flags
.FirstOrDefault(f => f.Title == "Unverified Company" && f.ScoreImpact < 0 &&
!string.IsNullOrEmpty(f.Description) &&
f.Description.Contains(claimedCompany, StringComparison.OrdinalIgnoreCase));
if (unverifiedFlag != null)
{
totalPoints = unverifiedFlag.ScoreImpact;
}
else
{
// Company is unverified but no specific flag found - show the standard penalty
totalPoints = -10;
}
}
return totalPoints;
}
}