992f89e619
Recover the F1 Career Profile foundation + AI-workspace persistence from the unmerged feature/career-workspace branch, so Phase 2 builds on the documented, tested target state instead of re-deriving it. Foundation only — CV Builder commits (variants, ATS badge, rewrite diff) stay deferred per "do not build CV Builder yet". See docs/career-workspace-branch-assessment.md. Squashed from 3 branch commits (235e291,5916f09,00a035e), resolved against main + Phase 0: - CareerProfile + CareerProfileVersion (append-only history), dual-written from every profile save path via CareerProfileService. ApplicationUser. ProfileCvStructureJson stays authoritative; the tables mirror it. Stable item IDs assigned to jobs/education/certifications/projects (the prerequisite for future variant lineage). CvDateNormalizer for free-text -> YYYY-MM. - InterviewPrepNote + AiWorkspaceNote: cache AI interview prep / candidate fit / focus plan keyed by an attachment-context signature, so they stop regenerating (and re-spending the provider) on every open. Conflict resolutions (union, favouring current code + Phase 0): - JobTrackerContext / StartupInitializationExtensions: kept Phase 0's tables and reconciler blocks, added the career/interview/ai-note tables (both SQLite and MySQL dialects). - ProfileCvController: dropped the branch's in-file DTO records (main defines them in ProfileCvDtos.cs) and the LayoutFamily/AtsRating template fields (deferred ATS-badge work), keeping main's 7-arg CvTemplateDescriptor. - JobApplicationsController: kept the branch's cache-check, restored main's AsNoTracking on the read-only user load. Tables ship empty (verified dev); nothing to migrate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
128 lines
4.6 KiB
C#
128 lines
4.6 KiB
C#
namespace JobTrackerApi.Models;
|
|
|
|
public sealed class StructuredCvProfile
|
|
{
|
|
public string Version { get; set; } = "1";
|
|
public StructuredCvMetadata Metadata { get; set; } = new();
|
|
public StructuredCvContact Contact { get; set; } = new();
|
|
public List<string> Summary { get; set; } = new();
|
|
public List<StructuredCvJob> Jobs { get; set; } = new();
|
|
public List<StructuredCvEducation> Education { get; set; } = new();
|
|
public List<StructuredCvCertification> Certifications { get; set; } = new();
|
|
public List<StructuredCvProject> Projects { get; set; } = new();
|
|
public List<string> Skills { get; set; } = new();
|
|
public List<StructuredCvLanguage> Languages { get; set; } = new();
|
|
public List<string> Interests { get; set; } = new();
|
|
public List<StructuredCvOtherSection> OtherSections { get; set; } = new();
|
|
public List<StructuredCvSection> Sections { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvMetadata
|
|
{
|
|
public int? ProfileVersion { get; set; }
|
|
public int? AppliedExtractionRunId { get; set; }
|
|
public DateTimeOffset? UpdatedAtUtc { get; set; }
|
|
public Dictionary<string, StructuredCvFieldMetadata> Fields { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvFieldMetadata
|
|
{
|
|
public double? Confidence { get; set; }
|
|
public string? Method { get; set; }
|
|
public string? SourceSnippet { get; set; }
|
|
public int? SourcePage { get; set; }
|
|
public string? SourceBlockId { get; set; }
|
|
public string? ReviewState { get; set; }
|
|
public DateTimeOffset? LastUpdatedAtUtc { get; set; }
|
|
}
|
|
|
|
public sealed class StructuredCvContact
|
|
{
|
|
public string? FullName { get; set; }
|
|
public string? Headline { get; set; }
|
|
public string? Email { get; set; }
|
|
public string? Phone { get; set; }
|
|
public string? Location { get; set; }
|
|
public string? Website { get; set; }
|
|
public string? LinkedIn { get; set; }
|
|
}
|
|
|
|
public sealed class StructuredCvJob
|
|
{
|
|
// Stable item ID (assigned by CareerProfileService on first save). Required for CV variants
|
|
// to reference "this job" across profile edits, instead of by array position. Nullable/empty
|
|
// on freshly-parsed or legacy data until the first save assigns it.
|
|
public string? Id { get; set; }
|
|
public string? Title { get; set; }
|
|
public string? Company { get; set; }
|
|
public string? Location { get; set; }
|
|
public string? Start { get; set; }
|
|
public string? End { get; set; }
|
|
// Best-effort "YYYY-MM" normalization of Start/End, computed alongside Id assignment.
|
|
// Null when Start/End can't be parsed; the free-string fields above remain the display source.
|
|
public string? StartDate { get; set; }
|
|
public string? EndDate { get; set; }
|
|
public bool IsCurrent { get; set; }
|
|
public List<string> Bullets { get; set; } = new();
|
|
public List<string> Skills { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvEducation
|
|
{
|
|
public string? Id { get; set; }
|
|
public string? Qualification { get; set; }
|
|
public string? QualificationLevel { get; set; }
|
|
public string? Institution { get; set; }
|
|
public string? Location { get; set; }
|
|
public string? Start { get; set; }
|
|
public string? End { get; set; }
|
|
public string? StartDate { get; set; }
|
|
public string? EndDate { get; set; }
|
|
public List<string> Details { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvCertification
|
|
{
|
|
public string? Id { get; set; }
|
|
public string? Name { get; set; }
|
|
public string? Issuer { get; set; }
|
|
public string? Location { get; set; }
|
|
public string? Date { get; set; }
|
|
public string? DateNormalized { get; set; }
|
|
public List<string> Details { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvProject
|
|
{
|
|
public string? Id { get; set; }
|
|
public string? Name { get; set; }
|
|
public string? Role { get; set; }
|
|
public string? Location { get; set; }
|
|
public string? Start { get; set; }
|
|
public string? End { get; set; }
|
|
public string? StartDate { get; set; }
|
|
public string? EndDate { get; set; }
|
|
public List<string> Bullets { get; set; } = new();
|
|
public List<string> Skills { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvLanguage
|
|
{
|
|
public string? Name { get; set; }
|
|
public string? Level { get; set; }
|
|
public string? Notes { get; set; }
|
|
}
|
|
|
|
public sealed class StructuredCvOtherSection
|
|
{
|
|
public string? Title { get; set; }
|
|
public List<string> Items { get; set; } = new();
|
|
}
|
|
|
|
public sealed class StructuredCvSection
|
|
{
|
|
public string Name { get; set; } = string.Empty;
|
|
public string Content { get; set; } = string.Empty;
|
|
public int WordCount { get; set; }
|
|
}
|