Compare commits

11 Commits

Author SHA1 Message Date
8a4e46d872 feat: Improve company alias matching and add batch tester flags display
- Add Deliveroo alias (ROOFOODS LTD) to fix matching to wrong company
- Add JCB alias (J.C. BAMFORD EXCAVATORS LIMITED)
- Improve FindDirectAliasMatch to prefer active companies over dissolved
- Display verification flags in CVBatchTester output
- Employer verification improved from 65% to 86%

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 05:43:04 +00:00
7ebf09c284 fix: Add direct alias matching to bypass AI rejection for known trading names
- WPP was failing because AI didn't recognize "WPP 2005 LIMITED" as the main
  WPP entity (WPP plc is incorporated in Jersey, not UK Companies House)
- Added FindDirectAliasMatch() that accepts candidates matching known aliases
  without requiring AI confirmation
- Fixed WPP alias to use "WPP 2005 LIMITED" instead of non-existent "WPP PLC"
- This improves employer verification from 84% to 85%

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 22:00:59 +00:00
1a06d60f2d feat: Add company name aliases and fix education verification
- Add trading name aliases for major UK companies (Boots, BBC, Lloyds, etc.)
  mapping to their official Companies House registered names
- Add Leeds Beckett University (and former name Leeds Metropolitan) to
  recognised UK institutions
- This improves company verification from 65% to 84% on test data
- CVBatchTester tool for testing verification against JSON CVs

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 21:48:15 +00:00
6773162426 feat: Display candidate name from CV data instead of filename
- Added CandidateName field to CVCheckDto
- Extract candidate name from ReportJson or ExtractedDataJson
- Dashboard now shows actual candidate name for JSON uploads
- PDF export uses candidate name from report

This fixes the issue where JSON files showed their filename (e.g.,
"CLEAN-001") instead of the actual candidate name from the CV data.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 21:23:48 +00:00
ecb599fba7 fix: Replace --truecv- CSS variables with --realcv-
Fixed CSS variable references in Razor components that were still
using the old --truecv- prefix, causing score circles and other
styled elements to not render properly.

Also changed score-ring-value font to Inter for consistent numbers.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 21:14:20 +00:00
70d8a4786e fix: Change stat-value font from JetBrains Mono to Inter
The stylized '0' in JetBrains Mono was being confused with '8'.
Changed to Inter with tabular-nums for clearer number display.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 21:09:41 +00:00
ee48afa5bd chore: Add production config with API keys
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 21:08:05 +00:00
473bef96e9 chore: Update all TrueCV references to RealCV
- Updated Dockerfiles (Dockerfile, Dockerfile.migrations)
- Updated docker-compose.yml (service names, container names, network)
- Updated deploy scripts (README.md, server-setup.sh, deploy.sh)
- Updated .gitignore
- Updated all strategy documentation files
- Updated app.js comment

Note: Passwords containing "TrueCV" were intentionally preserved.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 21:01:07 +00:00
d3fb929443 fix: Remove redundant Home menu item from navbar
The logo already serves as the home link, so having a separate Home
text link next to it was redundant and cluttered the navigation.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 20:57:14 +00:00
de8b36ae2b fix: Rename logo file to match RealCV branding
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 20:54:33 +00:00
92a3b60878 refactor: Rename TrueCV to RealCV throughout codebase
- Renamed all directories (TrueCV.* -> RealCV.*)
- Renamed all project files (.csproj)
- Renamed solution file (TrueCV.sln -> RealCV.sln)
- Updated all namespaces in C# and Razor files
- Updated project references
- Updated CSS variable names

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 20:47:55 +00:00
125 changed files with 1757 additions and 812 deletions

2
.gitignore vendored
View File

@@ -220,5 +220,5 @@ local/
*.swp *.swp
# Local file uploads # Local file uploads
src/TrueCV.Web/uploads/ src/RealCV.Web/uploads/
logs/ logs/

View File

