Initial commit: TrueCV CV verification platform
Clean architecture solution with: - Domain: Entities (User, CVCheck, CVFlag, CompanyCache) and Enums - Application: Service interfaces, DTOs, and models - Infrastructure: EF Core, Identity, Hangfire, external API clients, services - Web: Blazor Server UI with pages and components Features: - CV upload and parsing (PDF/DOCX) using Claude API - Employment verification against Companies House API - Timeline analysis for gaps and overlaps - Veracity scoring algorithm - Background job processing with Hangfire - Azure Blob Storage for file storage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
11
src/TrueCV.Application/DTOs/CVCheckDto.cs
Normal file
11
src/TrueCV.Application/DTOs/CVCheckDto.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace TrueCV.Application.DTOs;
|
||||
|
||||
public sealed record CVCheckDto
|
||||
{
|
||||
public required Guid Id { get; init; }
|
||||
public required string OriginalFileName { get; init; }
|
||||
public required string Status { get; init; }
|
||||
public int? VeracityScore { get; init; }
|
||||
public required DateTime CreatedAt { get; init; }
|
||||
public DateTime? CompletedAt { get; init; }
|
||||
}
|
||||
10
src/TrueCV.Application/DTOs/CompanySearchResult.cs
Normal file
10
src/TrueCV.Application/DTOs/CompanySearchResult.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TrueCV.Application.DTOs;
|
||||
|
||||
public sealed record CompanySearchResult
|
||||
{
|
||||
public required string CompanyNumber { get; init; }
|
||||
public required string CompanyName { get; init; }
|
||||
public required string CompanyStatus { get; init; }
|
||||
public DateOnly? IncorporationDate { get; init; }
|
||||
public string? AddressSnippet { get; init; }
|
||||
}
|
||||
13
src/TrueCV.Application/Interfaces/ICVCheckService.cs
Normal file
13
src/TrueCV.Application/Interfaces/ICVCheckService.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using TrueCV.Application.DTOs;
|
||||
using TrueCV.Application.Models;
|
||||
|
||||
namespace TrueCV.Application.Interfaces;
|
||||
|
||||
public interface ICVCheckService
|
||||
{
|
||||
Task<Guid> CreateCheckAsync(Guid userId, Stream file, string fileName);
|
||||
Task<CVCheckDto?> GetCheckAsync(Guid id);
|
||||
Task<CVCheckDto?> GetCheckForUserAsync(Guid id, Guid userId);
|
||||
Task<List<CVCheckDto>> GetUserChecksAsync(Guid userId);
|
||||
Task<VeracityReport?> GetReportAsync(Guid checkId, Guid userId);
|
||||
}
|
||||
8
src/TrueCV.Application/Interfaces/ICVParserService.cs
Normal file
8
src/TrueCV.Application/Interfaces/ICVParserService.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using TrueCV.Application.Models;
|
||||
|
||||
namespace TrueCV.Application.Interfaces;
|
||||
|
||||
public interface ICVParserService
|
||||
{
|
||||
Task<CVData> ParseAsync(Stream fileStream, string fileName);
|
||||
}
|
||||
10
src/TrueCV.Application/Interfaces/ICompanyVerifierService.cs
Normal file
10
src/TrueCV.Application/Interfaces/ICompanyVerifierService.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using TrueCV.Application.DTOs;
|
||||
using TrueCV.Application.Models;
|
||||
|
||||
namespace TrueCV.Application.Interfaces;
|
||||
|
||||
public interface ICompanyVerifierService
|
||||
{
|
||||
Task<CompanyVerificationResult> VerifyCompanyAsync(string companyName, DateOnly? startDate, DateOnly? endDate);
|
||||
Task<List<CompanySearchResult>> SearchCompaniesAsync(string query);
|
||||
}
|
||||
8
src/TrueCV.Application/Interfaces/IFileStorageService.cs
Normal file
8
src/TrueCV.Application/Interfaces/IFileStorageService.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace TrueCV.Application.Interfaces;
|
||||
|
||||
public interface IFileStorageService
|
||||
{
|
||||
Task<string> UploadAsync(Stream fileStream, string fileName);
|
||||
Task<Stream> DownloadAsync(string blobUrl);
|
||||
Task DeleteAsync(string blobUrl);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using TrueCV.Application.Models;
|
||||
|
||||
namespace TrueCV.Application.Interfaces;
|
||||
|
||||
public interface ITimelineAnalyserService
|
||||
{
|
||||
TimelineAnalysisResult Analyse(List<EmploymentEntry> employmentHistory);
|
||||
}
|
||||
11
src/TrueCV.Application/Models/CVData.cs
Normal file
11
src/TrueCV.Application/Models/CVData.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record CVData
|
||||
{
|
||||
public required string FullName { get; init; }
|
||||
public string? Email { get; init; }
|
||||
public string? Phone { get; init; }
|
||||
public List<EmploymentEntry> Employment { get; init; } = [];
|
||||
public List<EducationEntry> Education { get; init; } = [];
|
||||
public List<string> Skills { get; init; } = [];
|
||||
}
|
||||
13
src/TrueCV.Application/Models/CompanyVerificationResult.cs
Normal file
13
src/TrueCV.Application/Models/CompanyVerificationResult.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record CompanyVerificationResult
|
||||
{
|
||||
public required string ClaimedCompany { get; init; }
|
||||
public string? MatchedCompanyName { get; init; }
|
||||
public string? MatchedCompanyNumber { get; init; }
|
||||
public required int MatchScore { get; init; }
|
||||
public required bool IsVerified { get; init; }
|
||||
public string? VerificationNotes { get; init; }
|
||||
public DateOnly? ClaimedStartDate { get; init; }
|
||||
public DateOnly? ClaimedEndDate { get; init; }
|
||||
}
|
||||
11
src/TrueCV.Application/Models/EducationEntry.cs
Normal file
11
src/TrueCV.Application/Models/EducationEntry.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record EducationEntry
|
||||
{
|
||||
public required string Institution { get; init; }
|
||||
public string? Qualification { get; init; }
|
||||
public string? Subject { get; init; }
|
||||
public string? Grade { get; init; }
|
||||
public DateOnly? StartDate { get; init; }
|
||||
public DateOnly? EndDate { get; init; }
|
||||
}
|
||||
12
src/TrueCV.Application/Models/EmploymentEntry.cs
Normal file
12
src/TrueCV.Application/Models/EmploymentEntry.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record EmploymentEntry
|
||||
{
|
||||
public required string CompanyName { get; init; }
|
||||
public required string JobTitle { get; init; }
|
||||
public string? Location { get; init; }
|
||||
public DateOnly? StartDate { get; init; }
|
||||
public DateOnly? EndDate { get; init; }
|
||||
public bool IsCurrent { get; init; }
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
10
src/TrueCV.Application/Models/FlagResult.cs
Normal file
10
src/TrueCV.Application/Models/FlagResult.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record FlagResult
|
||||
{
|
||||
public required string Category { get; init; }
|
||||
public required string Severity { get; init; }
|
||||
public required string Title { get; init; }
|
||||
public required string Description { get; init; }
|
||||
public required int ScoreImpact { get; init; }
|
||||
}
|
||||
9
src/TrueCV.Application/Models/TimelineAnalysisResult.cs
Normal file
9
src/TrueCV.Application/Models/TimelineAnalysisResult.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record TimelineAnalysisResult
|
||||
{
|
||||
public required int TotalGapMonths { get; init; }
|
||||
public required int TotalOverlapMonths { get; init; }
|
||||
public List<TimelineGap> Gaps { get; init; } = [];
|
||||
public List<TimelineOverlap> Overlaps { get; init; } = [];
|
||||
}
|
||||
8
src/TrueCV.Application/Models/TimelineGap.cs
Normal file
8
src/TrueCV.Application/Models/TimelineGap.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record TimelineGap
|
||||
{
|
||||
public required DateOnly StartDate { get; init; }
|
||||
public required DateOnly EndDate { get; init; }
|
||||
public required int Months { get; init; }
|
||||
}
|
||||
10
src/TrueCV.Application/Models/TimelineOverlap.cs
Normal file
10
src/TrueCV.Application/Models/TimelineOverlap.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record TimelineOverlap
|
||||
{
|
||||
public required string Company1 { get; init; }
|
||||
public required string Company2 { get; init; }
|
||||
public required DateOnly OverlapStart { get; init; }
|
||||
public required DateOnly OverlapEnd { get; init; }
|
||||
public required int Months { get; init; }
|
||||
}
|
||||
11
src/TrueCV.Application/Models/VeracityReport.cs
Normal file
11
src/TrueCV.Application/Models/VeracityReport.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace TrueCV.Application.Models;
|
||||
|
||||
public sealed record VeracityReport
|
||||
{
|
||||
public required int OverallScore { get; init; }
|
||||
public required string ScoreLabel { get; init; }
|
||||
public List<CompanyVerificationResult> EmploymentVerifications { get; init; } = [];
|
||||
public required TimelineAnalysisResult TimelineAnalysis { get; init; }
|
||||
public List<FlagResult> Flags { get; init; } = [];
|
||||
public required DateTime GeneratedAt { get; init; }
|
||||
}
|
||||
13
src/TrueCV.Application/TrueCV.Application.csproj
Normal file
13
src/TrueCV.Application/TrueCV.Application.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TrueCV.Domain\TrueCV.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user