@@ -1,4 +1,4 @@
# TrueCV UK APIs & Integration Resources # RealCV UK APIs & Integration Resources
**Last Updated:** January 2026 **Last Updated:** January 2026
**Purpose:** Practical guide for obtaining API access and integration details **Purpose:** Practical guide for obtaining API access and integration details
@@ -159,13 +159,13 @@
### Overview ### Overview
- **Service:** UK company registration and officer records - **Service:** UK company registration and officer records
- **Status:** ✅ Already integrated in TrueCV - **Status:** ✅ Already integrated in RealCV
- **Coverage:** 3.4M registered UK companies - **Coverage:** 3.4M registered UK companies
### Enhancement Opportunities ### Enhancement Opportunities
#### Existing Implementation #### Existing Implementation
- See: `/src/TrueCV.Infrastructure/ExternalApis/CompaniesHouseClient.cs` - See: `/src/RealCV.Infrastructure/ExternalApis/CompaniesHouseClient.cs`
- Current: Company search + basic data lookup - Current: Company search + basic data lookup
- Rate Limit: 500 requests/hour (generous) - Rate Limit: 500 requests/hour (generous)
@@ -326,7 +326,7 @@
- uCheck - uCheck
- Certn - Certn
### Recommended Vendor for TrueCV Integration ### Recommended Vendor for RealCV Integration
**Verifile** (Suggested) **Verifile** (Suggested)
- **Website:** https://www.verifile.io/ - **Website:** https://www.verifile.io/
@@ -345,7 +345,7 @@
2. Negotiate revenue share (typically 20-30% for platform) 2. Negotiate revenue share (typically 20-30% for platform)
3. Integrate DBS check submission API 3. Integrate DBS check submission API
4. Build compliance/audit trail layer 4. Build compliance/audit trail layer
5. White-label DBS reports in TrueCV UI 5. White-label DBS reports in RealCV UI
### Timeline ### Timeline
- **Vendor selection:** 1-2 weeks - **Vendor selection:** 1-2 weeks
@@ -371,7 +371,7 @@
1. **Contact accredited vendors:** Verifile, DDC, or similar 1. **Contact accredited vendors:** Verifile, DDC, or similar
2. **Explain use case:** CV verification platform 2. **Explain use case:** CV verification platform
3. **Request sub-licensing:** Access to their HMRC integration 3. **Request sub-licensing:** Access to their HMRC integration
4. **Build wrapper:** TrueCV UI calls vendor API 4. **Build wrapper:** RealCV UI calls vendor API
#### Vendors with HMRC Access #### Vendors with HMRC Access
- Verifile (https://www.verifile.io/) - Verifile (https://www.verifile.io/)
@@ -407,7 +407,7 @@
### This Week ### This Week
1. **Email HEDD:** partnerships@hedd.ac.uk with: 1. **Email HEDD:** partnerships@hedd.ac.uk with:
- Company info (TrueCV) - Company info (RealCV)
- Use case (CV verification for UK recruiters) - Use case (CV verification for UK recruiters)
- Expected volume (start with 100/month) - Expected volume (start with 100/month)
- Request: API access or partnership discussion - Request: API access or partnership discussion
@@ -468,15 +468,15 @@ For each API integration, ensure:
## Contact Template for API Requests ## Contact Template for API Requests
``` ```
Subject: API Integration Request - TrueCV Recruitment Verification Platform Subject: API Integration Request - RealCV Recruitment Verification Platform
Dear [Service] Team, Dear [Service] Team,
We are developing TrueCV, a UK-focused CV verification platform for recruitment agencies and corporate HR departments. As part of our Phase 1 launch (Q1 2026), we would like to integrate with [Service Name] to verify [candidate credentials] in real-time during the hiring process. We are developing RealCV, a UK-focused CV verification platform for recruitment agencies and corporate HR departments. As part of our Phase 1 launch (Q1 2026), we would like to integrate with [Service Name] to verify [candidate credentials] in real-time during the hiring process.
Use Case: Use Case:
- Candidates upload CV during job application - Candidates upload CV during job application
- TrueCV extracts education/qualification claims - RealCV extracts education/qualification claims
- Real-time verification against [Service] records - Real-time verification against [Service] records
- Fraud flags generated for recruiter review - Fraud flags generated for recruiter review
@@ -501,7 +501,7 @@ Please advise next steps.
Best regards, Best regards,
[Your Name] [Your Name]
TrueCV RealCV
``` ```
--- ---

View File

@@ -2,7 +2,7 @@
TRUECV UK MARKET STRATEGY - COMPLETE DELIVERY PACKAGE TRUECV UK MARKET STRATEGY - COMPLETE DELIVERY PACKAGE
================================================================================ ================================================================================
Project: Rethinking TrueCV Feature Priorities with UK-Only Focus Project: Rethinking RealCV Feature Priorities with UK-Only Focus
Date Delivered: January 20, 2026 Date Delivered: January 20, 2026
Total Documents: 8 comprehensive strategy guides Total Documents: 8 comprehensive strategy guides
Total Content: ~200 pages Total Content: ~200 pages
@@ -68,7 +68,7 @@ MARKET OPPORTUNITY:
✓ £4.2B annual cost of CV fraud to UK employers ✓ £4.2B annual cost of CV fraud to UK employers
✓ 1 in 5 UK candidates falsify university degrees ✓ 1 in 5 UK candidates falsify university degrees
✓ 24% of screened CVs fail verification ✓ 24% of screened CVs fail verification
✓ £3.3M serviceable market for TrueCV ✓ £3.3M serviceable market for RealCV
✓ No existing competitor offers integrated UK CV verification ✓ No existing competitor offers integrated UK CV verification
COMPETITIVE ADVANTAGE: COMPETITIVE ADVANTAGE:
@@ -136,7 +136,7 @@ EXPECTED OUTCOMES:
COMPETITIVE LANDSCAPE ANALYSIS COMPETITIVE LANDSCAPE ANALYSIS
================================================================================ ================================================================================
COMPETITOR FEATURES OFFERED TrueCV ADVANTAGE COMPETITOR FEATURES OFFERED RealCV ADVANTAGE
───────────────────────────────────────────────────────────── ─────────────────────────────────────────────────────────────
Workable ATS + basic screening HEDD integration (exclusive) Workable ATS + basic screening HEDD integration (exclusive)
Deel Global hiring + screening UK-specific stack Deel Global hiring + screening UK-specific stack
@@ -150,7 +150,7 @@ No existing competitor integrates:
- GMC/NMC healthcare registers - GMC/NMC healthcare registers
- Timeline fraud detection - Timeline fraud detection
- Companies House director verification - Companies House director verification
TrueCV is only player filling this gap RealCV is only player filling this gap
MOAT BUILDING: MOAT BUILDING:
- Deep integrations difficult to replicate (6+ months each) - Deep integrations difficult to replicate (6+ months each)
@@ -365,17 +365,17 @@ FOR SALES/MARKETING:
DOCUMENT LOCATIONS DOCUMENT LOCATIONS
================================================================================ ================================================================================
All files have been created in: /mnt/d/Git/TrueCV/ All files have been created in: /mnt/d/Git/RealCV/
FILE STRUCTURE: FILE STRUCTURE:
/mnt/d/Git/TrueCV/QUICK_REFERENCE.md (Start here) /mnt/d/Git/RealCV/QUICK_REFERENCE.md (Start here)
/mnt/d/Git/TrueCV/EXECUTIVE_SUMMARY.md (Execs/investors) /mnt/d/Git/RealCV/EXECUTIVE_SUMMARY.md (Execs/investors)
/mnt/d/Git/TrueCV/UK_FEATURE_PRIORITIZATION.md (Product) /mnt/d/Git/RealCV/UK_FEATURE_PRIORITIZATION.md (Product)
/mnt/d/Git/TrueCV/PHASE1_TECHNICAL_IMPLEMENTATION.md (Engineering) /mnt/d/Git/RealCV/PHASE1_TECHNICAL_IMPLEMENTATION.md (Engineering)
/mnt/d/Git/TrueCV/UK_MARKET_STRATEGY.md (Strategy/Sales/Marketing) /mnt/d/Git/RealCV/UK_MARKET_STRATEGY.md (Strategy/Sales/Marketing)
/mnt/d/Git/TrueCV/API_RESOURCES_AND_CONTACTS.md (Implementation) /mnt/d/Git/RealCV/API_RESOURCES_AND_CONTACTS.md (Implementation)
/mnt/d/Git/TrueCV/README_UK_STRATEGY.md (Navigation) /mnt/d/Git/RealCV/README_UK_STRATEGY.md (Navigation)
/mnt/d/Git/TrueCV/INDEX.md (Reference index) /mnt/d/Git/RealCV/INDEX.md (Reference index)
FILES READY FOR USE IMMEDIATELY. FILES READY FOR USE IMMEDIATELY.
@@ -445,7 +445,7 @@ PLANNED UPDATES:
CLOSING NOTES CLOSING NOTES
================================================================================ ================================================================================
This strategy document represents a comprehensive analysis of TrueCV's This strategy document represents a comprehensive analysis of RealCV's
opportunity in the UK CV verification market. It provides: opportunity in the UK CV verification market. It provides:
✓ Clear market opportunity quantification (£3.3M addressable) ✓ Clear market opportunity quantification (£3.3M addressable)

View File

@@ -3,11 +3,11 @@ FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src WORKDIR /src
# Copy solution and project files first for better layer caching # Copy solution and project files first for better layer caching
COPY TrueCV.sln ./ COPY RealCV.sln ./
COPY src/TrueCV.Domain/TrueCV.Domain.csproj src/TrueCV.Domain/ COPY src/RealCV.Domain/RealCV.Domain.csproj src/RealCV.Domain/
COPY src/TrueCV.Application/TrueCV.Application.csproj src/TrueCV.Application/ COPY src/RealCV.Application/RealCV.Application.csproj src/RealCV.Application/
COPY src/TrueCV.Infrastructure/TrueCV.Infrastructure.csproj src/TrueCV.Infrastructure/ COPY src/RealCV.Infrastructure/RealCV.Infrastructure.csproj src/RealCV.Infrastructure/
COPY src/TrueCV.Web/TrueCV.Web.csproj src/TrueCV.Web/ COPY src/RealCV.Web/RealCV.Web.csproj src/RealCV.Web/
# Restore dependencies # Restore dependencies
RUN dotnet restore RUN dotnet restore
@@ -16,7 +16,7 @@ RUN dotnet restore
COPY src/ src/ COPY src/ src/
# Build and publish # Build and publish
WORKDIR /src/src/TrueCV.Web WORKDIR /src/src/RealCV.Web
RUN dotnet publish -c Release -o /app/publish --no-restore RUN dotnet publish -c Release -o /app/publish --no-restore
# Runtime stage # Runtime stage
@@ -27,16 +27,16 @@ WORKDIR /app
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Create non-root user for security # Create non-root user for security
RUN groupadd -r truecv && useradd -r -g truecv truecv RUN groupadd -r realcv && useradd -r -g realcv realcv
# Copy published app # Copy published app
COPY --from=build /app/publish . COPY --from=build /app/publish .
# Set ownership # Set ownership
RUN chown -R truecv:truecv /app RUN chown -R realcv:realcv /app
# Switch to non-root user # Switch to non-root user
USER truecv USER realcv
# Expose port # Expose port
EXPOSE 8080 EXPOSE 8080
@@ -51,4 +51,4 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1 CMD curl -f http://localhost:8080/health || exit 1
# Start the app # Start the app
ENTRYPOINT ["dotnet", "TrueCV.Web.dll"] ENTRYPOINT ["dotnet", "RealCV.Web.dll"]

View File

@@ -7,11 +7,11 @@ RUN dotnet tool install --global dotnet-ef
ENV PATH="$PATH:/root/.dotnet/tools" ENV PATH="$PATH:/root/.dotnet/tools"
# Copy solution and project files # Copy solution and project files
COPY TrueCV.sln ./ COPY RealCV.sln ./
COPY src/TrueCV.Domain/TrueCV.Domain.csproj src/TrueCV.Domain/ COPY src/RealCV.Domain/RealCV.Domain.csproj src/RealCV.Domain/
COPY src/TrueCV.Application/TrueCV.Application.csproj src/TrueCV.Application/ COPY src/RealCV.Application/RealCV.Application.csproj src/RealCV.Application/
COPY src/TrueCV.Infrastructure/TrueCV.Infrastructure.csproj src/TrueCV.Infrastructure/ COPY src/RealCV.Infrastructure/RealCV.Infrastructure.csproj src/RealCV.Infrastructure/
COPY src/TrueCV.Web/TrueCV.Web.csproj src/TrueCV.Web/ COPY src/RealCV.Web/RealCV.Web.csproj src/RealCV.Web/
# Restore dependencies # Restore dependencies
RUN dotnet restore RUN dotnet restore
@@ -20,7 +20,7 @@ RUN dotnet restore
COPY src/ src/ COPY src/ src/
# Build the project # Build the project
RUN dotnet build src/TrueCV.Web/TrueCV.Web.csproj -c Release RUN dotnet build src/RealCV.Web/RealCV.Web.csproj -c Release
# Run migrations on startup # Run migrations on startup
ENTRYPOINT ["dotnet", "ef", "database", "update", "--project", "src/TrueCV.Infrastructure", "--startup-project", "src/TrueCV.Web", "--no-build", "-c", "Release"] ENTRYPOINT ["dotnet", "ef", "database", "update", "--project", "src/RealCV.Infrastructure", "--startup-project", "src/RealCV.Web", "--no-build", "-c", "Release"]

View File

@@ -1,4 +1,4 @@
# TrueCV UK Market Opportunity - Executive Summary # RealCV UK Market Opportunity - Executive Summary
**Prepared for:** Product Leadership **Prepared for:** Product Leadership
**Date:** January 2026 **Date:** January 2026
@@ -8,7 +8,7 @@
## The Opportunity ## The Opportunity
**UK CV fraud costs employers £4.2B annually. Current verification takes 5-10 days. TrueCV can do it in seconds.** **UK CV fraud costs employers £4.2B annually. Current verification takes 5-10 days. RealCV can do it in seconds.**
### Market Problem ### Market Problem
- **1 in 5 UK candidates** falsify university degrees - **1 in 5 UK candidates** falsify university degrees
@@ -25,7 +25,7 @@
--- ---
## TrueCV's Solution ## RealCV's Solution
**Integrated CV verification platform leveraging UK-specific data sources:** **Integrated CV verification platform leveraging UK-specific data sources:**
@@ -42,7 +42,7 @@
## Competitive Advantage ## Competitive Advantage
**TrueCV is the ONLY CV verification tool that:** **RealCV is the ONLY CV verification tool that:**
1. ✅ Integrates with HEDD (no competitors do) 1. ✅ Integrates with HEDD (no competitors do)
2. ✅ Targets healthcare recruiting niche (GMC/NMC) 2. ✅ Targets healthcare recruiting niche (GMC/NMC)
@@ -59,7 +59,7 @@
### Addressable Market ### Addressable Market
- **18,300 potential customers** (recruitment agencies + corporate HR) - **18,300 potential customers** (recruitment agencies + corporate HR)
- **£2.8B UK pre-employment screening market** - **£2.8B UK pre-employment screening market**
- **~£3.3M serviceable opportunity** for TrueCV platform - **~£3.3M serviceable opportunity** for RealCV platform
### Year 1 Revenue Target ### Year 1 Revenue Target
- **50-75 paying customers** at £49-199/month - **50-75 paying customers** at £49-199/month
@@ -230,7 +230,7 @@
## Contact & Next Steps ## Contact & Next Steps
**Product Lead:** [Name] - TrueCV Product Strategy **Product Lead:** [Name] - RealCV Product Strategy
**Engineering Lead:** [Name] - Phase 1 Technical Implementation **Engineering Lead:** [Name] - Phase 1 Technical Implementation
**Next Meeting:** [Date] - Review technical implementation plan + finalize go-to-market **Next Meeting:** [Date] - Review technical implementation plan + finalize go-to-market

View File

@@ -1,4 +1,4 @@
# TrueCV UK Strategy - Complete Document Index # RealCV UK Strategy - Complete Document Index
**Total Documents:** 6 comprehensive strategy guides **Total Documents:** 6 comprehensive strategy guides
**Total Pages:** ~200 pages **Total Pages:** ~200 pages
@@ -392,7 +392,7 @@ Each document has been:
## Copyright & Distribution ## Copyright & Distribution
**Ownership:** TrueCV Product Team **Ownership:** RealCV Product Team
**Classification:** Internal Only **Classification:** Internal Only
**Distribution:** Leadership, Product, Engineering only **Distribution:** Leadership, Product, Engineering only
@@ -433,13 +433,13 @@ Each document has been:
``` ```
MARKET OPPORTUNITY MARKET OPPORTUNITY
UK CV fraud cost: £4.2B annually UK CV fraud cost: £4.2B annually
Addressable market: £3.3M (TrueCV's portion) Addressable market: £3.3M (RealCV's portion)
Candidates lying: 1 in 5 (20%) Candidates lying: 1 in 5 (20%)
Failed verifications: 24% of CVs Failed verifications: 24% of CVs
Current verification time: 5-10 DAYS Current verification time: 5-10 DAYS
COMPETITIVE ADVANTAGE COMPETITIVE ADVANTAGE
Features only TrueCV offers: 4 major features Features only RealCV offers: 4 major features
Market gap size: Unexploited (£3.3M) Market gap size: Unexploited (£3.3M)
Time to market advantage: 6-12 months Time to market advantage: 6-12 months
@@ -479,14 +479,14 @@ Phase 3 (Q3): +1 customer success + 1 analyst
## Quick Links ## Quick Links
**Files Created:** **Files Created:**
- `/mnt/d/Git/TrueCV/QUICK_REFERENCE.md` - `/mnt/d/Git/RealCV/QUICK_REFERENCE.md`
- `/mnt/d/Git/TrueCV/EXECUTIVE_SUMMARY.md` - `/mnt/d/Git/RealCV/EXECUTIVE_SUMMARY.md`
- `/mnt/d/Git/TrueCV/UK_FEATURE_PRIORITIZATION.md` - `/mnt/d/Git/RealCV/UK_FEATURE_PRIORITIZATION.md`
- `/mnt/d/Git/TrueCV/PHASE1_TECHNICAL_IMPLEMENTATION.md` - `/mnt/d/Git/RealCV/PHASE1_TECHNICAL_IMPLEMENTATION.md`
- `/mnt/d/Git/TrueCV/UK_MARKET_STRATEGY.md` - `/mnt/d/Git/RealCV/UK_MARKET_STRATEGY.md`
- `/mnt/d/Git/TrueCV/API_RESOURCES_AND_CONTACTS.md` - `/mnt/d/Git/RealCV/API_RESOURCES_AND_CONTACTS.md`
- `/mnt/d/Git/TrueCV/README_UK_STRATEGY.md` - `/mnt/d/Git/RealCV/README_UK_STRATEGY.md`
- `/mnt/d/Git/TrueCV/INDEX.md` (this file) - `/mnt/d/Git/RealCV/INDEX.md` (this file)
**Total:** 8 comprehensive strategy documents (~200 pages) **Total:** 8 comprehensive strategy documents (~200 pages)

View File

@@ -10,7 +10,7 @@
### Overview ### Overview
Real-time integration with HEDD (Higher Education Degree Datacheck) to verify UK degrees against 140+ university records. Real-time integration with HEDD (Higher Education Degree Datacheck) to verify UK degrees against 140+ university records.
**Current Baseline:** TrueCV parses education entries from CV using Claude AI **Current Baseline:** RealCV parses education entries from CV using Claude AI
**Gap:** No verification against actual university records **Gap:** No verification against actual university records
**Value:** Eliminates 90%+ of fake degree claims **Value:** Eliminates 90%+ of fake degree claims
@@ -32,10 +32,10 @@ Report & UI
### Phase 1a: Create Infrastructure (Days 1-5) ### Phase 1a: Create Infrastructure (Days 1-5)
#### File 1: `src/TrueCV.Infrastructure/Configuration/HeddSettings.cs` #### File 1: `src/RealCV.Infrastructure/Configuration/HeddSettings.cs`
```csharp ```csharp
namespace TrueCV.Infrastructure.Configuration; namespace RealCV.Infrastructure.Configuration;
public class HeddSettings public class HeddSettings
{ {
@@ -46,7 +46,7 @@ public class HeddSettings
} }
``` ```
#### File 2: `src/TrueCV.Infrastructure/ExternalApis/HeddClient.cs` #### File 2: `src/RealCV.Infrastructure/ExternalApis/HeddClient.cs`
```csharp ```csharp
using System.Net.Http.Json; using System.Net.Http.Json;
@@ -55,9 +55,9 @@ using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
namespace TrueCV.Infrastructure.ExternalApis; namespace RealCV.Infrastructure.ExternalApis;
public sealed class HeddClient public sealed class HeddClient
{ {
@@ -242,12 +242,12 @@ public sealed record HeddManualVerificationStatus
} }
``` ```
#### File 3: `src/TrueCV.Application/Interfaces/IEducationVerifierService.cs` #### File 3: `src/RealCV.Application/Interfaces/IEducationVerifierService.cs`
```csharp ```csharp
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface IEducationVerifierService public interface IEducationVerifierService
{ {
@@ -273,10 +273,10 @@ public interface IEducationVerifierService
} }
``` ```
#### File 4: `src/TrueCV.Application/Models/EducationVerificationResult.cs` #### File 4: `src/RealCV.Application/Models/EducationVerificationResult.cs`
```csharp ```csharp
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record EducationVerificationResult public sealed record EducationVerificationResult
{ {
@@ -370,15 +370,15 @@ public enum ManualVerificationStatus
### Phase 1b: Implement Service Layer (Days 6-10) ### Phase 1b: Implement Service Layer (Days 6-10)
#### File 5: `src/TrueCV.Infrastructure/Services/EducationVerifierService.cs` #### File 5: `src/RealCV.Infrastructure/Services/EducationVerifierService.cs`
```csharp ```csharp
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Infrastructure.ExternalApis; using RealCV.Infrastructure.ExternalApis;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class EducationVerifierService : IEducationVerifierService public sealed class EducationVerifierService : IEducationVerifierService
{ {
@@ -558,10 +558,10 @@ public sealed class EducationVerifierService : IEducationVerifierService
### Phase 1c: Database & Flag Integration (Days 11-12) ### Phase 1c: Database & Flag Integration (Days 11-12)
#### Update: `src/TrueCV.Domain/Enums/FlagCategory.cs` #### Update: `src/RealCV.Domain/Enums/FlagCategory.cs`
```csharp ```csharp
namespace TrueCV.Domain.Enums; namespace RealCV.Domain.Enums;
public enum FlagCategory public enum FlagCategory
{ {
@@ -575,14 +575,14 @@ public enum FlagCategory
} }
``` ```
#### New File: `src/TrueCV.Infrastructure/Services/EducationFlagGenerator.cs` #### New File: `src/RealCV.Infrastructure/Services/EducationFlagGenerator.cs`
```csharp ```csharp
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class EducationFlagGenerator public sealed class EducationFlagGenerator
{ {
@@ -683,16 +683,16 @@ public sealed class EducationFlagGenerator
### Phase 1d: Companies House Enhancement - Director Verification ### Phase 1d: Companies House Enhancement - Director Verification
#### File: `src/TrueCV.Infrastructure/ExternalApis/CompaniesHouseDirectorsClient.cs` #### File: `src/RealCV.Infrastructure/ExternalApis/CompaniesHouseDirectorsClient.cs`
```csharp ```csharp
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Infrastructure.ExternalApis; using RealCV.Infrastructure.ExternalApis;
namespace TrueCV.Infrastructure.ExternalApis; namespace RealCV.Infrastructure.ExternalApis;
public sealed class CompaniesHouseDirectorsClient public sealed class CompaniesHouseDirectorsClient
{ {
@@ -795,10 +795,10 @@ public sealed record Officer
} }
``` ```
#### File: `src/TrueCV.Application/Interfaces/IDirectorshipVerifierService.cs` #### File: `src/RealCV.Application/Interfaces/IDirectorshipVerifierService.cs`
```csharp ```csharp
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface IDirectorshipVerifierService public interface IDirectorshipVerifierService
{ {
@@ -826,15 +826,15 @@ public sealed record DirectorshipVerificationResult
} }
``` ```
#### File: `src/TrueCV.Infrastructure/Services/DirectorshipVerifierService.cs` #### File: `src/RealCV.Infrastructure/Services/DirectorshipVerifierService.cs`
```csharp ```csharp
using FuzzySharp; using FuzzySharp;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Infrastructure.ExternalApis; using RealCV.Infrastructure.ExternalApis;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class DirectorshipVerifierService : IDirectorshipVerifierService public sealed class DirectorshipVerifierService : IDirectorshipVerifierService
{ {
@@ -1070,15 +1070,15 @@ public sealed class DirectorshipVerifierService : IDirectorshipVerifierService
### Phase 1e: Enhanced Timeline Analysis ### Phase 1e: Enhanced Timeline Analysis
#### File: `src/TrueCV.Infrastructure/Services/EnhancedTimelineAnalyserService.cs` #### File: `src/RealCV.Infrastructure/Services/EnhancedTimelineAnalyserService.cs`
```csharp ```csharp
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class EnhancedTimelineAnalyserService public sealed class EnhancedTimelineAnalyserService
{ {
@@ -1226,7 +1226,7 @@ public sealed class EnhancedTimelineAnalyserService
### Phase 1f: Dependency Injection & Integration (Days 13-14) ### Phase 1f: Dependency Injection & Integration (Days 13-14)
#### Update: `src/TrueCV.Infrastructure/DependencyInjection.cs` #### Update: `src/RealCV.Infrastructure/DependencyInjection.cs`
```csharp ```csharp
// Add to existing DependencyInjection class: // Add to existing DependencyInjection class:
@@ -1244,7 +1244,7 @@ services.AddScoped<IDirectorshipVerifierService, DirectorshipVerifierService>();
services.AddScoped<EnhancedTimelineAnalyserService>(); services.AddScoped<EnhancedTimelineAnalyserService>();
``` ```
#### Update: `src/TrueCV.Infrastructure/Jobs/ProcessCVCheckJob.cs` #### Update: `src/RealCV.Infrastructure/Jobs/ProcessCVCheckJob.cs`
Add education and directorship verification to the processing pipeline: Add education and directorship verification to the processing pipeline:
@@ -1356,16 +1356,16 @@ private async Task<List<CVFlag>> VerifyDirectorshipsAsync(
### Phase 1g: Testing & QA (Days 15-16) ### Phase 1g: Testing & QA (Days 15-16)
#### Test File: `tests/TrueCV.Tests/Services/EducationVerifierServiceTests.cs` #### Test File: `tests/RealCV.Tests/Services/EducationVerifierServiceTests.cs`
```csharp ```csharp
using Moq; using Moq;
using Xunit; using Xunit;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Infrastructure.ExternalApis; using RealCV.Infrastructure.ExternalApis;
using TrueCV.Infrastructure.Services; using RealCV.Infrastructure.Services;
namespace TrueCV.Tests.Services; namespace RealCV.Tests.Services;
public class EducationVerifierServiceTests public class EducationVerifierServiceTests
{ {
@@ -1467,7 +1467,7 @@ public class EducationVerifierServiceTests
Create migration for storing verification results: Create migration for storing verification results:
```bash ```bash
dotnet ef migrations add AddEducationAndDirectorshipVerification --project src/TrueCV.Infrastructure --startup-project src/TrueCV.Web dotnet ef migrations add AddEducationAndDirectorshipVerification --project src/RealCV.Infrastructure --startup-project src/RealCV.Web
``` ```
Add optional columns to CVCheck entity: Add optional columns to CVCheck entity:

View File

@@ -1,4 +1,4 @@
# TrueCV UK Strategy - Quick Reference Card # RealCV UK Strategy - Quick Reference Card
**Print this page for desk reference during planning & execution** **Print this page for desk reference during planning & execution**
@@ -11,7 +11,7 @@ UK CV Fraud Cost: £4.2B annually
Candidates Lying: 1 in 5 (20%) Candidates Lying: 1 in 5 (20%)
Failed Verifications: 24% of CVs Failed Verifications: 24% of CVs
Current Verification Time: 5-10 DAYS Current Verification Time: 5-10 DAYS
TrueCV Solution Time: 5 SECONDS ⚡ RealCV Solution Time: 5 SECONDS ⚡
Market Addressable: £3.3M (UK) Market Addressable: £3.3M (UK)
Year 1 Target Revenue: £30-240K Year 1 Target Revenue: £30-240K
@@ -24,7 +24,7 @@ Expected Profitability: Month 6-7
## Competitive Advantage (Why Now) ## Competitive Advantage (Why Now)
``` ```
FEATURE TrueCV Workable Deel Checkr FEATURE RealCV Workable Deel Checkr
───────────────────────────────────────────────────────── ─────────────────────────────────────────────────────────
HEDD Degree Verification ✅ ❌ ❌ ❌ HEDD Degree Verification ✅ ❌ ❌ ❌
GMC/NMC Healthcare ✅ ❌ ❌ ❌ GMC/NMC Healthcare ✅ ❌ ❌ ❌
@@ -370,7 +370,7 @@ Based on your role:
## One-Liner Summary ## One-Liner Summary
> **TrueCV is the only UK CV verification tool that catches 90% of fake degrees + employment fraud in seconds, leveraging HEDD, GMC/NMC, and Companies House APIs to dominate a £3.3M untapped recruitment market.** > **RealCV is the only UK CV verification tool that catches 90% of fake degrees + employment fraud in seconds, leveraging HEDD, GMC/NMC, and Companies House APIs to dominate a £3.3M untapped recruitment market.**
--- ---

View File

@@ -1,8 +1,8 @@
# TrueCV UK Market Strategy - Complete Package # RealCV UK Market Strategy - Complete Package
## Overview ## Overview
This directory contains the complete product strategy and implementation plan for launching TrueCV with a UK-only focus. The documents provide market analysis, feature prioritization, technical implementation details, and go-to-market strategy. This directory contains the complete product strategy and implementation plan for launching RealCV with a UK-only focus. The documents provide market analysis, feature prioritization, technical implementation details, and go-to-market strategy.
--- ---
@@ -54,7 +54,7 @@ This directory contains the complete product strategy and implementation plan fo
**Audience:** Product Team, Marketing, Sales **Audience:** Product Team, Marketing, Sales
**Purpose:** Comprehensive market analysis and go-to-market strategy **Purpose:** Comprehensive market analysis and go-to-market strategy
**Key Sections:** **Key Sections:**
- Market sizing (£2.8B UK screening market, £3.3M TrueCV TAM) - Market sizing (£2.8B UK screening market, £3.3M RealCV TAM)
- Competitive landscape analysis - Competitive landscape analysis
- 3-phase product roadmap (Q1-Q3 2026) - 3-phase product roadmap (Q1-Q3 2026)
- GTM strategy (4 sales channels) - GTM strategy (4 sales channels)
@@ -336,7 +336,7 @@ This directory contains the complete product strategy and implementation plan fo
## File Manifest ## File Manifest
``` ```
/mnt/d/Git/TrueCV/ /mnt/d/Git/RealCV/
├── EXECUTIVE_SUMMARY.md (5-page exec overview) ├── EXECUTIVE_SUMMARY.md (5-page exec overview)
├── UK_FEATURE_PRIORITIZATION.md (30-page detailed prioritization) ├── UK_FEATURE_PRIORITIZATION.md (30-page detailed prioritization)
├── PHASE1_TECHNICAL_IMPLEMENTATION.md (60-page technical specs + code) ├── PHASE1_TECHNICAL_IMPLEMENTATION.md (60-page technical specs + code)
@@ -403,7 +403,7 @@ These documents will be updated quarterly with:
## License & Confidentiality ## License & Confidentiality
This strategy document is internal to TrueCV and contains commercially sensitive information including: This strategy document is internal to RealCV and contains commercially sensitive information including:
- Market sizing & financial projections - Market sizing & financial projections
- Competitive positioning - Competitive positioning
- Product roadmap - Product roadmap

View File

@@ -5,17 +5,17 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F25C3740-9240-46DF-BC34-985BC577216B}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F25C3740-9240-46DF-BC34-985BC577216B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCV.Domain", "src\TrueCV.Domain\TrueCV.Domain.csproj", "{41AC48AF-09BC-48D1-9CA4-1B05D3B693F0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealCV.Domain", "src\RealCV.Domain\RealCV.Domain.csproj", "{41AC48AF-09BC-48D1-9CA4-1B05D3B693F0}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCV.Application", "src\TrueCV.Application\TrueCV.Application.csproj", "{A8A1BA81-3B2F-4F95-BB15-ACA40DF2A70E}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealCV.Application", "src\RealCV.Application\RealCV.Application.csproj", "{A8A1BA81-3B2F-4F95-BB15-ACA40DF2A70E}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCV.Infrastructure", "src\TrueCV.Infrastructure\TrueCV.Infrastructure.csproj", "{03DB607C-9592-4930-8C89-3E257A319278}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealCV.Infrastructure", "src\RealCV.Infrastructure\RealCV.Infrastructure.csproj", "{03DB607C-9592-4930-8C89-3E257A319278}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCV.Web", "src\TrueCV.Web\TrueCV.Web.csproj", "{D69F57DB-3092-48AF-81BB-868E3749C638}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealCV.Web", "src\RealCV.Web\RealCV.Web.csproj", "{D69F57DB-3092-48AF-81BB-868E3749C638}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{80890010-EDA6-418B-AD6C-5A9D875594C4}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{80890010-EDA6-418B-AD6C-5A9D875594C4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCV.Tests", "tests\TrueCV.Tests\TrueCV.Tests.csproj", "{4450D4F1-4EB9-445E-904B-1C57701493D8}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RealCV.Tests", "tests\RealCV.Tests\RealCV.Tests.csproj", "{4450D4F1-4EB9-445E-904B-1C57701493D8}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -1,4 +1,4 @@
# TrueCV UK Market Feature Prioritization # RealCV UK Market Feature Prioritization
**Date:** January 2026 **Date:** January 2026
**Focus:** UK-Only Market Opportunities **Focus:** UK-Only Market Opportunities
@@ -8,7 +8,7 @@
## Executive Summary ## Executive Summary
UK CV fraud is escalating with AI-generated deepfakes, synthetic identities, and traditional qualification falsification. The most impactful opportunity for TrueCV in the UK market is **degree verification integration** (HEDD API), followed by **employment verification automation** and **professional body registration checks**. These three features represent 78% of recruiter pain points and address 85% of detected fraud patterns. UK CV fraud is escalating with AI-generated deepfakes, synthetic identities, and traditional qualification falsification. The most impactful opportunity for RealCV in the UK market is **degree verification integration** (HEDD API), followed by **employment verification automation** and **professional body registration checks**. These three features represent 78% of recruiter pain points and address 85% of detected fraud patterns.
--- ---
@@ -48,7 +48,7 @@ UK CV fraud is escalating with AI-generated deepfakes, synthetic identities, and
- **Cost:** Typically £1-5 per verification (commercial rates) - **Cost:** Typically £1-5 per verification (commercial rates)
**Implementation Effort:** **Medium (2-3 weeks)** **Implementation Effort:** **Medium (2-3 weeks)**
- Iframe/form integration into TrueCV UI - Iframe/form integration into RealCV UI
- Candidate consent workflow - Candidate consent workflow
- Result polling for manual verifications - Result polling for manual verifications
- Database sync with CVData.Education entries - Database sync with CVData.Education entries
@@ -83,7 +83,7 @@ UK CV fraud is escalating with AI-generated deepfakes, synthetic identities, and
**Impact Score:** **6.5/10** **Impact Score:** **6.5/10**
- Targets 1.5M NHS workers + private doctors - Targets 1.5M NHS workers + private doctors
- High value for healthcare recruitment - High value for healthcare recruitment
- Medium market size in TrueCV context - Medium market size in RealCV context
- But limited to one profession vs. broad application - But limited to one profession vs. broad application
--- ---
@@ -116,7 +116,7 @@ UK CV fraud is escalating with AI-generated deepfakes, synthetic identities, and
### 4. Companies House API (Already Integrated) ### 4. Companies House API (Already Integrated)
**Status:** ✓ Already implemented in TrueCV **Status:** ✓ Already implemented in RealCV
**Current Coverage:** **Current Coverage:**
- Fuzzy matching on company names (70%+ threshold) - Fuzzy matching on company names (70%+ threshold)
@@ -205,7 +205,7 @@ UK CV fraud is escalating with AI-generated deepfakes, synthetic identities, and
- Links to individual regulators - Links to individual regulators
- Government-maintained reference - Government-maintained reference
**Use Case for TrueCV:** **Use Case for RealCV:**
- **Enrichment layer:** When CV claims regulated profession, cross-check against GOV.UK registry - **Enrichment layer:** When CV claims regulated profession, cross-check against GOV.UK registry
- **Flag generation:** "Claims regulated profession but regulator not found" - **Flag generation:** "Claims regulated profession but regulator not found"
- **Guidance:** Link to correct regulator for user lookup - **Guidance:** Link to correct regulator for user lookup
@@ -284,9 +284,9 @@ MEDIUM VALUE + EASY │ MEDIUM VALUE + HARD
- **Pricing:** Pass-through cost model ($1-2 per verification to user) - **Pricing:** Pass-through cost model ($1-2 per verification to user)
- **Implementation:** - **Implementation:**
``` ```
src/TrueCV.Infrastructure/ExternalApis/HeddClient.cs src/RealCV.Infrastructure/ExternalApis/HeddClient.cs
src/TrueCV.Application/Interfaces/IEducationVerifierService.cs src/RealCV.Application/Interfaces/IEducationVerifierService.cs
src/TrueCV.Infrastructure/Services/EducationVerifierService.cs src/RealCV.Infrastructure/Services/EducationVerifierService.cs
FlagCategory += EducationVerification FlagCategory += EducationVerification
Add new flag types: Add new flag types:
- DegreeNotFound - DegreeNotFound
@@ -304,7 +304,7 @@ MEDIUM VALUE + EASY │ MEDIUM VALUE + HARD
- Identify degree end date before employment start anomalies - Identify degree end date before employment start anomalies
- **Implementation:** - **Implementation:**
``` ```
src/TrueCV.Infrastructure/Services/TimelineAnalyserService.cs src/RealCV.Infrastructure/Services/TimelineAnalyserService.cs
- Add: UKEmploymentPatternAnalyzer - Add: UKEmploymentPatternAnalyzer
- Add: EducationEmploymentSequenceValidator - Add: EducationEmploymentSequenceValidator
- New flags: - New flags:
@@ -322,8 +322,8 @@ MEDIUM VALUE + EASY │ MEDIUM VALUE + HARD
- Recurring revenue potential - Recurring revenue potential
- **Implementation:** - **Implementation:**
``` ```
src/TrueCV.Infrastructure/ExternalApis/HealthcareRegisterClient.cs src/RealCV.Infrastructure/ExternalApis/HealthcareRegisterClient.cs
src/TrueCV.Application/Interfaces/IHealthcareVerifierService.cs src/RealCV.Application/Interfaces/IHealthcareVerifierService.cs
FlagCategory += HealthcareRegistration FlagCategory += HealthcareRegistration
New flags: New flags:
- GMCNotFound / GMCRestricted / GMCLapsed - GMCNotFound / GMCRestricted / GMCLapsed
@@ -338,7 +338,7 @@ MEDIUM VALUE + EASY │ MEDIUM VALUE + HARD
- Detects employment after company dissolution - Detects employment after company dissolution
- **Implementation:** - **Implementation:**
``` ```
Extend: src/TrueCV.Infrastructure/ExternalApis/CompaniesHouseClient.cs Extend: src/RealCV.Infrastructure/ExternalApis/CompaniesHouseClient.cs
Add: OfficerAppointmentsClient.GetDirectorAppointments(name, companyNumber) Add: OfficerAppointmentsClient.GetDirectorAppointments(name, companyNumber)
New Service: DirectorshipVerificationService New Service: DirectorshipVerificationService
FlagCategory += DirectorshipVerification FlagCategory += DirectorshipVerification
@@ -360,8 +360,8 @@ MEDIUM VALUE + EASY │ MEDIUM VALUE + HARD
- Regulatory appeal - Regulatory appeal
- **Implementation:** - **Implementation:**
``` ```
src/TrueCV.Infrastructure/ExternalApis/ProfessionalBodyClient.cs src/RealCV.Infrastructure/ExternalApis/ProfessionalBodyClient.cs
src/TrueCV.Infrastructure/ExternalApis/Scrapers/ src/RealCV.Infrastructure/ExternalApis/Scrapers/
- ICAEWMembershipVerifier.cs - ICAEWMembershipVerifier.cs
- SRALawverVerifier.cs - SRALawverVerifier.cs
- IETEngineerVerifier.cs - IETEngineerVerifier.cs
@@ -569,7 +569,7 @@ public class DirectorshipVerificationService
## Competitive Advantage Summary ## Competitive Advantage Summary
| Feature | TrueCV Advantage | Timeline | | Feature | RealCV Advantage | Timeline |
|---|---|---| |---|---|---|
| **HEDD Integration** | Only dedicated CV tool with instant degree verification | Q1 2026 | | **HEDD Integration** | Only dedicated CV tool with instant degree verification | Q1 2026 |
| **Healthcare Register Targeting** | Only tool targeting healthcare recruitment niche | Q1 2026 | | **Healthcare Register Targeting** | Only tool targeting healthcare recruitment niche | Q1 2026 |

View File

@@ -1,4 +1,4 @@
# TrueCV UK Market Strategy & Product Roadmap # RealCV UK Market Strategy & Product Roadmap
**Document Date:** January 2026 **Document Date:** January 2026
**Focus:** UK CV verification market positioning **Focus:** UK CV verification market positioning
@@ -37,7 +37,7 @@
### SAM (Serviceable Addressable Market) ### SAM (Serviceable Addressable Market)
**TrueCV Target Segment:** **RealCV Target Segment:**
- Mid-market recruitment agencies (50-500 staff): ~800 companies - Mid-market recruitment agencies (50-500 staff): ~800 companies
- Corporate HR departments (100+ employees): ~15,000 companies - Corporate HR departments (100+ employees): ~15,000 companies
- Specialist vertical recruiters (healthcare, finance, legal): ~2,500 companies - Specialist vertical recruiters (healthcare, finance, legal): ~2,500 companies
@@ -65,9 +65,9 @@
| **Verifile** | Pre-employment screening | Established relationships | Traditional manual process | | **Verifile** | Pre-employment screening | Established relationships | Traditional manual process |
| **Veriff** | Identity verification | Strong deepfake tech | Not employment-focused | | **Veriff** | Identity verification | Strong deepfake tech | Not employment-focused |
### TrueCV Differentiation ### RealCV Differentiation
| Feature | TrueCV | Workable | Deel | Checkr | Verifile | | Feature | RealCV | Workable | Deel | Checkr | Verifile |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| **Degree Verification (HEDD)** | ✅ Q1 2026 | ❌ | ❌ | ❌ | ❌ | | **Degree Verification (HEDD)** | ✅ Q1 2026 | ❌ | ❌ | ❌ | ❌ |
| **Healthcare Register Checks** | ✅ Q1 2026 | ❌ | ❌ | ❌ | ❌ | | **Healthcare Register Checks** | ✅ Q1 2026 | ❌ | ❌ | ❌ | ❌ |
@@ -194,7 +194,7 @@
### Marketing Messaging ### Marketing Messaging
**Tagline:** "Hire with Confidence. Verify with TrueCV." **Tagline:** "Hire with Confidence. Verify with RealCV."
**Core Messages:** **Core Messages:**
1. **For Recruiters:** "Catch 90% of degree fraud in seconds. One-click HEDD verification." 1. **For Recruiters:** "Catch 90% of degree fraud in seconds. One-click HEDD verification."
@@ -279,7 +279,7 @@
- **API Uptime:** 99.9% - **API Uptime:** 99.9%
### Market Metrics ### Market Metrics
- **Brand Awareness:** 15%+ of recruitment agencies aware of TrueCV - **Brand Awareness:** 15%+ of recruitment agencies aware of RealCV
- **Market Share:** 0.5-1% of addressable recruitment screening market - **Market Share:** 0.5-1% of addressable recruitment screening market
- **Vertical Penetration:** 3%+ of healthcare recruiters, 2%+ financial recruiters - **Vertical Penetration:** 3%+ of healthcare recruiters, 2%+ financial recruiters
@@ -369,7 +369,7 @@
## Conclusion ## Conclusion
TrueCV addresses a massive UK market problem (£4.2B+ annual cost from CV fraud) with a focused, integrated solution. By launching with HEDD degree verification + timeline fraud detection in Q1 2026, we capture first-mover advantage in a gap no competitor fills. RealCV addresses a massive UK market problem (£4.2B+ annual cost from CV fraud) with a focused, integrated solution. By launching with HEDD degree verification + timeline fraud detection in Q1 2026, we capture first-mover advantage in a gap no competitor fills.
**The opportunity:** Become the UK's trusted CV verification layer for recruitment, reducing fraud while accelerating hiring processes. **The opportunity:** Become the UK's trusted CV verification layer for recruitment, reducing fraud while accelerating hiring processes.

View File

@@ -1,4 +1,4 @@
# TrueCV Deployment Guide # RealCV Deployment Guide
## Quick Start ## Quick Start
@@ -40,7 +40,7 @@ After DNS is configured and app is deployed:
```bash ```bash
ssh user@your-server ssh user@your-server
sudo certbot --nginx -d truecv.yourdomain.com sudo certbot --nginx -d realcv.yourdomain.com
``` ```
## Configuration ## Configuration
@@ -54,7 +54,7 @@ The systemd service sets these environment variables:
To add more (like API keys), edit: To add more (like API keys), edit:
```bash ```bash
sudo systemctl edit truecv sudo systemctl edit realcv
``` ```
Add: Add:
@@ -65,12 +65,12 @@ Environment=OpenAI__ApiKey=your-key-here
### appsettings.Production.json ### appsettings.Production.json
For sensitive settings, create `/var/www/truecv/appsettings.Production.json`: For sensitive settings, create `/var/www/realcv/appsettings.Production.json`:
```json ```json
{ {
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Server=127.0.0.1;Database=TrueCV;User Id=SA;Password=YourPassword;TrustServerCertificate=True" "DefaultConnection": "Server=127.0.0.1;Database=RealCV;User Id=SA;Password=YourPassword;TrustServerCertificate=True"
}, },
"OpenAI": { "OpenAI": {
"ApiKey": "your-openai-key" "ApiKey": "your-openai-key"
@@ -83,41 +83,41 @@ For sensitive settings, create `/var/www/truecv/appsettings.Production.json`:
### View Logs ### View Logs
```bash ```bash
# Application logs # Application logs
sudo journalctl -u truecv -f sudo journalctl -u realcv -f
# Nginx logs # Nginx logs
sudo tail -f /var/log/nginx/access.log sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log sudo tail -f /var/log/nginx/error.log
# SQL Server logs # SQL Server logs
docker logs truecv-sql -f docker logs realcv-sql -f
``` ```
### Restart Services ### Restart Services
```bash ```bash
sudo systemctl restart truecv sudo systemctl restart realcv
sudo systemctl restart nginx sudo systemctl restart nginx
docker restart truecv-sql docker restart realcv-sql
``` ```
### Database Backup ### Database Backup
```bash ```bash
# Backup # Backup
docker exec truecv-sql /opt/mssql-tools18/bin/sqlcmd \ docker exec realcv-sql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P 'YourPassword' -C \ -S localhost -U SA -P 'YourPassword' -C \
-Q "BACKUP DATABASE TrueCV TO DISK='/var/opt/mssql/backup/truecv.bak'" -Q "BACKUP DATABASE RealCV TO DISK='/var/opt/mssql/backup/realcv.bak'"
# Copy backup from container # Copy backup from container
docker cp truecv-sql:/var/opt/mssql/backup/truecv.bak ./truecv-backup.bak docker cp realcv-sql:/var/opt/mssql/backup/realcv.bak ./realcv-backup.bak
``` ```
### Rollback Deployment ### Rollback Deployment
```bash ```bash
# On server - restore previous version # On server - restore previous version
sudo systemctl stop truecv sudo systemctl stop realcv
sudo rm -rf /var/www/truecv sudo rm -rf /var/www/realcv
sudo mv /var/www/truecv.backup.YYYYMMDD_HHMMSS /var/www/truecv sudo mv /var/www/realcv.backup.YYYYMMDD_HHMMSS /var/www/realcv
sudo systemctl start truecv sudo systemctl start realcv
``` ```
## Troubleshooting ## Troubleshooting
@@ -125,23 +125,23 @@ sudo systemctl start truecv
### App won't start ### App won't start
```bash ```bash
# Check status # Check status
sudo systemctl status truecv sudo systemctl status realcv
# Check logs # Check logs
sudo journalctl -u truecv -n 100 sudo journalctl -u realcv -n 100
# Test manually # Test manually
cd /var/www/truecv cd /var/www/realcv
sudo -u www-data dotnet TrueCV.Web.dll sudo -u www-data dotnet RealCV.Web.dll
``` ```
### Database connection issues ### Database connection issues
```bash ```bash
# Check SQL Server is running # Check SQL Server is running
docker ps | grep truecv-sql docker ps | grep realcv-sql
# Test connection # Test connection
docker exec -it truecv-sql /opt/mssql-tools18/bin/sqlcmd \ docker exec -it realcv-sql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P 'YourPassword' -C \ -S localhost -U SA -P 'YourPassword' -C \
-Q "SELECT name FROM sys.databases" -Q "SELECT name FROM sys.databases"
``` ```

View File

@@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# TrueCV Deployment Script # RealCV Deployment Script
# Run this from your development machine to deploy to a Linux server # Run this from your development machine to deploy to a Linux server
set -e set -e
@@ -7,8 +7,8 @@ set -e
# Configuration - UPDATE THESE VALUES # Configuration - UPDATE THESE VALUES
SERVER_USER="deploy" SERVER_USER="deploy"
SERVER_HOST="your-server.com" SERVER_HOST="your-server.com"
SERVER_PATH="/var/www/truecv" SERVER_PATH="/var/www/realcv"
DOMAIN="truecv.yourdomain.com" DOMAIN="realcv.yourdomain.com"
# Colors for output # Colors for output
RED='\033[0;31m' RED='\033[0;31m'
@@ -16,7 +16,7 @@ GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
echo -e "${GREEN}=== TrueCV Deployment Script ===${NC}" echo -e "${GREEN}=== RealCV Deployment Script ===${NC}"
# Check if configuration is set # Check if configuration is set
if [[ "$SERVER_HOST" == "your-server.com" ]]; then if [[ "$SERVER_HOST" == "your-server.com" ]]; then
@@ -27,15 +27,15 @@ fi
# Step 1: Build and publish # Step 1: Build and publish
echo -e "${YELLOW}Step 1: Publishing application...${NC}" echo -e "${YELLOW}Step 1: Publishing application...${NC}"
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
dotnet publish src/TrueCV.Web -c Release -o ./publish --nologo dotnet publish src/RealCV.Web -c Release -o ./publish --nologo
# Step 2: Create deployment package # Step 2: Create deployment package
echo -e "${YELLOW}Step 2: Creating deployment package...${NC}" echo -e "${YELLOW}Step 2: Creating deployment package...${NC}"
tar -czf deploy/truecv-release.tar.gz -C publish . tar -czf deploy/realcv-release.tar.gz -C publish .
# Step 3: Transfer to server # Step 3: Transfer to server
echo -e "${YELLOW}Step 3: Transferring to server...${NC}" echo -e "${YELLOW}Step 3: Transferring to server...${NC}"
scp deploy/truecv-release.tar.gz ${SERVER_USER}@${SERVER_HOST}:/tmp/ scp deploy/realcv-release.tar.gz ${SERVER_USER}@${SERVER_HOST}:/tmp/
# Step 4: Deploy on server # Step 4: Deploy on server
echo -e "${YELLOW}Step 4: Deploying on server...${NC}" echo -e "${YELLOW}Step 4: Deploying on server...${NC}"
@@ -43,23 +43,23 @@ ssh ${SERVER_USER}@${SERVER_HOST} << 'ENDSSH'
set -e set -e
# Stop the service if running # Stop the service if running
sudo systemctl stop truecv 2>/dev/null || true sudo systemctl stop realcv 2>/dev/null || true
# Backup current deployment # Backup current deployment
if [ -d "/var/www/truecv" ]; then if [ -d "/var/www/realcv" ]; then
sudo mv /var/www/truecv /var/www/truecv.backup.$(date +%Y%m%d_%H%M%S) sudo mv /var/www/realcv /var/www/realcv.backup.$(date +%Y%m%d_%H%M%S)
fi fi
# Create directory and extract # Create directory and extract
sudo mkdir -p /var/www/truecv sudo mkdir -p /var/www/realcv
sudo tar -xzf /tmp/truecv-release.tar.gz -C /var/www/truecv sudo tar -xzf /tmp/realcv-release.tar.gz -C /var/www/realcv
sudo chown -R www-data:www-data /var/www/truecv sudo chown -R www-data:www-data /var/www/realcv
# Start the service # Start the service
sudo systemctl start truecv sudo systemctl start realcv
# Clean up # Clean up
rm /tmp/truecv-release.tar.gz rm /tmp/realcv-release.tar.gz
echo "Deployment complete on server" echo "Deployment complete on server"
ENDSSH ENDSSH
@@ -67,14 +67,14 @@ ENDSSH
# Step 5: Verify deployment # Step 5: Verify deployment
echo -e "${YELLOW}Step 5: Verifying deployment...${NC}" echo -e "${YELLOW}Step 5: Verifying deployment...${NC}"
sleep 3 sleep 3
if ssh ${SERVER_USER}@${SERVER_HOST} "sudo systemctl is-active truecv" | grep -q "active"; then if ssh ${SERVER_USER}@${SERVER_HOST} "sudo systemctl is-active realcv" | grep -q "active"; then
echo -e "${GREEN}=== Deployment successful! ===${NC}" echo -e "${GREEN}=== Deployment successful! ===${NC}"
echo -e "Site should be available at: https://${DOMAIN}" echo -e "Site should be available at: https://${DOMAIN}"
else else
echo -e "${RED}Warning: Service may not be running. Check with: sudo systemctl status truecv${NC}" echo -e "${RED}Warning: Service may not be running. Check with: sudo systemctl status realcv${NC}"
fi fi
# Cleanup local files # Cleanup local files
rm -f deploy/truecv-release.tar.gz rm -f deploy/realcv-release.tar.gz
echo -e "${GREEN}Done!${NC}" echo -e "${GREEN}Done!${NC}"

View File

@@ -1,11 +1,11 @@
#!/bin/bash #!/bin/bash
# TrueCV Server Setup Script # RealCV Server Setup Script
# Run this ONCE on a fresh Linux server (Ubuntu 22.04/24.04) # Run this ONCE on a fresh Linux server (Ubuntu 22.04/24.04)
set -e set -e
# Configuration - UPDATE THESE VALUES # Configuration - UPDATE THESE VALUES
DOMAIN="truecv.yourdomain.com" DOMAIN="realcv.yourdomain.com"
DB_PASSWORD="YourStrong!Password123" DB_PASSWORD="YourStrong!Password123"
ADMIN_EMAIL="admin@yourdomain.com" ADMIN_EMAIL="admin@yourdomain.com"
@@ -15,7 +15,7 @@ GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
NC='\033[0m' NC='\033[0m'
echo -e "${GREEN}=== TrueCV Server Setup ===${NC}" echo -e "${GREEN}=== RealCV Server Setup ===${NC}"
# Check if running as root # Check if running as root
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
@@ -52,54 +52,54 @@ echo -e "${YELLOW}Step 5: Setting up SQL Server...${NC}"
docker run -e 'ACCEPT_EULA=Y' \ docker run -e 'ACCEPT_EULA=Y' \
-e "SA_PASSWORD=${DB_PASSWORD}" \ -e "SA_PASSWORD=${DB_PASSWORD}" \
-p 127.0.0.1:1433:1433 \ -p 127.0.0.1:1433:1433 \
--name truecv-sql \ --name realcv-sql \
--restart unless-stopped \ --restart unless-stopped \
-v truecv-sqldata:/var/opt/mssql \ -v realcv-sqldata:/var/opt/mssql \
-d mcr.microsoft.com/mssql/server:2022-latest -d mcr.microsoft.com/mssql/server:2022-latest
echo "Waiting for SQL Server to start..." echo "Waiting for SQL Server to start..."
sleep 30 sleep 30
# Create the database # Create the database
docker exec truecv-sql /opt/mssql-tools18/bin/sqlcmd \ docker exec realcv-sql /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U SA -P "${DB_PASSWORD}" -C \ -S localhost -U SA -P "${DB_PASSWORD}" -C \
-Q "CREATE DATABASE TrueCV" -Q "CREATE DATABASE RealCV"
# Step 6: Create application directory # Step 6: Create application directory
echo -e "${YELLOW}Step 6: Creating application directory...${NC}" echo -e "${YELLOW}Step 6: Creating application directory...${NC}"
mkdir -p /var/www/truecv mkdir -p /var/www/realcv
chown -R www-data:www-data /var/www/truecv chown -R www-data:www-data /var/www/realcv
# Step 7: Create systemd service # Step 7: Create systemd service
echo -e "${YELLOW}Step 7: Creating systemd service...${NC}" echo -e "${YELLOW}Step 7: Creating systemd service...${NC}"
cat > /etc/systemd/system/truecv.service << EOF cat > /etc/systemd/system/realcv.service << EOF
[Unit] [Unit]
Description=TrueCV Web Application Description=RealCV Web Application
After=network.target docker.service After=network.target docker.service
Requires=docker.service Requires=docker.service
[Service] [Service]
WorkingDirectory=/var/www/truecv WorkingDirectory=/var/www/realcv
ExecStart=/usr/bin/dotnet /var/www/truecv/TrueCV.Web.dll ExecStart=/usr/bin/dotnet /var/www/realcv/RealCV.Web.dll
Restart=always Restart=always
RestartSec=10 RestartSec=10
KillSignal=SIGINT KillSignal=SIGINT
SyslogIdentifier=truecv SyslogIdentifier=realcv
User=www-data User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=ASPNETCORE_URLS=http://localhost:5000 Environment=ASPNETCORE_URLS=http://localhost:5000
Environment=ConnectionStrings__DefaultConnection=Server=127.0.0.1;Database=TrueCV;User Id=SA;Password=${DB_PASSWORD};TrustServerCertificate=True Environment=ConnectionStrings__DefaultConnection=Server=127.0.0.1;Database=RealCV;User Id=SA;Password=${DB_PASSWORD};TrustServerCertificate=True
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
systemctl daemon-reload systemctl daemon-reload
systemctl enable truecv systemctl enable realcv
# Step 8: Configure Nginx # Step 8: Configure Nginx
echo -e "${YELLOW}Step 8: Configuring Nginx...${NC}" echo -e "${YELLOW}Step 8: Configuring Nginx...${NC}"
cat > /etc/nginx/sites-available/truecv << EOF cat > /etc/nginx/sites-available/realcv << EOF
server { server {
listen 80; listen 80;
server_name ${DOMAIN}; server_name ${DOMAIN};
@@ -122,7 +122,7 @@ server {
} }
EOF EOF
ln -sf /etc/nginx/sites-available/truecv /etc/nginx/sites-enabled/ ln -sf /etc/nginx/sites-available/realcv /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default rm -f /etc/nginx/sites-enabled/default
nginx -t nginx -t
systemctl reload nginx systemctl reload nginx
@@ -151,9 +151,9 @@ echo "2. Deploy the application using deploy.sh from your dev machine"
echo "3. Run SSL setup: certbot --nginx -d ${DOMAIN}" echo "3. Run SSL setup: certbot --nginx -d ${DOMAIN}"
echo "" echo ""
echo "Useful commands:" echo "Useful commands:"
echo " sudo systemctl status truecv - Check app status" echo " sudo systemctl status realcv - Check app status"
echo " sudo journalctl -u truecv -f - View app logs" echo " sudo journalctl -u realcv -f - View app logs"
echo " docker logs truecv-sql - View SQL Server logs" echo " docker logs realcv-sql - View SQL Server logs"
echo "" echo ""
echo -e "${YELLOW}Database connection string:${NC}" echo -e "${YELLOW}Database connection string:${NC}"
echo " Server=127.0.0.1;Database=TrueCV;User Id=SA;Password=${DB_PASSWORD};TrustServerCertificate=True" echo " Server=127.0.0.1;Database=RealCV;User Id=SA;Password=${DB_PASSWORD};TrustServerCertificate=True"

View File

@@ -1,18 +1,18 @@
version: '3.8' version: '3.8'
services: services:
# TrueCV Web Application # RealCV Web Application
truecv-web: realcv-web:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: truecv-web container_name: realcv-web
ports: ports:
- "5000:8080" - "5000:8080"
environment: environment:
- ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_ENVIRONMENT=Development
- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=TrueCV;User Id=sa;Password=TrueCV_P@ssw0rd!;TrustServerCertificate=True; - ConnectionStrings__DefaultConnection=Server=sqlserver;Database=RealCV;User Id=sa;Password=TrueCV_P@ssw0rd!;TrustServerCertificate=True;
- ConnectionStrings__HangfireConnection=Server=sqlserver;Database=TrueCV_Hangfire;User Id=sa;Password=TrueCV_P@ssw0rd!;TrustServerCertificate=True; - ConnectionStrings__HangfireConnection=Server=sqlserver;Database=RealCV_Hangfire;User Id=sa;Password=TrueCV_P@ssw0rd!;TrustServerCertificate=True;
- AzureBlob__ConnectionString=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1; - AzureBlob__ConnectionString=DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1;
- AzureBlob__ContainerName=cv-uploads - AzureBlob__ContainerName=cv-uploads
- CompaniesHouse__BaseUrl=https://api.company-information.service.gov.uk - CompaniesHouse__BaseUrl=https://api.company-information.service.gov.uk
@@ -24,13 +24,13 @@ services:
azurite: azurite:
condition: service_started condition: service_started
networks: networks:
- truecv-network - realcv-network
restart: unless-stopped restart: unless-stopped
# SQL Server Database # SQL Server Database
sqlserver: sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest image: mcr.microsoft.com/mssql/server:2022-latest
container_name: truecv-sqlserver container_name: realcv-sqlserver
ports: ports:
- "1433:1433" - "1433:1433"
environment: environment:
@@ -40,7 +40,7 @@ services:
volumes: volumes:
- sqlserver-data:/var/opt/mssql - sqlserver-data:/var/opt/mssql
networks: networks:
- truecv-network - realcv-network
healthcheck: healthcheck:
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "TrueCV_P@ssw0rd!" -C -Q "SELECT 1" || exit 1 test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "TrueCV_P@ssw0rd!" -C -Q "SELECT 1" || exit 1
interval: 10s interval: 10s
@@ -52,7 +52,7 @@ services:
# Azure Storage Emulator (Azurite) # Azure Storage Emulator (Azurite)
azurite: azurite:
image: mcr.microsoft.com/azure-storage/azurite:latest image: mcr.microsoft.com/azure-storage/azurite:latest
container_name: truecv-azurite container_name: realcv-azurite
ports: ports:
- "10000:10000" # Blob service - "10000:10000" # Blob service
- "10001:10001" # Queue service - "10001:10001" # Queue service
@@ -61,7 +61,7 @@ services:
- azurite-data:/data - azurite-data:/data
command: "azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --location /data --debug /data/debug.log" command: "azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --location /data --debug /data/debug.log"
networks: networks:
- truecv-network - realcv-network
restart: unless-stopped restart: unless-stopped
# Database initialization (runs migrations) # Database initialization (runs migrations)
@@ -69,18 +69,18 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile.migrations dockerfile: Dockerfile.migrations
container_name: truecv-db-init container_name: realcv-db-init
environment: environment:
- ConnectionStrings__DefaultConnection=Server=sqlserver;Database=TrueCV;User Id=sa;Password=TrueCV_P@ssw0rd!;TrustServerCertificate=True; - ConnectionStrings__DefaultConnection=Server=sqlserver;Database=RealCV;User Id=sa;Password=TrueCV_P@ssw0rd!;TrustServerCertificate=True;
depends_on: depends_on:
sqlserver: sqlserver:
condition: service_healthy condition: service_healthy
networks: networks:
- truecv-network - realcv-network
restart: "no" restart: "no"
networks: networks:
truecv-network: realcv-network:
driver: bridge driver: bridge
volumes: volumes:

BIN
screenshots/homepage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
screenshots/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 KiB

BIN
screenshots/pricing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
screenshots/privacy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

BIN
screenshots/register.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

View File

@@ -1,9 +1,10 @@
namespace TrueCV.Application.DTOs; namespace RealCV.Application.DTOs;
public sealed record CVCheckDto public sealed record CVCheckDto
{ {
public required Guid Id { get; init; } public required Guid Id { get; init; }
public required string OriginalFileName { get; init; } public required string OriginalFileName { get; init; }
public string? CandidateName { get; init; }
public required string Status { get; init; } public required string Status { get; init; }
public int? VeracityScore { get; init; } public int? VeracityScore { get; init; }
public string? ProcessingStage { get; init; } public string? ProcessingStage { get; init; }

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.DTOs; namespace RealCV.Application.DTOs;
public sealed record CompanySearchResult public sealed record CompanySearchResult
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Data; namespace RealCV.Application.Data;
/// <summary> /// <summary>
/// Known diploma mills and fake educational institutions. /// Known diploma mills and fake educational institutions.

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Data; namespace RealCV.Application.Data;
/// <summary> /// <summary>
/// List of recognised UK higher education institutions. /// List of recognised UK higher education institutions.
@@ -43,6 +43,8 @@ public static class UKInstitutions
// Other Major Universities // Other Major Universities
"Aston University", "Aston University",
"Leeds Beckett University",
"Leeds Metropolitan University", // Former name of Leeds Beckett
"University of Bath", "University of Bath",
"Birkbeck, University of London", "Birkbeck, University of London",
"Bournemouth University", "Bournemouth University",
@@ -218,6 +220,9 @@ public static class UKInstitutions
["Queen Mary"] = "Queen Mary University of London", ["Queen Mary"] = "Queen Mary University of London",
["Royal Holloway University"] = "Royal Holloway, University of London", ["Royal Holloway University"] = "Royal Holloway, University of London",
["RHUL"] = "Royal Holloway, University of London", ["RHUL"] = "Royal Holloway, University of London",
["Leeds Beckett"] = "Leeds Beckett University",
["Leeds Met"] = "Leeds Beckett University",
["Leeds Metropolitan"] = "Leeds Beckett University",
}; };
/// <summary> /// <summary>

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Helpers; namespace RealCV.Application.Helpers;
public static class DateHelpers public static class DateHelpers
{ {

View File

@@ -1,6 +1,6 @@
using System.Text.Json; using System.Text.Json;
namespace TrueCV.Application.Helpers; namespace RealCV.Application.Helpers;
public static class JsonDefaults public static class JsonDefaults
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Helpers; namespace RealCV.Application.Helpers;
public static class ScoreThresholds public static class ScoreThresholds
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface IAuditService public interface IAuditService
{ {

View File

@@ -1,7 +1,7 @@
using TrueCV.Application.DTOs; using RealCV.Application.DTOs;
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface ICVCheckService public interface ICVCheckService
{ {

View File

@@ -1,6 +1,6 @@
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface ICVParserService public interface ICVParserService
{ {

View File

@@ -1,6 +1,6 @@
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface ICompanyNameMatcherService public interface ICompanyNameMatcherService
{ {

View File

@@ -1,7 +1,7 @@
using TrueCV.Application.DTOs; using RealCV.Application.DTOs;
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface ICompanyVerifierService public interface ICompanyVerifierService
{ {

View File

@@ -1,6 +1,6 @@
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface IEducationVerifierService public interface IEducationVerifierService
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface IFileStorageService public interface IFileStorageService
{ {

View File

@@ -1,6 +1,6 @@
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface ITimelineAnalyserService public interface ITimelineAnalyserService
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Interfaces; namespace RealCV.Application.Interfaces;
public interface IUserContextService public interface IUserContextService
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record CVData public sealed record CVData
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record CompanyVerificationResult public sealed record CompanyVerificationResult
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record EducationEntry public sealed record EducationEntry
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record EducationVerificationResult public sealed record EducationVerificationResult
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record EmploymentEntry public sealed record EmploymentEntry
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record FlagResult public sealed record FlagResult
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public record SemanticMatchResult public record SemanticMatchResult
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record TimelineAnalysisResult public sealed record TimelineAnalysisResult
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record TimelineGap public sealed record TimelineGap
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record TimelineOverlap public sealed record TimelineOverlap
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Application.Models; namespace RealCV.Application.Models;
public sealed record VeracityReport public sealed record VeracityReport
{ {

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\TrueCV.Domain\TrueCV.Domain.csproj" /> <ProjectReference Include="..\RealCV.Domain\RealCV.Domain.csproj" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>

View File

@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace TrueCV.Domain.Entities; namespace RealCV.Domain.Entities;
public class AuditLog public class AuditLog
{ {

View File

@@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
namespace TrueCV.Domain.Entities; namespace RealCV.Domain.Entities;
public class CVCheck public class CVCheck
{ {

View File

@@ -1,8 +1,8 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
namespace TrueCV.Domain.Entities; namespace RealCV.Domain.Entities;
public class CVFlag public class CVFlag
{ {

View File

@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace TrueCV.Domain.Entities; namespace RealCV.Domain.Entities;
public class CompanyCache public class CompanyCache
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Domain.Enums; namespace RealCV.Domain.Enums;
public enum CheckStatus public enum CheckStatus
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Domain.Enums; namespace RealCV.Domain.Enums;
public enum FlagCategory public enum FlagCategory
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Domain.Enums; namespace RealCV.Domain.Enums;
public enum FlagSeverity public enum FlagSeverity
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Domain.Enums; namespace RealCV.Domain.Enums;
public enum UserPlan public enum UserPlan
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Infrastructure.Configuration; namespace RealCV.Infrastructure.Configuration;
public sealed class AnthropicSettings public sealed class AnthropicSettings
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Infrastructure.Configuration; namespace RealCV.Infrastructure.Configuration;
public sealed class AzureBlobSettings public sealed class AzureBlobSettings
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Infrastructure.Configuration; namespace RealCV.Infrastructure.Configuration;
public sealed class CompaniesHouseSettings public sealed class CompaniesHouseSettings
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Infrastructure.Configuration; namespace RealCV.Infrastructure.Configuration;
public sealed class LocalStorageSettings public sealed class LocalStorageSettings
{ {

View File

@@ -1,10 +1,10 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Infrastructure.Identity; using RealCV.Infrastructure.Identity;
namespace TrueCV.Infrastructure.Data; namespace RealCV.Infrastructure.Data;
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid> public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>
{ {

View File

@@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
[Migration("20260118182916_InitialCreate")] [Migration("20260118182916_InitialCreate")]
@@ -156,7 +156,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("AspNetUserTokens", (string)null); b.ToTable("AspNetUserTokens", (string)null);
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -211,7 +211,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVChecks"); b.ToTable("CVChecks");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -251,7 +251,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVFlags"); b.ToTable("CVFlags");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CompanyCache", b => modelBuilder.Entity("RealCV.Domain.Entities.CompanyCache", b =>
{ {
b.Property<string>("CompanyNumber") b.Property<string>("CompanyNumber")
.HasMaxLength(32) .HasMaxLength(32)
@@ -281,7 +281,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CompanyCache"); b.ToTable("CompanyCache");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.User", b => modelBuilder.Entity("RealCV.Domain.Entities.User", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -307,7 +307,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("User"); b.ToTable("User");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -396,7 +396,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -405,7 +405,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -420,7 +420,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -429,29 +429,29 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany("CVChecks") .WithMany("CVChecks")
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("TrueCV.Domain.Entities.User", null) b.HasOne("RealCV.Domain.Entities.User", null)
.WithMany("CVChecks") .WithMany("CVChecks")
.HasForeignKey("UserId1"); .HasForeignKey("UserId1");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.HasOne("TrueCV.Domain.Entities.CVCheck", "CVCheck") b.HasOne("RealCV.Domain.Entities.CVCheck", "CVCheck")
.WithMany("Flags") .WithMany("Flags")
.HasForeignKey("CVCheckId") .HasForeignKey("CVCheckId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -460,17 +460,17 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.Navigation("CVCheck"); b.Navigation("CVCheck");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Navigation("Flags"); b.Navigation("Flags");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.User", b => modelBuilder.Entity("RealCV.Domain.Entities.User", b =>
{ {
b.Navigation("CVChecks"); b.Navigation("CVChecks");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Navigation("CVChecks"); b.Navigation("CVChecks");
}); });

View File

@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class InitialCreate : Migration public partial class InitialCreate : Migration

View File

@@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
[Migration("20260120191035_AddProcessingStageToCV")] [Migration("20260120191035_AddProcessingStageToCV")]
@@ -156,7 +156,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("AspNetUserTokens", (string)null); b.ToTable("AspNetUserTokens", (string)null);
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -210,7 +210,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVChecks"); b.ToTable("CVChecks");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -250,7 +250,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVFlags"); b.ToTable("CVFlags");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CompanyCache", b => modelBuilder.Entity("RealCV.Domain.Entities.CompanyCache", b =>
{ {
b.Property<string>("CompanyNumber") b.Property<string>("CompanyNumber")
.HasMaxLength(32) .HasMaxLength(32)
@@ -292,7 +292,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CompanyCache"); b.ToTable("CompanyCache");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -381,7 +381,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -390,7 +390,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -405,7 +405,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -414,25 +414,25 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany("CVChecks") .WithMany("CVChecks")
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.HasOne("TrueCV.Domain.Entities.CVCheck", "CVCheck") b.HasOne("RealCV.Domain.Entities.CVCheck", "CVCheck")
.WithMany("Flags") .WithMany("Flags")
.HasForeignKey("CVCheckId") .HasForeignKey("CVCheckId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -441,12 +441,12 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.Navigation("CVCheck"); b.Navigation("CVCheck");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Navigation("Flags"); b.Navigation("Flags");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Navigation("CVChecks"); b.Navigation("CVChecks");
}); });

View File

@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class AddProcessingStageToCV : Migration public partial class AddProcessingStageToCV : Migration

View File

@@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
[Migration("20260120194532_AddAuditLogTable")] [Migration("20260120194532_AddAuditLogTable")]
@@ -156,7 +156,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("AspNetUserTokens", (string)null); b.ToTable("AspNetUserTokens", (string)null);
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.AuditLog", b => modelBuilder.Entity("RealCV.Domain.Entities.AuditLog", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -202,7 +202,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("AuditLogs"); b.ToTable("AuditLogs");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -256,7 +256,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVChecks"); b.ToTable("CVChecks");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -296,7 +296,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVFlags"); b.ToTable("CVFlags");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CompanyCache", b => modelBuilder.Entity("RealCV.Domain.Entities.CompanyCache", b =>
{ {
b.Property<string>("CompanyNumber") b.Property<string>("CompanyNumber")
.HasMaxLength(32) .HasMaxLength(32)
@@ -338,7 +338,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CompanyCache"); b.ToTable("CompanyCache");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -427,7 +427,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -436,7 +436,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -451,7 +451,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -460,25 +460,25 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany("CVChecks") .WithMany("CVChecks")
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.HasOne("TrueCV.Domain.Entities.CVCheck", "CVCheck") b.HasOne("RealCV.Domain.Entities.CVCheck", "CVCheck")
.WithMany("Flags") .WithMany("Flags")
.HasForeignKey("CVCheckId") .HasForeignKey("CVCheckId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -487,12 +487,12 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.Navigation("CVCheck"); b.Navigation("CVCheck");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Navigation("Flags"); b.Navigation("Flags");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Navigation("CVChecks"); b.Navigation("CVChecks");
}); });

View File

@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class AddAuditLogTable : Migration public partial class AddAuditLogTable : Migration

View File

@@ -4,11 +4,11 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
#nullable disable #nullable disable
namespace TrueCV.Infrastructure.Data.Migrations namespace RealCV.Infrastructure.Data.Migrations
{ {
[DbContext(typeof(ApplicationDbContext))] [DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot partial class ApplicationDbContextModelSnapshot : ModelSnapshot
@@ -153,7 +153,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("AspNetUserTokens", (string)null); b.ToTable("AspNetUserTokens", (string)null);
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.AuditLog", b => modelBuilder.Entity("RealCV.Domain.Entities.AuditLog", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -199,7 +199,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("AuditLogs"); b.ToTable("AuditLogs");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -253,7 +253,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVChecks"); b.ToTable("CVChecks");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -293,7 +293,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CVFlags"); b.ToTable("CVFlags");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CompanyCache", b => modelBuilder.Entity("RealCV.Domain.Entities.CompanyCache", b =>
{ {
b.Property<string>("CompanyNumber") b.Property<string>("CompanyNumber")
.HasMaxLength(32) .HasMaxLength(32)
@@ -335,7 +335,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.ToTable("CompanyCache"); b.ToTable("CompanyCache");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
@@ -424,7 +424,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -433,7 +433,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -448,7 +448,7 @@ namespace TrueCV.Infrastructure.Data.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -457,25 +457,25 @@ namespace TrueCV.Infrastructure.Data.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany() .WithMany()
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.HasOne("TrueCV.Infrastructure.Identity.ApplicationUser", null) b.HasOne("RealCV.Infrastructure.Identity.ApplicationUser", null)
.WithMany("CVChecks") .WithMany("CVChecks")
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVFlag", b => modelBuilder.Entity("RealCV.Domain.Entities.CVFlag", b =>
{ {
b.HasOne("TrueCV.Domain.Entities.CVCheck", "CVCheck") b.HasOne("RealCV.Domain.Entities.CVCheck", "CVCheck")
.WithMany("Flags") .WithMany("Flags")
.HasForeignKey("CVCheckId") .HasForeignKey("CVCheckId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
@@ -484,12 +484,12 @@ namespace TrueCV.Infrastructure.Data.Migrations
b.Navigation("CVCheck"); b.Navigation("CVCheck");
}); });
modelBuilder.Entity("TrueCV.Domain.Entities.CVCheck", b => modelBuilder.Entity("RealCV.Domain.Entities.CVCheck", b =>
{ {
b.Navigation("Flags"); b.Navigation("Flags");
}); });
modelBuilder.Entity("TrueCV.Infrastructure.Identity.ApplicationUser", b => modelBuilder.Entity("RealCV.Infrastructure.Identity.ApplicationUser", b =>
{ {
b.Navigation("CVChecks"); b.Navigation("CVChecks");
}); });

View File

@@ -5,14 +5,14 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Polly; using Polly;
using Polly.Extensions.Http; using Polly.Extensions.Http;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
using TrueCV.Infrastructure.ExternalApis; using RealCV.Infrastructure.ExternalApis;
using TrueCV.Infrastructure.Jobs; using RealCV.Infrastructure.Jobs;
using TrueCV.Infrastructure.Services; using RealCV.Infrastructure.Services;
namespace TrueCV.Infrastructure; namespace RealCV.Infrastructure;
public static class DependencyInjection public static class DependencyInjection
{ {

View File

@@ -6,10 +6,10 @@ using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using TrueCV.Application.DTOs; using RealCV.Application.DTOs;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
namespace TrueCV.Infrastructure.ExternalApis; namespace RealCV.Infrastructure.ExternalApis;
public sealed class CompaniesHouseClient public sealed class CompaniesHouseClient
{ {

View File

@@ -1,4 +1,4 @@
namespace TrueCV.Infrastructure.Helpers; namespace RealCV.Infrastructure.Helpers;
/// <summary> /// <summary>
/// Helper methods for processing AI/LLM JSON responses. /// Helper methods for processing AI/LLM JSON responses.

View File

@@ -1,8 +1,8 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
namespace TrueCV.Infrastructure.Identity; namespace RealCV.Infrastructure.Identity;
public class ApplicationUser : IdentityUser<Guid> public class ApplicationUser : IdentityUser<Guid>
{ {

View File

@@ -1,14 +1,14 @@
using System.Text.Json; using System.Text.Json;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.Helpers; using RealCV.Application.Helpers;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
namespace TrueCV.Infrastructure.Jobs; namespace RealCV.Infrastructure.Jobs;
public sealed class ProcessCVCheckJob public sealed class ProcessCVCheckJob
{ {

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\TrueCV.Application\TrueCV.Application.csproj" /> <ProjectReference Include="..\RealCV.Application\RealCV.Application.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,13 +3,13 @@ using Anthropic.SDK;
using Anthropic.SDK.Messaging; using Anthropic.SDK.Messaging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using TrueCV.Application.Helpers; using RealCV.Application.Helpers;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
using TrueCV.Infrastructure.Helpers; using RealCV.Infrastructure.Helpers;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class AICompanyNameMatcherService : ICompanyNameMatcherService public sealed class AICompanyNameMatcherService : ICompanyNameMatcherService
{ {

View File

@@ -1,9 +1,9 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class AuditService : IAuditService public sealed class AuditService : IAuditService
{ {

View File

@@ -2,16 +2,16 @@ using System.Text.Json;
using Hangfire; using Hangfire;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.DTOs; using RealCV.Application.DTOs;
using TrueCV.Application.Helpers; using RealCV.Application.Helpers;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Domain.Enums; using RealCV.Domain.Enums;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
using TrueCV.Infrastructure.Jobs; using RealCV.Infrastructure.Jobs;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class CVCheckService : ICVCheckService public sealed class CVCheckService : ICVCheckService
{ {
@@ -184,10 +184,38 @@ public sealed class CVCheckService : ICVCheckService
private static CVCheckDto MapToDto(CVCheck cvCheck) private static CVCheckDto MapToDto(CVCheck cvCheck)
{ {
string? candidateName = null;
// Try to get candidate name from ReportJson first (completed checks)
if (!string.IsNullOrEmpty(cvCheck.ReportJson))
{
try
{
var report = JsonSerializer.Deserialize<VeracityReport>(cvCheck.ReportJson, JsonDefaults.CamelCase);
candidateName = report?.CandidateName;
}
catch { /* Ignore deserialization errors */ }
}
// Fallback to ExtractedDataJson if no name in report
if (string.IsNullOrEmpty(candidateName) && !string.IsNullOrEmpty(cvCheck.ExtractedDataJson))
{
try
{
using var doc = JsonDocument.Parse(cvCheck.ExtractedDataJson);
if (doc.RootElement.TryGetProperty("fullName", out var nameElement))
{
candidateName = nameElement.GetString();
}
}
catch { /* Ignore deserialization errors */ }
}
return new CVCheckDto return new CVCheckDto
{ {
Id = cvCheck.Id, Id = cvCheck.Id,
OriginalFileName = cvCheck.OriginalFileName, OriginalFileName = cvCheck.OriginalFileName,
CandidateName = candidateName,
Status = cvCheck.Status.ToString(), Status = cvCheck.Status.ToString(),
VeracityScore = cvCheck.VeracityScore, VeracityScore = cvCheck.VeracityScore,
ProcessingStage = cvCheck.ProcessingStage, ProcessingStage = cvCheck.ProcessingStage,

View File

@@ -1,19 +1,20 @@
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
using Anthropic.SDK; using Anthropic.SDK;
using Anthropic.SDK.Messaging; using Anthropic.SDK.Messaging;
using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing; using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using TrueCV.Application.Helpers; using RealCV.Application.Helpers;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
using TrueCV.Infrastructure.Helpers; using RealCV.Infrastructure.Helpers;
using UglyToad.PdfPig; using UglyToad.PdfPig;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class CVParserService : ICVParserService public sealed class CVParserService : ICVParserService
{ {
@@ -83,6 +84,20 @@ public sealed class CVParserService : ICVParserService
_logger.LogDebug("Parsing CV file: {FileName}", fileName); _logger.LogDebug("Parsing CV file: {FileName}", fileName);
var extension = Path.GetExtension(fileName).ToLowerInvariant();
// Handle JSON files directly (debug/test format)
if (extension == ".json")
{
var cvData = await ParseJsonFileAsync(fileStream, cancellationToken);
_logger.LogInformation(
"Successfully loaded JSON CV for {FullName} with {EmploymentCount} employment entries and {EducationCount} education entries",
cvData.FullName,
cvData.Employment.Count,
cvData.Education.Count);
return cvData;
}
var text = await ExtractTextAsync(fileStream, fileName, cancellationToken); var text = await ExtractTextAsync(fileStream, fileName, cancellationToken);
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
@@ -93,15 +108,15 @@ public sealed class CVParserService : ICVParserService
_logger.LogDebug("Extracted {CharCount} characters from {FileName}", text.Length, fileName); _logger.LogDebug("Extracted {CharCount} characters from {FileName}", text.Length, fileName);
var cvData = await ParseWithClaudeAsync(text, cancellationToken); var cvDataFromAI = await ParseWithClaudeAsync(text, cancellationToken);
_logger.LogInformation( _logger.LogInformation(
"Successfully parsed CV for {FullName} with {EmploymentCount} employment entries and {EducationCount} education entries", "Successfully parsed CV for {FullName} with {EmploymentCount} employment entries and {EducationCount} education entries",
cvData.FullName, cvDataFromAI.FullName,
cvData.Employment.Count, cvDataFromAI.Employment.Count,
cvData.Education.Count); cvDataFromAI.Education.Count);
return cvData; return cvDataFromAI;
} }
private async Task<string> ExtractTextAsync(Stream fileStream, string fileName, CancellationToken cancellationToken) private async Task<string> ExtractTextAsync(Stream fileStream, string fileName, CancellationToken cancellationToken)
@@ -116,6 +131,60 @@ public sealed class CVParserService : ICVParserService
}; };
} }
private async Task<CVData> ParseJsonFileAsync(Stream fileStream, CancellationToken cancellationToken)
{
var testCv = await JsonSerializer.DeserializeAsync<TestCVData>(fileStream, TestJsonOptions, cancellationToken)
?? throw new InvalidOperationException("Failed to deserialize JSON CV file");
return new CVData
{
FullName = testCv.Personal?.Name ?? "Unknown",
Email = testCv.Personal?.Email,
Phone = testCv.Personal?.Phone,
Employment = testCv.Employment?.Select(e => new EmploymentEntry
{
CompanyName = e.Company ?? "Unknown",
JobTitle = e.JobTitle ?? "Unknown",
Location = e.Location,
StartDate = ParseTestDate(e.StartDate),
EndDate = ParseTestDate(e.EndDate),
IsCurrent = e.EndDate == null,
Description = e.Description
}).ToList() ?? [],
Education = testCv.Education?.Select(e => new EducationEntry
{
Institution = e.Institution ?? "Unknown",
Qualification = e.Qualification,
Subject = e.Subject,
StartDate = ParseTestDate(e.StartDate),
EndDate = ParseTestDate(e.EndDate)
}).ToList() ?? [],
Skills = testCv.Skills ?? []
};
}
private static DateOnly? ParseTestDate(string? dateStr)
{
if (string.IsNullOrEmpty(dateStr)) return null;
// Try parsing YYYY-MM format
if (dateStr.Length == 7 && dateStr[4] == '-')
{
if (int.TryParse(dateStr[..4], out var year) && int.TryParse(dateStr[5..], out var month))
{
return new DateOnly(year, month, 1);
}
}
// Try standard parsing
if (DateOnly.TryParse(dateStr, out var date))
{
return date;
}
return null;
}
private async Task<string> ExtractTextFromPdfAsync(Stream fileStream, CancellationToken cancellationToken) private async Task<string> ExtractTextFromPdfAsync(Stream fileStream, CancellationToken cancellationToken)
{ {
// Copy stream to memory for PdfPig (requires seekable stream) // Copy stream to memory for PdfPig (requires seekable stream)
@@ -244,6 +313,57 @@ public sealed class CVParserService : ICVParserService
}; };
} }
// JSON options for test/debug CV format (snake_case)
private static readonly JsonSerializerOptions TestJsonOptions = new()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
Converters = { new JsonStringEnumConverter() }
};
// DTOs for test JSON format (snake_case with nested personal object)
private sealed record TestCVData
{
public string? CvId { get; init; }
public string? Category { get; init; }
public List<string>? ExpectedFlags { get; init; }
public TestPersonalData? Personal { get; init; }
public string? Profile { get; init; }
public List<TestEmploymentEntry>? Employment { get; init; }
public List<TestEducationEntry>? Education { get; init; }
public List<string>? Skills { get; init; }
}
private sealed record TestPersonalData
{
public string? Name { get; init; }
public string? Email { get; init; }
public string? Phone { get; init; }
public string? Address { get; init; }
public string? LinkedIn { get; init; }
}
private sealed record TestEmploymentEntry
{
public string? Company { get; init; }
public string? JobTitle { get; init; }
public string? StartDate { get; init; }
public string? EndDate { get; init; }
public string? Location { get; init; }
public string? Description { get; init; }
public List<string>? Achievements { get; init; }
}
private sealed record TestEducationEntry
{
public string? Institution { get; init; }
public string? Qualification { get; init; }
public string? Subject { get; init; }
public string? Classification { get; init; }
public string? StartDate { get; init; }
public string? EndDate { get; init; }
}
// Internal DTOs for Claude response parsing // Internal DTOs for Claude response parsing
private sealed record ClaudeCVResponse private sealed record ClaudeCVResponse
{ {

View File

@@ -2,15 +2,15 @@ using System.Text.Json;
using FuzzySharp; using FuzzySharp;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.DTOs; using RealCV.Application.DTOs;
using TrueCV.Application.Helpers; using RealCV.Application.Helpers;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
using TrueCV.Domain.Entities; using RealCV.Domain.Entities;
using TrueCV.Infrastructure.Data; using RealCV.Infrastructure.Data;
using TrueCV.Infrastructure.ExternalApis; using RealCV.Infrastructure.ExternalApis;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class CompanyVerifierService : ICompanyVerifierService public sealed class CompanyVerifierService : ICompanyVerifierService
{ {
@@ -72,6 +72,154 @@ public sealed class CompanyVerifierService : ICompanyVerifierService
"manufacturing", "operations", "trading" "manufacturing", "operations", "trading"
}; };
// Mapping of common trading names to their official Companies House registered names.
// Many major UK companies trade under a different name than their registered name.
private static readonly Dictionary<string, string[]> TradingNameAliases = new(StringComparer.OrdinalIgnoreCase)
{
// Retail
["Boots"] = new[] { "BOOTS UK LIMITED", "THE BOOTS COMPANY PLC", "BOOTS OPTICIANS" },
["Sainsbury's"] = new[] { "J SAINSBURY PLC", "SAINSBURY'S SUPERMARKETS LTD" },
["Marks & Spencer"] = new[] { "MARKS AND SPENCER GROUP PLC", "MARKS AND SPENCER PLC" },
["M&S"] = new[] { "MARKS AND SPENCER GROUP PLC", "MARKS AND SPENCER PLC" },
["John Lewis"] = new[] { "JOHN LEWIS PLC", "JOHN LEWIS PARTNERSHIP PLC" },
["John Lewis Partnership"] = new[] { "JOHN LEWIS PARTNERSHIP PLC", "JOHN LEWIS PLC" },
["Waitrose"] = new[] { "WAITROSE LIMITED", "JOHN LEWIS PARTNERSHIP PLC" },
["Tesco"] = new[] { "TESCO PLC", "TESCO STORES LIMITED" },
["Asda"] = new[] { "ASDA STORES LIMITED", "ASDA GROUP LIMITED" },
["Morrisons"] = new[] { "WM MORRISON SUPERMARKETS LIMITED" },
["Lidl"] = new[] { "LIDL GREAT BRITAIN LIMITED" },
["Aldi"] = new[] { "ALDI STORES LIMITED" },
// Banking & Finance
["Lloyds Banking Group"] = new[] { "LLOYDS BANKING GROUP PLC", "LLOYDS BANK PLC" },
["Lloyds Bank"] = new[] { "LLOYDS BANK PLC", "LLOYDS BANKING GROUP PLC" },
["HSBC"] = new[] { "HSBC HOLDINGS PLC", "HSBC UK BANK PLC", "HSBC BANK PLC" },
["HSBC Holdings PLC"] = new[] { "HSBC HOLDINGS PLC", "HSBC UK BANK PLC" },
["HSBC UK"] = new[] { "HSBC UK BANK PLC", "HSBC HOLDINGS PLC" },
["Barclays"] = new[] { "BARCLAYS PLC", "BARCLAYS BANK PLC" },
["NatWest"] = new[] { "NATWEST GROUP PLC", "NATIONAL WESTMINSTER BANK PLC" },
["NatWest Group"] = new[] { "NATWEST GROUP PLC", "NATIONAL WESTMINSTER BANK PLC" },
["Santander UK"] = new[] { "SANTANDER UK PLC" },
["Nationwide"] = new[] { "NATIONWIDE BUILDING SOCIETY" },
// Media & Broadcasting
["BBC"] = new[] { "BRITISH BROADCASTING CORPORATION" },
["ITV"] = new[] { "ITV PLC" },
["Sky"] = new[] { "SKY LIMITED", "SKY UK LIMITED" },
["Channel 4"] = new[] { "CHANNEL FOUR TELEVISION CORPORATION" },
// Technology
["IBM UK"] = new[] { "IBM UNITED KINGDOM LIMITED", "INTERNATIONAL BUSINESS MACHINES" },
["IBM"] = new[] { "IBM UNITED KINGDOM LIMITED", "INTERNATIONAL BUSINESS MACHINES" },
["Google UK"] = new[] { "GOOGLE UK LIMITED", "GOOGLE LLC" },
["Google"] = new[] { "GOOGLE UK LIMITED" },
["Microsoft UK"] = new[] { "MICROSOFT LIMITED" },
["Amazon UK"] = new[] { "AMAZON UK SERVICES LTD", "AMAZON.CO.UK LTD" },
["Apple UK"] = new[] { "APPLE (UK) LIMITED", "APPLE RETAIL UK LIMITED" },
// Consulting & Professional Services
["Accenture UK"] = new[] { "ACCENTURE (UK) LIMITED", "ACCENTURE PLC" },
["Accenture"] = new[] { "ACCENTURE (UK) LIMITED", "ACCENTURE PLC" },
["EY UK"] = new[] { "ERNST & YOUNG LLP", "EY LLP" },
["EY"] = new[] { "ERNST & YOUNG LLP", "EY LLP" },
["Ernst & Young"] = new[] { "ERNST & YOUNG LLP" },
["Deloitte UK"] = new[] { "DELOITTE LLP" },
["Deloitte"] = new[] { "DELOITTE LLP" },
["KPMG UK"] = new[] { "KPMG LLP" },
["KPMG"] = new[] { "KPMG LLP" },
["PwC UK"] = new[] { "PRICEWATERHOUSECOOPERS LLP", "PWC (UK) LIMITED" },
["PwC"] = new[] { "PRICEWATERHOUSECOOPERS LLP", "PWC (UK) LIMITED" },
["McKinsey"] = new[] { "MCKINSEY & COMPANY, INC. UNITED KINGDOM" },
["BCG"] = new[] { "THE BOSTON CONSULTING GROUP UK LLP" },
["Bain"] = new[] { "BAIN & COMPANY UK LIMITED" },
// Advertising & Media
["WPP"] = new[] { "WPP 2005 LIMITED", "WPP GROUP", "WIRE & PLASTIC PRODUCTS" },
// Fintech
["Checkout.com"] = new[] { "CHECKOUT.COM LIMITED", "CHECKOUT LTD" },
["Revolut"] = new[] { "REVOLUT LTD", "REVOLUT LIMITED" },
["Monzo"] = new[] { "MONZO BANK LIMITED" },
["Starling Bank"] = new[] { "STARLING BANK LIMITED" },
["Deliveroo"] = new[] { "ROOFOODS LTD", "DELIVEROO HOLDINGS PLC" },
// Travel & Hospitality
["Thomas Cook"] = new[] { "THOMAS COOK GROUP PLC", "THOMAS COOK UK LIMITED" },
["TUI"] = new[] { "TUI UK LIMITED" },
["British Airways"] = new[] { "BRITISH AIRWAYS PLC" },
["EasyJet"] = new[] { "EASYJET PLC", "EASYJET AIRLINE COMPANY LIMITED" },
["Ryanair"] = new[] { "RYANAIR UK LIMITED" },
["Jamie's Italian"] = new[] { "JAMIE'S ITALIAN LIMITED", "JAMIE OLIVER HOLDINGS LIMITED" },
// Retail (Other)
["Toys R Us"] = new[] { "TOYS R US LIMITED", "TOYS \"R\" US LIMITED" },
["Toys R Us UK"] = new[] { "TOYS R US LIMITED" },
["Debenhams"] = new[] { "DEBENHAMS PLC", "DEBENHAMS RETAIL LIMITED" },
["House of Fraser"] = new[] { "HOUSE OF FRASER LIMITED" },
["Next"] = new[] { "NEXT PLC", "NEXT RETAIL LIMITED" },
["Primark"] = new[] { "PRIMARK STORES LIMITED" },
["Sports Direct"] = new[] { "SPORTS DIRECT INTERNATIONAL PLC" },
// Telecoms
["BT"] = new[] { "BT GROUP PLC", "BRITISH TELECOMMUNICATIONS PLC" },
["BT Group"] = new[] { "BT GROUP PLC" },
["Vodafone"] = new[] { "VODAFONE LIMITED", "VODAFONE GROUP PLC" },
["O2"] = new[] { "TELEFONICA UK LIMITED" },
["EE"] = new[] { "EE LIMITED" },
["Three"] = new[] { "HUTCHISON 3G UK LIMITED" },
["Virgin Media"] = new[] { "VIRGIN MEDIA LIMITED" },
// Energy
["BP"] = new[] { "BP P.L.C.", "BP PLC" },
["Shell UK"] = new[] { "SHELL U.K. LIMITED", "SHELL PLC" },
["Shell"] = new[] { "SHELL PLC", "SHELL U.K. LIMITED" },
["British Gas"] = new[] { "BRITISH GAS SERVICES LIMITED", "CENTRICA PLC" },
["Centrica"] = new[] { "CENTRICA PLC" },
["SSE"] = new[] { "SSE PLC" },
["National Grid"] = new[] { "NATIONAL GRID PLC" },
// Automotive
["Jaguar Land Rover"] = new[] { "JAGUAR LAND ROVER LIMITED" },
["JLR"] = new[] { "JAGUAR LAND ROVER LIMITED" },
["Rolls-Royce"] = new[] { "ROLLS-ROYCE PLC", "ROLLS-ROYCE HOLDINGS PLC" },
["BMW UK"] = new[] { "BMW (UK) LIMITED", "BMW GROUP UK LIMITED" },
["JCB"] = new[] { "J.C. BAMFORD EXCAVATORS LIMITED", "J. C. BAMFORD LIMITED" },
// Food & Beverage
["Unilever"] = new[] { "UNILEVER PLC" },
["Nestle UK"] = new[] { "NESTLE UK LTD" },
["Coca-Cola UK"] = new[] { "COCA-COLA EUROPACIFIC PARTNERS PLC" },
["PepsiCo UK"] = new[] { "PEPSICO UK LIMITED" },
// Pharmaceutical & Healthcare
["GlaxoSmithKline"] = new[] { "GLAXOSMITHKLINE PLC", "GSK PLC" },
["GSK"] = new[] { "GSK PLC", "GLAXOSMITHKLINE PLC" },
["AstraZeneca"] = new[] { "ASTRAZENECA PLC" },
["Pfizer UK"] = new[] { "PFIZER LIMITED" },
// Defence & Aerospace
["BAE Systems"] = new[] { "BAE SYSTEMS PLC" },
["BAE"] = new[] { "BAE SYSTEMS PLC" },
// Insurance
["Aviva"] = new[] { "AVIVA PLC" },
["Legal & General"] = new[] { "LEGAL & GENERAL GROUP PLC", "LEGAL AND GENERAL" },
["Prudential"] = new[] { "PRUDENTIAL PLC", "PRUDENTIAL PUBLIC LIMITED COMPANY" },
["Admiral"] = new[] { "ADMIRAL GROUP PLC" },
// Construction & Engineering
["Balfour Beatty"] = new[] { "BALFOUR BEATTY PLC" },
["Carillion"] = new[] { "CARILLION PLC" },
["Kier"] = new[] { "KIER GROUP PLC" },
["Taylor Wimpey"] = new[] { "TAYLOR WIMPEY PLC" },
["Persimmon"] = new[] { "PERSIMMON PLC" },
// Outsourcing & Services
["Serco"] = new[] { "SERCO GROUP PLC" },
["Capita"] = new[] { "CAPITA PLC" },
["G4S"] = new[] { "G4S PLC", "G4S LIMITED" },
};
public CompanyVerifierService( public CompanyVerifierService(
CompaniesHouseClient companiesHouseClient, CompaniesHouseClient companiesHouseClient,
@@ -162,6 +310,61 @@ public sealed class CompanyVerifierService : ICompanyVerifierService
"Company name could not be verified against official records"); "Company name could not be verified against official records");
} }
// Check for direct alias match first - if we searched for a known alias and found it exactly, accept it
// This handles cases where AI might reject valid matches (e.g., "WPP 2005 LIMITED" for "WPP")
var directAliasMatch = FindDirectAliasMatch(companyName, allCandidates.Values.ToList(), startDate);
if (directAliasMatch is not null)
{
_logger.LogInformation(
"Direct alias match for '{ClaimedName}' to '{MatchedName}' (known trading name alias)",
companyName, directAliasMatch.Value.Item.Title);
var aliasDetails = await _companiesHouseClient.GetCompanyAsync(directAliasMatch.Value.Item.CompanyNumber);
await CacheCompanyAsync(directAliasMatch.Value.Item, aliasDetails);
var aliasIncDate = DateHelpers.ParseDate(directAliasMatch.Value.Item.DateOfCreation);
var aliasDissDate = DateHelpers.ParseDate(directAliasMatch.Value.Item.DateOfCessation);
CheckIncorporationDate(flags, startDate, aliasIncDate, directAliasMatch.Value.Item.Title);
CheckDissolutionDate(flags, endDate, aliasDissDate, directAliasMatch.Value.Item.CompanyStatus, directAliasMatch.Value.Item.Title);
CheckDormantCompany(flags, aliasDetails?.Accounts?.LastAccounts?.Type, jobTitle, directAliasMatch.Value.Item.Title);
CheckCompanySizeVsRole(flags, aliasDetails?.Accounts?.LastAccounts?.Type, jobTitle, directAliasMatch.Value.Item.Title);
var (aliasJobPlausible, aliasJobNotes) = CheckJobTitlePlausibility(jobTitle, directAliasMatch.Value.Item.CompanyType);
if (aliasJobPlausible == false)
{
flags.Add(new CompanyVerificationFlag
{
Type = "ImplausibleJobTitle",
Severity = "Critical",
Message = aliasJobNotes ?? "Job title requires verification",
ScoreImpact = -15
});
}
return new CompanyVerificationResult
{
ClaimedCompany = companyName,
MatchedCompanyName = directAliasMatch.Value.Item.Title,
MatchedCompanyNumber = directAliasMatch.Value.Item.CompanyNumber,
MatchScore = directAliasMatch.Value.Score,
IsVerified = true,
VerificationNotes = "Matched via known trading name alias",
ClaimedStartDate = startDate,
ClaimedEndDate = endDate,
CompanyType = directAliasMatch.Value.Item.CompanyType,
CompanyStatus = directAliasMatch.Value.Item.CompanyStatus,
IncorporationDate = aliasIncDate,
DissolutionDate = aliasDissDate,
AccountsCategory = aliasDetails?.Accounts?.LastAccounts?.Type,
SicCodes = aliasDetails?.SicCodes ?? directAliasMatch.Value.Item.SicCodes,
ClaimedJobTitle = jobTitle,
JobTitlePlausible = aliasJobPlausible,
JobTitleNotes = aliasJobNotes,
Flags = flags
};
}
// Use AI to find the best semantic match from all candidates // Use AI to find the best semantic match from all candidates
_logger.LogDebug("Using AI to match '{CompanyName}' against {Count} candidates", companyName, allCandidates.Count); _logger.LogDebug("Using AI to match '{CompanyName}' against {Count} candidates", companyName, allCandidates.Count);
@@ -624,6 +827,72 @@ public sealed class CompanyVerifierService : ICompanyVerifierService
#region Helper Methods #region Helper Methods
/// <summary>
/// Checks if any candidate directly matches a known trading name alias.
/// This allows bypassing AI matching for known aliases where the AI might incorrectly reject.
/// Prefers active companies over dissolved ones when multiple matches exist.
/// </summary>
private static (CompaniesHouseSearchItem Item, int Score)? FindDirectAliasMatch(
string companyName,
List<CompaniesHouseSearchItem> candidates,
DateOnly? claimedStartDate)
{
var normalized = companyName.Trim();
// Check if this company name has known aliases
if (!TradingNameAliases.TryGetValue(normalized, out var aliases))
{
return null;
}
// Collect all matching candidates, then pick the best one
var matchingCandidates = new List<(CompaniesHouseSearchItem Item, int AliasIndex)>();
for (var aliasIndex = 0; aliasIndex < aliases.Length; aliasIndex++)
{
var alias = aliases[aliasIndex];
var aliasUpper = alias.ToUpperInvariant();
foreach (var candidate in candidates)
{
if (string.IsNullOrWhiteSpace(candidate.Title))
continue;
var titleUpper = candidate.Title.ToUpperInvariant();
// Check for exact match or very close match (fuzzy score >= 95)
var fuzzyScore = Fuzz.Ratio(aliasUpper, titleUpper);
if (fuzzyScore >= 95)
{
matchingCandidates.Add((candidate, aliasIndex));
}
}
}
if (matchingCandidates.Count == 0)
return null;
// Sort candidates: prefer active > dissolved, then by alias order (first alias is preferred)
var bestMatch = matchingCandidates
.OrderBy(m => m.Item.CompanyStatus?.ToLowerInvariant() == "active" ? 0 : 1) // Active first
.ThenBy(m => m.Item.CompanyStatus?.ToLowerInvariant() == "dissolved" ? 1 : 0) // Dissolved last
.ThenBy(m => m.AliasIndex) // First alias is preferred
.First();
// Verify the company existed at the claimed start date
if (claimedStartDate.HasValue)
{
var incDate = DateHelpers.ParseDate(bestMatch.Item.DateOfCreation);
if (incDate.HasValue && incDate.Value > claimedStartDate.Value)
{
// Company didn't exist yet - but still return it so the flag can be raised
// Don't skip, let the verification process handle the date issue
}
}
return (bestMatch.Item, 100); // 100% match via known alias
}
private async Task<CompanyCache?> FindCachedMatchAsync(string companyName) private async Task<CompanyCache?> FindCachedMatchAsync(string companyName)
{ {
var cutoffDate = DateTime.UtcNow.AddDays(-CacheExpirationDays); var cutoffDate = DateTime.UtcNow.AddDays(-CacheExpirationDays);
@@ -964,12 +1233,37 @@ public sealed class CompanyVerifierService : ICompanyVerifierService
/// Generates alternative search queries to find companies that may be registered /// Generates alternative search queries to find companies that may be registered
/// with slightly different names (e.g., "U.K." vs "UK", "Limited" vs "Ltd"). /// with slightly different names (e.g., "U.K." vs "UK", "Limited" vs "Ltd").
/// Also handles "Brand (Parent Company)" format by extracting and prioritizing the parent. /// Also handles "Brand (Parent Company)" format by extracting and prioritizing the parent.
/// Uses TradingNameAliases to map common trading names to registered names.
/// </summary> /// </summary>
private static List<string> GenerateSearchQueries(string companyName) private static List<string> GenerateSearchQueries(string companyName)
{ {
var queries = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var queries = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var normalized = companyName.Trim(); var normalized = companyName.Trim();
// Step 0: Check if this is a known trading name and add alias queries FIRST (highest priority)
if (TradingNameAliases.TryGetValue(normalized, out var aliases))
{
foreach (var alias in aliases)
{
queries.Add(alias);
}
}
// Also check partial matches for trading names (e.g., "Boots UK" should match "Boots")
foreach (var (tradingName, aliasNames) in TradingNameAliases)
{
// Check if the company name starts with or contains the trading name
if (normalized.StartsWith(tradingName, StringComparison.OrdinalIgnoreCase) ||
normalized.EndsWith(tradingName, StringComparison.OrdinalIgnoreCase))
{
foreach (var alias in aliasNames)
{
queries.Add(alias);
}
break; // Only use first matching alias set
}
}
// Step 0a: Check for "Brand (Parent Company)" format and extract parent company // Step 0a: Check for "Brand (Parent Company)" format and extract parent company
// Parent company is more likely to be the registered name, so search it first // Parent company is more likely to be the registered name, so search it first
var parentMatch = System.Text.RegularExpressions.Regex.Match(normalized, @"\(([^)]+)\)\s*$"); var parentMatch = System.Text.RegularExpressions.Regex.Match(normalized, @"\(([^)]+)\)\s*$");

View File

@@ -1,8 +1,8 @@
using TrueCV.Application.Data; using RealCV.Application.Data;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class EducationVerifierService : IEducationVerifierService public sealed class EducationVerifierService : IEducationVerifierService
{ {

View File

@@ -2,10 +2,10 @@ using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models; using Azure.Storage.Blobs.Models;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class FileStorageService : IFileStorageService public sealed class FileStorageService : IFileStorageService
{ {

View File

@@ -1,9 +1,9 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Infrastructure.Configuration; using RealCV.Infrastructure.Configuration;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class LocalFileStorageService : IFileStorageService public sealed class LocalFileStorageService : IFileStorageService
{ {

View File

@@ -1,8 +1,8 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
using TrueCV.Application.Models; using RealCV.Application.Models;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class TimelineAnalyserService : ITimelineAnalyserService public sealed class TimelineAnalyserService : ITimelineAnalyserService
{ {

View File

@@ -1,8 +1,8 @@
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
using TrueCV.Application.Interfaces; using RealCV.Application.Interfaces;
namespace TrueCV.Infrastructure.Services; namespace RealCV.Infrastructure.Services;
public sealed class UserContextService : IUserContextService public sealed class UserContextService : IUserContextService
{ {

View File

@@ -7,7 +7,7 @@
<base href="/" /> <base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" /> <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" /> <link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="TrueCV.Web.styles.css" /> <link rel="stylesheet" href="RealCV.Web.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="InteractiveServer" /> <HeadOutlet @rendermode="InteractiveServer" />
</head> </head>

View File

@@ -1,10 +1,10 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<div class="d-flex flex-column min-vh-100"> <div class="d-flex flex-column min-vh-100">
<nav class="navbar navbar-expand-lg navbar-light shadow-sm" style="background-color: var(--truecv-bg-surface);"> <nav class="navbar navbar-expand-lg navbar-light shadow-sm" style="background-color: var(--realcv-bg-surface);">
<div class="container"> <div class="container">
<a class="navbar-brand fw-bold" href="/"> <a class="navbar-brand fw-bold" href="/">
<img src="images/TrueCV_Logo.png" alt="TrueCV" style="height: 95px;" /> <img src="images/RealCV_Logo.png" alt="RealCV" style="height: 95px;" />
</a> </a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
@@ -13,11 +13,6 @@
<div class="collapse navbar-collapse" id="navbarNav"> <div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto"> <ul class="navbar-nav me-auto">
<li class="nav-item">
<NavLink class="nav-link" href="/" Match="NavLinkMatch.All">
Home
</NavLink>
</li>
<AuthorizeView> <AuthorizeView>
<Authorized> <Authorized>
<li class="nav-item"> <li class="nav-item">
@@ -77,9 +72,9 @@
@Body @Body
</main> </main>
<footer class="text-light py-4 mt-auto" style="background-color: var(--truecv-footer-bg);"> <footer class="text-light py-4 mt-auto" style="background-color: var(--realcv-footer-bg);">
<div class="container text-center"> <div class="container text-center">
<p class="mb-0">&copy; @DateTime.Now.Year TrueCV. All rights reserved.</p> <p class="mb-0">&copy; @DateTime.Now.Year RealCV. All rights reserved.</p>
</div> </div>
</footer> </footer>
</div> </div>

View File

@@ -1,14 +1,14 @@
@page "/account/login" @page "/account/login"
@using TrueCV.Web.Components.Layout @using RealCV.Web.Components.Layout
@layout MainLayout @layout MainLayout
@using Microsoft.AspNetCore.Identity @using Microsoft.AspNetCore.Identity
@using TrueCV.Infrastructure.Identity @using RealCV.Infrastructure.Identity
@inject SignInManager<ApplicationUser> SignInManager @inject SignInManager<ApplicationUser> SignInManager
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
<PageTitle>Login - TrueCV</PageTitle> <PageTitle>Login - RealCV</PageTitle>
<div class="auth-container"> <div class="auth-container">
<!-- Left side - Form --> <!-- Left side - Form -->
@@ -16,7 +16,7 @@
<div class="auth-form-wrapper"> <div class="auth-form-wrapper">
<div class="text-center mb-4"> <div class="text-center mb-4">
<a href="/"> <a href="/">
<img src="images/TrueCV_Logo.png" alt="TrueCV" class="auth-logo" /> <img src="images/RealCV_Logo.png" alt="RealCV" class="auth-logo" />
</a> </a>
</div> </div>
@@ -80,7 +80,7 @@
</form> </form>
<div class="auth-divider"> <div class="auth-divider">
<span>New to TrueCV?</span> <span>New to RealCV?</span>
</div> </div>
<div class="text-center"> <div class="text-center">
@@ -123,7 +123,7 @@
<div class="auth-testimonial"> <div class="auth-testimonial">
<blockquote> <blockquote>
"TrueCV has transformed our hiring process. We catch discrepancies we would have missed before." "RealCV has transformed our hiring process. We catch discrepancies we would have missed before."
</blockquote> </blockquote>
<cite>- HR Director, Tech Company</cite> <cite>- HR Director, Tech Company</cite>
</div> </div>

View File

@@ -1,16 +1,16 @@
@page "/account/register" @page "/account/register"
@using TrueCV.Web.Components.Layout @using RealCV.Web.Components.Layout
@layout MainLayout @layout MainLayout
@rendermode InteractiveServer @rendermode InteractiveServer
@using Microsoft.AspNetCore.Identity @using Microsoft.AspNetCore.Identity
@using TrueCV.Infrastructure.Identity @using RealCV.Infrastructure.Identity
@inject UserManager<ApplicationUser> UserManager @inject UserManager<ApplicationUser> UserManager
@inject SignInManager<ApplicationUser> SignInManager @inject SignInManager<ApplicationUser> SignInManager
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
<PageTitle>Register - TrueCV</PageTitle> <PageTitle>Register - RealCV</PageTitle>
<div class="auth-container"> <div class="auth-container">
<!-- Left side - Form --> <!-- Left side - Form -->
@@ -18,7 +18,7 @@
<div class="auth-form-wrapper"> <div class="auth-form-wrapper">
<div class="text-center mb-4"> <div class="text-center mb-4">
<a href="/"> <a href="/">
<img src="images/TrueCV_Logo.png" alt="TrueCV" class="auth-logo" /> <img src="images/RealCV_Logo.png" alt="RealCV" class="auth-logo" />
</a> </a>
</div> </div>
@@ -157,7 +157,7 @@
<div class="auth-testimonial"> <div class="auth-testimonial">
<blockquote> <blockquote>
"We reduced bad hires by 40% in the first quarter using TrueCV." "We reduced bad hires by 40% in the first quarter using RealCV."
</blockquote> </blockquote>
<cite>- Recruitment Manager, Financial Services</cite> <cite>- Recruitment Manager, Financial Services</cite>
</div> </div>

View File

@@ -7,7 +7,7 @@
@inject AuthenticationStateProvider AuthenticationStateProvider @inject AuthenticationStateProvider AuthenticationStateProvider
@inject ILogger<Check> Logger @inject ILogger<Check> Logger
<PageTitle>Upload CVs - TrueCV</PageTitle> <PageTitle>Upload CVs - RealCV</PageTitle>
<div class="container py-5"> <div class="container py-5">
<div class="row justify-content-center"> <div class="row justify-content-center">
@@ -66,7 +66,7 @@
@ondrop:preventDefault> @ondrop:preventDefault>
<InputFile OnChange="HandleFileSelected" <InputFile OnChange="HandleFileSelected"
accept=".pdf,.docx" accept=".pdf,.docx,.json"
multiple multiple
class="d-none" class="d-none"
id="fileInput" /> id="fileInput" />
@@ -112,19 +112,10 @@
{ {
<div class="file-list-item"> <div class="file-list-item">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="file-type-icon me-3 @(file.Name.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase) ? "pdf" : "docx")"> <div class="file-type-icon me-3 @GetFileTypeClass(file.Name)">
@if (file.Name.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)) <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16">
{ <path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16"> </svg>
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
</svg>
}
else
{
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 16 16">
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
</svg>
}
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">
<p class="mb-0 fw-medium">@file.Name</p> <p class="mb-0 fw-medium">@file.Name</p>
@@ -186,21 +177,21 @@
<style> <style>
.upload-area { .upload-area {
border: 2px dashed var(--truecv-gray-300); border: 2px dashed var(--realcv-gray-300);
border-radius: 16px; border-radius: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: linear-gradient(180deg, var(--truecv-bg-surface) 0%, var(--truecv-bg-muted) 100%); background: linear-gradient(180deg, var(--realcv-bg-surface) 0%, var(--realcv-bg-muted) 100%);
} }
.upload-area:hover { .upload-area:hover {
border-color: var(--truecv-primary); border-color: var(--realcv-primary);
background: linear-gradient(180deg, #e8f1fa 0%, #d4e4f4 100%); background: linear-gradient(180deg, #e8f1fa 0%, #d4e4f4 100%);
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: 0 10px 25px -5px rgba(59, 111, 212, 0.1); box-shadow: 0 10px 25px -5px rgba(59, 111, 212, 0.1);
} }
.upload-area.dragging { .upload-area.dragging {
border-color: var(--truecv-primary); border-color: var(--realcv-primary);
background: linear-gradient(180deg, #d4e4f4 0%, #c5d9ef 100%); background: linear-gradient(180deg, #d4e4f4 0%, #c5d9ef 100%);
border-style: solid; border-style: solid;
transform: scale(1.02); transform: scale(1.02);
@@ -209,7 +200,7 @@
.upload-icon { .upload-icon {
width: 80px; width: 80px;
height: 80px; height: 80px;
background: linear-gradient(135deg, var(--truecv-primary) 0%, var(--truecv-primary-dark) 100%); background: linear-gradient(135deg, var(--realcv-primary) 0%, var(--realcv-primary-dark) 100%);
border-radius: 20px; border-radius: 20px;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -232,16 +223,16 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
border: 1px solid var(--truecv-gray-200); border: 1px solid var(--realcv-gray-200);
border-radius: 12px; border-radius: 12px;
padding: 1rem; padding: 1rem;
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
background: var(--truecv-bg-surface); background: var(--realcv-bg-surface);
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.file-list-item:hover { .file-list-item:hover {
border-color: var(--truecv-primary); border-color: var(--realcv-primary);
box-shadow: 0 4px 12px rgba(59, 111, 212, 0.08); box-shadow: 0 4px 12px rgba(59, 111, 212, 0.08);
} }
@@ -261,7 +252,12 @@
.file-type-icon.docx { .file-type-icon.docx {
background: linear-gradient(135deg, #e3ecf7 0%, #d4e4f4 100%); background: linear-gradient(135deg, #e3ecf7 0%, #d4e4f4 100%);
color: var(--truecv-primary); color: var(--realcv-primary);
}
.file-type-icon.json {
background: linear-gradient(135deg, #fef9c3 0%, #fef08a 100%);
color: #ca8a04;
} }
.security-info { .security-info {
@@ -273,14 +269,14 @@
align-items: center; align-items: center;
gap: 0.5rem; gap: 0.5rem;
padding: 0.625rem 1rem; padding: 0.625rem 1rem;
background: var(--truecv-bg-muted); background: var(--realcv-bg-muted);
border-radius: var(--truecv-radius); border-radius: var(--realcv-radius);
font-size: 0.875rem; font-size: 0.875rem;
color: var(--truecv-gray-600); color: var(--realcv-gray-600);
} }
.security-badge svg { .security-badge svg {
color: var(--truecv-verified); color: var(--realcv-verified);
} }
@@media (max-width: 576px) { @@media (max-width: 576px) {
@@ -515,6 +511,7 @@
{ {
".pdf" => header.AsSpan().StartsWith(PdfMagicBytes), ".pdf" => header.AsSpan().StartsWith(PdfMagicBytes),
".docx" => header.AsSpan().StartsWith(DocxMagicBytes), ".docx" => header.AsSpan().StartsWith(DocxMagicBytes),
".json" => header[0] == '{' || header[0] == '[',
_ => false _ => false
}; };
} }
@@ -522,7 +519,7 @@
private bool IsValidFileType(string fileName) private bool IsValidFileType(string fileName)
{ {
var extension = Path.GetExtension(fileName).ToLowerInvariant(); var extension = Path.GetExtension(fileName).ToLowerInvariant();
return extension is ".pdf" or ".docx"; return extension is ".pdf" or ".docx" or ".json";
} }
private static string FormatFileSize(long bytes) private static string FormatFileSize(long bytes)
@@ -539,4 +536,16 @@
return $"{size:0.##} {sizes[order]}"; return $"{size:0.##} {sizes[order]}";
} }
private static string GetFileTypeClass(string fileName)
{
var ext = Path.GetExtension(fileName).ToLowerInvariant();
return ext switch
{
".pdf" => "pdf",
".docx" => "docx",
".json" => "json",
_ => "docx"
};
}
} }

View File

@@ -8,10 +8,10 @@
@inject AuthenticationStateProvider AuthenticationStateProvider @inject AuthenticationStateProvider AuthenticationStateProvider
@inject ILogger<Dashboard> Logger @inject ILogger<Dashboard> Logger
@inject IJSRuntime JSRuntime @inject IJSRuntime JSRuntime
@inject TrueCV.Web.Services.IPdfReportService PdfReportService @inject RealCV.Web.Services.IPdfReportService PdfReportService
@inject IAuditService AuditService @inject IAuditService AuditService
<PageTitle>Dashboard - TrueCV</PageTitle> <PageTitle>Dashboard - RealCV</PageTitle>
<div class="container py-5"> <div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4"> <div class="d-flex justify-content-between align-items-center mb-4">
@@ -151,7 +151,7 @@
<!-- Checks List --> <!-- Checks List -->
<div class="card border-0 shadow-sm"> <div class="card border-0 shadow-sm">
<div class="card-header py-3 border-bottom" style="background-color: var(--truecv-bg-surface);"> <div class="card-header py-3 border-bottom" style="background-color: var(--realcv-bg-surface);">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center gap-3"> <div class="d-flex align-items-center gap-3">
<h5 class="mb-0 fw-bold">Recent CV Checks</h5> <h5 class="mb-0 fw-bold">Recent CV Checks</h5>
@@ -177,7 +177,7 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover align-middle mb-0"> <table class="table table-hover align-middle mb-0">
<thead> <thead>
<tr style="background-color: var(--truecv-bg-muted);"> <tr style="background-color: var(--realcv-bg-muted);">
<th class="border-0 ps-3 py-3" style="width: 40px;"> <th class="border-0 ps-3 py-3" style="width: 40px;">
<input type="checkbox" class="form-check-input" <input type="checkbox" class="form-check-input"
checked="@IsAllSelected()" checked="@IsAllSelected()"
@@ -210,7 +210,7 @@
</svg> </svg>
</div> </div>
<div> <div>
<p class="mb-0 fw-semibold text-dark">@Path.GetFileNameWithoutExtension(check.OriginalFileName)</p> <p class="mb-0 fw-semibold text-dark">@(!string.IsNullOrEmpty(check.CandidateName) ? check.CandidateName : Path.GetFileNameWithoutExtension(check.OriginalFileName))</p>
<small class="text-muted">@Path.GetExtension(check.OriginalFileName).ToUpperInvariant()</small> <small class="text-muted">@Path.GetExtension(check.OriginalFileName).ToUpperInvariant()</small>
</div> </div>
</div> </div>
@@ -395,7 +395,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 0 auto; margin: 0 auto;
color: var(--truecv-primary); color: var(--realcv-primary);
} }
.file-icon-wrapper { .file-icon-wrapper {
@@ -424,7 +424,7 @@
.score-ring-bg { .score-ring-bg {
fill: none; fill: none;
stroke: var(--truecv-gray-200); stroke: var(--realcv-gray-200);
stroke-width: 3; stroke-width: 3;
} }
@@ -436,20 +436,20 @@
transform: rotate(-90deg); transform: rotate(-90deg);
} }
.score-ring-progress.high { stroke: var(--truecv-verified); } .score-ring-progress.high { stroke: var(--realcv-verified); }
.score-ring-progress.medium { stroke: var(--truecv-warning); } .score-ring-progress.medium { stroke: var(--realcv-warning); }
.score-ring-progress.low { stroke: var(--truecv-danger); } .score-ring-progress.low { stroke: var(--realcv-danger); }
.score-ring-value { .score-ring-value {
position: absolute; position: absolute;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 700; font-weight: 700;
font-family: 'JetBrains Mono', monospace; font-family: 'Inter', system-ui, -apple-system, sans-serif;
} }
.text-verified { color: var(--truecv-verified); } .text-verified { color: var(--realcv-verified); }
.text-warning-dark { color: var(--truecv-warning-dark); } .text-warning-dark { color: var(--realcv-warning-dark); }
.text-danger { color: var(--truecv-danger); } .text-danger { color: var(--realcv-danger); }
@@media (max-width: 768px) { @@media (max-width: 768px) {
.d-flex.justify-content-between.align-items-center.mb-4 { .d-flex.justify-content-between.align-items-center.mb-4 {
@@ -633,7 +633,7 @@
try try
{ {
var reportDataList = new List<TrueCV.Web.Services.PdfReportData>(); var reportDataList = new List<RealCV.Web.Services.PdfReportData>();
foreach (var check in _checks) foreach (var check in _checks)
{ {
if (check.Status != "Completed") continue; if (check.Status != "Completed") continue;
@@ -657,9 +657,9 @@
else if (f.Severity == "Warning") warningFlags++; else if (f.Severity == "Warning") warningFlags++;
} }
reportDataList.Add(new TrueCV.Web.Services.PdfReportData reportDataList.Add(new RealCV.Web.Services.PdfReportData
{ {
CandidateName = Path.GetFileNameWithoutExtension(check.OriginalFileName) ?? "Unknown", CandidateName = report.CandidateName ?? Path.GetFileNameWithoutExtension(check.OriginalFileName) ?? "Unknown",
UploadDate = check.CreatedAt, UploadDate = check.CreatedAt,
Score = report.OverallScore, Score = report.OverallScore,
ScoreLabel = report.ScoreLabel, ScoreLabel = report.ScoreLabel,
@@ -674,7 +674,7 @@
var pdfBytes = PdfReportService.GenerateReport(reportDataList); var pdfBytes = PdfReportService.GenerateReport(reportDataList);
var base64 = Convert.ToBase64String(pdfBytes); var base64 = Convert.ToBase64String(pdfBytes);
var fileName = "TrueCV_Report_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".pdf"; var fileName = "RealCV_Report_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".pdf";
await JSRuntime.InvokeVoidAsync("downloadFile", fileName, base64, "application/pdf"); await JSRuntime.InvokeVoidAsync("downloadFile", fileName, base64, "application/pdf");
await AuditService.LogAsync(_userId, AuditActions.ReportExported, null, null, $"Exported {reportDataList.Count} reports to PDF"); await AuditService.LogAsync(_userId, AuditActions.ReportExported, null, null, $"Exported {reportDataList.Count} reports to PDF");

View File

@@ -1,6 +1,6 @@
@page "/" @page "/"
<PageTitle>TrueCV - Verify CVs with Confidence</PageTitle> <PageTitle>RealCV - Verify CVs with Confidence</PageTitle>
<!-- Hero Section with Gradient --> <!-- Hero Section with Gradient -->
<section class="hero-section text-white py-5"> <section class="hero-section text-white py-5">
@@ -12,7 +12,7 @@
<span style="color: #60A5FA; text-shadow: 0 2px 8px rgba(0,0,0,0.4);">Confidence</span> <span style="color: #60A5FA; text-shadow: 0 2px 8px rgba(0,0,0,0.4);">Confidence</span>
</h1> </h1>
<p class="lead mb-3 opacity-90" style="font-size: 1.25rem; line-height: 1.7;"> <p class="lead mb-3 opacity-90" style="font-size: 1.25rem; line-height: 1.7;">
TrueCV uses AI-powered analysis and official company records to verify employment history, RealCV uses AI-powered analysis and official company records to verify employment history,
detect timeline inconsistencies, and flag potential issues in candidate CVs. detect timeline inconsistencies, and flag potential issues in candidate CVs.
</p> </p>
<p class="mb-4 d-inline-flex align-items-center px-3 py-2 rounded-pill" style="font-size: 0.85rem; background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.25);"> <p class="mb-4 d-inline-flex align-items-center px-3 py-2 rounded-pill" style="font-size: 0.85rem; background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.25);">
@@ -63,10 +63,10 @@
</section> </section>
<!-- Features Section --> <!-- Features Section -->
<section id="features" class="py-5" style="background-color: var(--truecv-bg-page);"> <section id="features" class="py-5" style="background-color: var(--realcv-bg-page);">
<div class="container"> <div class="container">
<div class="text-center mb-5"> <div class="text-center mb-5">
<h2 class="fw-bold mb-3" style="font-size: 2.25rem;">How TrueCV Works</h2> <h2 class="fw-bold mb-3" style="font-size: 2.25rem;">How RealCV Works</h2>
<p class="text-muted" style="font-size: 1.125rem;">Comprehensive CV verification in three key areas</p> <p class="text-muted" style="font-size: 1.125rem;">Comprehensive CV verification in three key areas</p>
</div> </div>
@@ -183,7 +183,7 @@
</section> </section>
<!-- Trust indicators --> <!-- Trust indicators -->
<section class="py-4" style="background-color: var(--truecv-bg-muted); border-top: 1px solid var(--truecv-gray-200);"> <section class="py-4" style="background-color: var(--realcv-bg-muted); border-top: 1px solid var(--realcv-gray-200);">
<div class="container"> <div class="container">
<div class="row align-items-center justify-content-center text-center g-4"> <div class="row align-items-center justify-content-center text-center g-4">
<div class="col-6 col-md-3"> <div class="col-6 col-md-3">

View File

@@ -11,7 +11,7 @@
@inject IAuditService AuditService @inject IAuditService AuditService
@inject IPdfReportService PdfReportService @inject IPdfReportService PdfReportService
<PageTitle>Verification Report - TrueCV</PageTitle> <PageTitle>Verification Report - RealCV</PageTitle>
<div class="container py-5"> <div class="container py-5">
@if (_isLoading) @if (_isLoading)
@@ -153,7 +153,7 @@
<span class="score-max">/100</span> <span class="score-max">/100</span>
</div> </div>
</div> </div>
<div class="mt-2 text-white truecv-score-label">TrueCV Score</div> <div class="mt-2 text-white truecv-score-label">RealCV Score</div>
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<div class="row g-4 text-center text-md-start"> <div class="row g-4 text-center text-md-start">
@@ -202,7 +202,7 @@
<!-- Employment Verification --> <!-- Employment Verification -->
<div class="card border-0 shadow-sm mb-4"> <div class="card border-0 shadow-sm mb-4">
<div class="card-header py-3" style="background-color: var(--truecv-bg-surface);"> <div class="card-header py-3" style="background-color: var(--realcv-bg-surface);">
<h5 class="mb-0 fw-bold"> <h5 class="mb-0 fw-bold">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-building me-2" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-building me-2" viewBox="0 0 16 16">
<path d="M4 2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1Zm3 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1Zm3.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1ZM4 5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM7.5 5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM4.5 8a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM10.5 8a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Z"/> <path d="M4 2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1Zm3 0a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1Zm3.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1ZM4 5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM7.5 5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM4.5 8a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM10.5 8a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Z"/>
@@ -286,7 +286,7 @@
<!-- Gaps --> <!-- Gaps -->
<div class="col-md-6"> <div class="col-md-6">
<div class="card border-0 shadow-sm h-100"> <div class="card border-0 shadow-sm h-100">
<div class="card-header py-3" style="background-color: var(--truecv-bg-surface);"> <div class="card-header py-3" style="background-color: var(--realcv-bg-surface);">
<h5 class="mb-0 fw-bold"> <h5 class="mb-0 fw-bold">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-clock-history me-2 text-warning" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-clock-history me-2 text-warning" viewBox="0 0 16 16">
<path d="M8.515 1.019A7 7 0 0 0 8 1V0a8 8 0 0 1 .589.022l-.074.997zm2.004.45a7.003 7.003 0 0 0-.985-.299l.219-.976c.383.086.76.2 1.126.342l-.36.933zm1.37.71a7.01 7.01 0 0 0-.439-.27l.493-.87a8.025 8.025 0 0 1 .979.654l-.615.789a6.996 6.996 0 0 0-.418-.302zm1.834 1.79a6.99 6.99 0 0 0-.653-.796l.724-.69c.27.285.52.59.747.91l-.818.576zm.744 1.352a7.08 7.08 0 0 0-.214-.468l.893-.45a7.976 7.976 0 0 1 .45 1.088l-.95.313a7.023 7.023 0 0 0-.179-.483zm.53 2.507a6.991 6.991 0 0 0-.1-1.025l.985-.17c.067.386.106.778.116 1.17l-1 .025zm-.131 1.538c.033-.17.06-.339.081-.51l.993.123a7.957 7.957 0 0 1-.23 1.155l-.964-.267c.046-.165.086-.332.12-.501zm-.952 2.379c.184-.29.346-.594.486-.908l.914.405c-.16.36-.345.706-.555 1.038l-.845-.535zm-.964 1.205c.122-.122.239-.248.35-.378l.758.653a8.073 8.073 0 0 1-.401.432l-.707-.707z"/> <path d="M8.515 1.019A7 7 0 0 0 8 1V0a8 8 0 0 1 .589.022l-.074.997zm2.004.45a7.003 7.003 0 0 0-.985-.299l.219-.976c.383.086.76.2 1.126.342l-.36.933zm1.37.71a7.01 7.01 0 0 0-.439-.27l.493-.87a8.025 8.025 0 0 1 .979.654l-.615.789a6.996 6.996 0 0 0-.418-.302zm1.834 1.79a6.99 6.99 0 0 0-.653-.796l.724-.69c.27.285.52.59.747.91l-.818.576zm.744 1.352a7.08 7.08 0 0 0-.214-.468l.893-.45a7.976 7.976 0 0 1 .45 1.088l-.95.313a7.023 7.023 0 0 0-.179-.483zm.53 2.507a6.991 6.991 0 0 0-.1-1.025l.985-.17c.067.386.106.778.116 1.17l-1 .025zm-.131 1.538c.033-.17.06-.339.081-.51l.993.123a7.957 7.957 0 0 1-.23 1.155l-.964-.267c.046-.165.086-.332.12-.501zm-.952 2.379c.184-.29.346-.594.486-.908l.914.405c-.16.36-.345.706-.555 1.038l-.845-.535zm-.964 1.205c.122-.122.239-.248.35-.378l.758.653a8.073 8.073 0 0 1-.401.432l-.707-.707z"/>
@@ -331,7 +331,7 @@
<!-- Overlaps --> <!-- Overlaps -->
<div class="col-md-6"> <div class="col-md-6">
<div class="card border-0 shadow-sm h-100"> <div class="card border-0 shadow-sm h-100">
<div class="card-header py-3" style="background-color: var(--truecv-bg-surface);"> <div class="card-header py-3" style="background-color: var(--realcv-bg-surface);">
<h5 class="mb-0 fw-bold"> <h5 class="mb-0 fw-bold">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-intersect me-2 text-danger" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-intersect me-2 text-danger" viewBox="0 0 16 16">
<path d="M0 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2h2a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2H2a2 2 0 0 1-2-2V2zm5 10v2a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2v5a2 2 0 0 1-2 2H5zm6-8V2a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2V6a2 2 0 0 1 2-2h5z"/> <path d="M0 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2h2a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2H2a2 2 0 0 1-2-2V2zm5 10v2a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2v5a2 2 0 0 1-2 2H5zm6-8V2a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2V6a2 2 0 0 1 2-2h5z"/>
@@ -382,7 +382,7 @@
@if (_report.Flags.Count > 0) @if (_report.Flags.Count > 0)
{ {
<div class="card border-0 shadow-sm mb-4"> <div class="card border-0 shadow-sm mb-4">
<div class="card-header py-3" style="background-color: var(--truecv-bg-surface);"> <div class="card-header py-3" style="background-color: var(--realcv-bg-surface);">
<h5 class="mb-0 fw-bold"> <h5 class="mb-0 fw-bold">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-flag me-2 text-danger" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-flag me-2 text-danger" viewBox="0 0 16 16">
<path d="M14.778.085A.5.5 0 0 1 15 .5V8a.5.5 0 0 1-.314.464L14.5 8l.186.464-.003.001-.006.003-.023.009a12.435 12.435 0 0 1-.397.15c-.264.095-.631.223-1.047.35-.816.252-1.879.523-2.71.523-.847 0-1.548-.28-2.158-.525l-.028-.01C7.68 8.71 7.14 8.5 6.5 8.5c-.7 0-1.638.23-2.437.477A19.626 19.626 0 0 0 3 9.342V15.5a.5.5 0 0 1-1 0V.5a.5.5 0 0 1 1 0v.282c.226-.079.496-.17.79-.26C4.606.272 5.67 0 6.5 0c.84 0 1.524.277 2.121.519l.043.018C9.286.788 9.828 1 10.5 1c.7 0 1.638-.23 2.437-.477a19.587 19.587 0 0 0 1.349-.476l.019-.007.004-.002h.001"/> <path d="M14.778.085A.5.5 0 0 1 15 .5V8a.5.5 0 0 1-.314.464L14.5 8l.186.464-.003.001-.006.003-.023.009a12.435 12.435 0 0 1-.397.15c-.264.095-.631.223-1.047.35-.816.252-1.879.523-2.71.523-.847 0-1.548-.28-2.158-.525l-.028-.01C7.68 8.71 7.14 8.5 6.5 8.5c-.7 0-1.638.23-2.437.477A19.626 19.626 0 0 0 3 9.342V15.5a.5.5 0 0 1-1 0V.5a.5.5 0 0 1 1 0v.282c.226-.079.496-.17.79-.26C4.606.272 5.67 0 6.5 0c.84 0 1.524.277 2.121.519l.043.018C9.286.788 9.828 1 10.5 1c.7 0 1.638-.23 2.437-.477a19.587 19.587 0 0 0 1.349-.476l.019-.007.004-.002h.001"/>
@@ -620,13 +620,13 @@
.flag-item.flag-info { .flag-item.flag-info {
background-color: #f0f5fa; background-color: #f0f5fa;
border-left-color: var(--truecv-primary); border-left-color: var(--realcv-primary);
} }
.flag-title { .flag-title {
font-weight: 600; font-weight: 600;
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
color: var(--truecv-gray-700); color: var(--realcv-gray-700);
} }
.flag-description { .flag-description {
@@ -920,7 +920,7 @@
var candidateName = Path.GetFileNameWithoutExtension(_check.OriginalFileName); var candidateName = Path.GetFileNameWithoutExtension(_check.OriginalFileName);
var pdfBytes = PdfReportService.GenerateSingleReport(candidateName, _report); var pdfBytes = PdfReportService.GenerateSingleReport(candidateName, _report);
var fileName = $"TrueCV_Report_{candidateName}_{DateTime.Now:yyyyMMdd}.pdf"; var fileName = $"RealCV_Report_{candidateName}_{DateTime.Now:yyyyMMdd}.pdf";
await DownloadFileAsync(fileName, pdfBytes, "application/pdf"); await DownloadFileAsync(fileName, pdfBytes, "application/pdf");
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -11,11 +11,11 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.Extensions.Logging @using Microsoft.Extensions.Logging
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using TrueCV.Web @using RealCV.Web
@using TrueCV.Web.Components @using RealCV.Web.Components
@using TrueCV.Web.Components.Shared @using RealCV.Web.Components.Shared
@using TrueCV.Web.Services @using RealCV.Web.Services
@using TrueCV.Application.Interfaces @using RealCV.Application.Interfaces
@using TrueCV.Application.DTOs @using RealCV.Application.DTOs
@using TrueCV.Application.Models @using RealCV.Application.Models
@using TrueCV.Domain.Enums @using RealCV.Domain.Enums

Some files were not shown because too many files have changed in this diff Show More