diff --git a/Apis/cv-search-data/cv-search-models.csproj b/Apis/cv-search-data/cv-search-models.csproj deleted file mode 100644 index 310b3cf..0000000 --- a/Apis/cv-search-data/cv-search-models.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net10.0 - CvSearch.Models - enable - enable - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.Designer.cs b/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.Designer.cs deleted file mode 100644 index 475bd9b..0000000 --- a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.Designer.cs +++ /dev/null @@ -1,160 +0,0 @@ -// -using System; -using CvSearch.Models.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CvSearch.Models.Migrations -{ - [DbContext(typeof(CvSearchDbContext))] - [Migration("20260522093356_AddJobSearchTables")] - partial class AddJobSearchTables - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("cvSearch") - .HasAnnotation("ProductVersion", "10.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchResultEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("JobText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("JobTitle") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("nvarchar(512)"); - - b.Property("JobUrl") - .IsRequired() - .HasMaxLength(2048) - .HasColumnType("nvarchar(2048)"); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ResultJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Score") - .HasColumnType("int"); - - b.Property("SessionId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("SessionId"); - - b.ToTable("JobSearchResults", "cvSearch"); - }); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchSessionEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("CvDocumentId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Keywords") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("ProviderConfigJson") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("nvarchar(32)"); - - b.Property("TokenId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("Status"); - - b.ToTable("JobSearchSessions", "cvSearch"); - }); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchTokenEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("CvDocumentId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExpiresAt") - .HasColumnType("datetime2"); - - b.Property("Used") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false); - - b.HasKey("Id"); - - b.ToTable("JobSearchTokens", "cvSearch"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.cs b/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.cs deleted file mode 100644 index adbc233..0000000 --- a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace CvSearch.Models.Migrations -{ - /// - public partial class AddJobSearchTables : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "cvSearch"); - - migrationBuilder.CreateTable( - name: "JobSearchResults", - schema: "cvSearch", - columns: table => new - { - Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - SessionId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - ProviderName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - JobUrl = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false), - JobTitle = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), - JobText = table.Column(type: "nvarchar(max)", nullable: false), - Score = table.Column(type: "int", nullable: false), - ResultJson = table.Column(type: "nvarchar(max)", nullable: false), - CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()") - }, - constraints: table => - { - table.PrimaryKey("PK_JobSearchResults", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "JobSearchSessions", - schema: "cvSearch", - columns: table => new - { - Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - TokenId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - CvDocumentId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - Status = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: false), - Keywords = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: false), - ProviderConfigJson = table.Column(type: "nvarchar(max)", nullable: true), - CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()") - }, - constraints: table => - { - table.PrimaryKey("PK_JobSearchSessions", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "JobSearchTokens", - schema: "cvSearch", - columns: table => new - { - Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - CvDocumentId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), - ExpiresAt = table.Column(type: "datetime2", nullable: false), - Used = table.Column(type: "bit", nullable: false, defaultValue: false), - CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()") - }, - constraints: table => - { - table.PrimaryKey("PK_JobSearchTokens", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_JobSearchResults_SessionId", - schema: "cvSearch", - table: "JobSearchResults", - column: "SessionId"); - - migrationBuilder.CreateIndex( - name: "IX_JobSearchSessions_Status", - schema: "cvSearch", - table: "JobSearchSessions", - column: "Status"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "JobSearchResults", - schema: "cvSearch"); - - migrationBuilder.DropTable( - name: "JobSearchSessions", - schema: "cvSearch"); - - migrationBuilder.DropTable( - name: "JobSearchTokens", - schema: "cvSearch"); - } - } -} diff --git a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.Designer.cs b/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.Designer.cs deleted file mode 100644 index 68602de..0000000 --- a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.Designer.cs +++ /dev/null @@ -1,174 +0,0 @@ -// -using System; -using CvSearch.Models.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CvSearch.Models.Migrations -{ - [DbContext(typeof(CvSearchDbContext))] - [Migration("20260524145702_AddLanguageToJobSearchEntities")] - partial class AddLanguageToJobSearchEntities - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("cvSearch") - .HasAnnotation("ProductVersion", "10.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchResultEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("JobText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("JobTitle") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("nvarchar(512)"); - - b.Property("JobUrl") - .IsRequired() - .HasMaxLength(2048) - .HasColumnType("nvarchar(2048)"); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ResultJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Score") - .HasColumnType("int"); - - b.Property("SessionId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("SessionId"); - - b.ToTable("JobSearchResults", "cvSearch"); - }); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchSessionEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("CvDocumentId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Keywords") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("Language") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("nvarchar(8)") - .HasDefaultValue("en"); - - b.Property("ProviderConfigJson") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("nvarchar(32)"); - - b.Property("TokenId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("Status"); - - b.ToTable("JobSearchSessions", "cvSearch"); - }); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchTokenEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("CvDocumentId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExpiresAt") - .HasColumnType("datetime2"); - - b.Property("Language") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("nvarchar(8)") - .HasDefaultValue("en"); - - b.Property("Used") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false); - - b.HasKey("Id"); - - b.ToTable("JobSearchTokens", "cvSearch"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.cs b/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.cs deleted file mode 100644 index ac5ea0b..0000000 --- a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace CvSearch.Models.Migrations -{ - /// - public partial class AddLanguageToJobSearchEntities : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Language", - schema: "cvSearch", - table: "JobSearchTokens", - type: "nvarchar(8)", - maxLength: 8, - nullable: false, - defaultValue: "en"); - - migrationBuilder.AddColumn( - name: "Language", - schema: "cvSearch", - table: "JobSearchSessions", - type: "nvarchar(8)", - maxLength: 8, - nullable: false, - defaultValue: "en"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Language", - schema: "cvSearch", - table: "JobSearchTokens"); - - migrationBuilder.DropColumn( - name: "Language", - schema: "cvSearch", - table: "JobSearchSessions"); - } - } -} diff --git a/Apis/cv-search-models/Migrations/CvSearchDbContextModelSnapshot.cs b/Apis/cv-search-models/Migrations/CvSearchDbContextModelSnapshot.cs deleted file mode 100644 index 5fd3d9e..0000000 --- a/Apis/cv-search-models/Migrations/CvSearchDbContextModelSnapshot.cs +++ /dev/null @@ -1,171 +0,0 @@ -// -using System; -using CvSearch.Models.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CvSearch.Models.Migrations -{ - [DbContext(typeof(CvSearchDbContext))] - partial class CvSearchDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("cvSearch") - .HasAnnotation("ProductVersion", "10.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchResultEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("JobText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("JobTitle") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("nvarchar(512)"); - - b.Property("JobUrl") - .IsRequired() - .HasMaxLength(2048) - .HasColumnType("nvarchar(2048)"); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("ResultJson") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Score") - .HasColumnType("int"); - - b.Property("SessionId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("SessionId"); - - b.ToTable("JobSearchResults", "cvSearch"); - }); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchSessionEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("CvDocumentId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("Keywords") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("Language") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("nvarchar(8)") - .HasDefaultValue("en"); - - b.Property("ProviderConfigJson") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("nvarchar(32)"); - - b.Property("TokenId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.HasKey("Id"); - - b.HasIndex("Status"); - - b.ToTable("JobSearchSessions", "cvSearch"); - }); - - modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchTokenEntity", b => - { - b.Property("Id") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("CvDocumentId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("nvarchar(64)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("ExpiresAt") - .HasColumnType("datetime2"); - - b.Property("Language") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(8) - .HasColumnType("nvarchar(8)") - .HasDefaultValue("en"); - - b.Property("Used") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(false); - - b.HasKey("Id"); - - b.ToTable("JobSearchTokens", "cvSearch"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Apis/cv-search-models/Settings/JobSearchSettings.cs b/Apis/cv-search-models/Settings/JobSearchSettings.cs deleted file mode 100644 index 2634509..0000000 --- a/Apis/cv-search-models/Settings/JobSearchSettings.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace CvSearch.Models.Settings; - -public sealed class JobSearchSettings -{ - public bool Enabled { get; set; } = true; - public string JobSearchLinkBaseUrl { get; set; } = string.Empty; - public int TokenExpiryDays { get; set; } = 7; - public int MinMatchScore { get; set; } = 15; - public int MaxJobsToMatch { get; set; } = 15; - public List Providers { get; set; } = []; -} - -public sealed class JobProviderConfig -{ - public string Name { get; set; } = string.Empty; - public bool Enabled { get; set; } = true; - public string SearchUrlTemplate { get; set; } = string.Empty; - public string JobLinkContains { get; set; } = string.Empty; - public List InitialKeywords { get; set; } = []; - public int MaxResults { get; set; } = 20; -} diff --git a/Apis/cv-search-models/cv-search-models.csproj b/Apis/cv-search-models/cv-search-models.csproj deleted file mode 100644 index 310b3cf..0000000 --- a/Apis/cv-search-models/cv-search-models.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net10.0 - CvSearch.Models - enable - enable - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/Apis/myai-data/myai-models.csproj b/Apis/myai-data/myai-models.csproj deleted file mode 100644 index cf8d4c5..0000000 --- a/Apis/myai-data/myai-models.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net10.0 - MyAi.Models - enable - enable - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/Apis/myai-models/Migrations/20260524145351_AddTemplates.Designer.cs b/Apis/myai-models/Migrations/20260524145351_AddTemplates.Designer.cs deleted file mode 100644 index 1e7b3c9..0000000 --- a/Apis/myai-models/Migrations/20260524145351_AddTemplates.Designer.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using MyAi.Models.Data; - -#nullable disable - -namespace MyAi.Models.Migrations -{ - [DbContext(typeof(MyAiDbContext))] - [Migration("20260524145351_AddTemplates")] - partial class AddTemplates - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("myAi") - .HasAnnotation("ProductVersion", "10.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("MyAi.Models.Data.Entities.TemplateEntity", b => - { - b.Property("Key") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Language") - .HasMaxLength(8) - .HasColumnType("nvarchar(8)"); - - b.Property("Description") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasDefaultValue(""); - - b.Property("UpdatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Key", "Language"); - - b.ToTable("Templates", "myAi"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Apis/myai-models/Migrations/20260524145351_AddTemplates.cs b/Apis/myai-models/Migrations/20260524145351_AddTemplates.cs deleted file mode 100644 index 299afc6..0000000 --- a/Apis/myai-models/Migrations/20260524145351_AddTemplates.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace MyAi.Models.Migrations -{ - /// - public partial class AddTemplates : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "myAi"); - - migrationBuilder.CreateTable( - name: "Templates", - schema: "myAi", - columns: table => new - { - Key = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), - Language = table.Column(type: "nvarchar(8)", maxLength: 8, nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: false), - Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false, defaultValue: ""), - UpdatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()") - }, - constraints: table => - { - table.PrimaryKey("PK_Templates", x => new { x.Key, x.Language }); - }); - - Seed(migrationBuilder); - } - - private static void Seed(MigrationBuilder m) - { - void Row(string key, string lang, string value, string description = "") - => m.InsertData("Templates", ["Key", "Language", "Value", "Description"], [key, lang, value, description], "myAi"); - - // Match result email — subject - Row("email.match.subject", "en", "MyAi.ro CV Match: {{score}}% - {{jobLabel}}", "Subject for the CV match result email"); - Row("email.match.subject", "ro", "MyAi.ro Potrivire CV: {{score}}% - {{jobLabel}}", "Subiect email rezultat potrivire CV"); - - // Match result email — body - Row("email.match.body", "en", - "CV Matcher result\n\nCV Document ID: {{cvDocumentId}}\nJob: {{jobLabel}}\nJob URL: {{jobUrl}}\nScore: {{score}}%\n\nSummary:\n{{summary}}\n\nStrengths:\n{{strengths}}\n\nGaps:\n{{gaps}}\n\nRecommendations:\n{{recommendations}}", - "Body for the CV match result email"); - Row("email.match.body", "ro", - "Rezultat potrivire CV\n\nID document CV: {{cvDocumentId}}\nJob: {{jobLabel}}\nURL job: {{jobUrl}}\nScor: {{score}}%\n\nRezumat:\n{{summary}}\n\nPuncte forte:\n{{strengths}}\n\nLipsuri:\n{{gaps}}\n\nRecomandări:\n{{recommendations}}", - "Corpul emailului pentru rezultatul potrivirii CV"); - - // Match result email — job search CTA footer - Row("email.match.job-search-footer", "en", - "\n\n---\nWant to find more jobs matching your CV?\nClick: {{jobSearchLink}}\n(link valid for {{expiryDays}} days)", - "Job search CTA appended to match result email"); - Row("email.match.job-search-footer", "ro", - "\n\n---\nVrei sa gasesti mai multe joburi potrivite CV-ului tau?\nClick: {{jobSearchLink}}\n(link valabil {{expiryDays}} zile)", - "CTA cautare joburi adaugat la emailul de potrivire CV"); - - // Job search results email — subject - Row("email.search-results.subject", "en", "MyAi.ro: {{count}} jobs matching your CV", "Subject for job search results email"); - Row("email.search-results.subject", "ro", "MyAi.ro: {{count}} joburi potrivite CV-ului tau", "Subiect email rezultate cautare joburi"); - - // Job search results email — body preamble (items appended in code) - Row("email.search-results.body", "en", "MyAi.ro found {{count}} jobs matching your CV:\n\n{{items}}", "Body preamble for job search results email"); - Row("email.search-results.body", "ro", "MyAi.ro a gasit {{count}} joburi potrivite CV-ului tau:\n\n{{items}}", "Corpul emailului de rezultate cautare joburi"); - - // Job search results email — no results found - Row("email.search-results.empty", "en", "MyAi.ro found no jobs matching your CV. Try again later or update your CV.", "No results message for job search results email"); - Row("email.search-results.empty", "ro", "MyAi.ro nu a gasit joburi care sa corespunda CV-ului tau. Incercati mai tarziu sau ajustati CV-ul.", "Mesaj fara rezultate pentru emailul de cautare joburi"); - - // HTML job-search start page messages - Row("html.job-search.started.title", "en", "Job search started", "Title for job search started page"); - Row("html.job-search.started.message", "en", "Your job search has started. Results will be sent to your email shortly.", "Message for job search started page"); - Row("html.job-search.started.title", "ro", "Căutare joburi pornită", "Titlu pagina cautare joburi pornita"); - Row("html.job-search.started.message", "ro", "Căutarea joburilor a început. Rezultatele vor fi trimise pe email în scurt timp.", "Mesaj pagina cautare joburi pornita"); - - Row("html.job-search.already-used.title", "en", "Link already used", "Title for already-used page"); - Row("html.job-search.already-used.message", "en", "This job search link has already been used.", "Message for already-used page"); - Row("html.job-search.already-used.title", "ro", "Link deja folosit", "Titlu pagina link deja folosit"); - Row("html.job-search.already-used.message", "ro", "Acest link de cautare joburi a fost deja folosit.", "Mesaj pagina link deja folosit"); - - Row("html.job-search.expired.title", "en", "Link expired", "Title for expired link page"); - Row("html.job-search.expired.message", "en", "This job search link has expired. Please request a new CV match to get a fresh link.", "Message for expired link page"); - Row("html.job-search.expired.title", "ro", "Link expirat", "Titlu pagina link expirat"); - Row("html.job-search.expired.message", "ro", "Acest link de cautare joburi a expirat. Solicita o noua potrivire CV pentru a primi un link nou.", "Mesaj pagina link expirat"); - - Row("html.job-search.invalid.title", "en", "Invalid link", "Title for invalid link page"); - Row("html.job-search.invalid.message", "en", "This job search link is not valid.", "Message for invalid link page"); - Row("html.job-search.invalid.title", "ro", "Link invalid", "Titlu pagina link invalid"); - Row("html.job-search.invalid.message", "ro", "Acest link de cautare joburi nu este valid.", "Mesaj pagina link invalid"); - - Row("html.job-search.error.title", "en", "Error", "Title for error page"); - Row("html.job-search.error.message", "en", "An error occurred. Please try again later.", "Message for error page"); - Row("html.job-search.error.title", "ro", "Eroare", "Titlu pagina eroare"); - Row("html.job-search.error.message", "ro", "A apărut o eroare. Te rugăm să încerci din nou mai târziu.", "Mesaj pagina eroare"); - - // AI system prompt for CV matching (language is a {{languageName}} variable inside it) - Row("ai.cv-match.system-prompt", "*", - "You are a strict CV-to-job matching engine. Return JSON only. Score realistically from 0 to 100.\nPenalize missing required skills. Do not invent experience. Use concise business language.\nRespond entirely in {{languageName}} — all text fields in the JSON must be in {{languageName}}.\nJSON shape: {\"score\":number,\"summary\":\"...\",\"strengths\":[\"...\"],\"gaps\":[\"...\"],\"recommendations\":[\"...\"],\"evidence\":[\"...\"]}", - "System prompt template for the CV-to-job LLM matching call. {{languageName}} is substituted at runtime."); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Templates", - schema: "myAi"); - } - } -} diff --git a/Apis/myai-models/Migrations/MyAiDbContextModelSnapshot.cs b/Apis/myai-models/Migrations/MyAiDbContextModelSnapshot.cs deleted file mode 100644 index d9a7549..0000000 --- a/Apis/myai-models/Migrations/MyAiDbContextModelSnapshot.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using MyAi.Models.Data; - -#nullable disable - -namespace MyAi.Models.Migrations -{ - [DbContext(typeof(MyAiDbContext))] - partial class MyAiDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("myAi") - .HasAnnotation("ProductVersion", "10.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("MyAi.Models.Data.Entities.TemplateEntity", b => - { - b.Property("Key") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)"); - - b.Property("Language") - .HasMaxLength(8) - .HasColumnType("nvarchar(8)"); - - b.Property("Description") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)") - .HasDefaultValue(""); - - b.Property("UpdatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValueSql("SYSUTCDATETIME()"); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Key", "Language"); - - b.ToTable("Templates", "myAi"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Apis/myai-models/Services/DbTemplateService.cs b/Apis/myai-models/Services/DbTemplateService.cs deleted file mode 100644 index a19a48f..0000000 --- a/Apis/myai-models/Services/DbTemplateService.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using MyAi.Models.Data; -using System.Collections.Concurrent; - -namespace MyAi.Models.Services; - -public sealed class DbTemplateService : ITemplateService -{ - private readonly IServiceScopeFactory _scopeFactory; - private readonly ILogger _logger; - private ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase); - private DateTime _loadedAt = DateTime.MinValue; - private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(10); - - public DbTemplateService(IServiceScopeFactory scopeFactory, ILogger logger) - { - _scopeFactory = scopeFactory; - _logger = logger; - } - - public string Get(string key, string language = "en") - { - EnsureCacheLoaded(); - - if (_cache.TryGetValue(CacheKey(key, language), out var value)) - return value; - - if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase) - && _cache.TryGetValue(CacheKey(key, "en"), out var fallback)) - return fallback; - - _logger.LogWarning("Template not found: key={Key}, language={Language}", key, language); - return key; - } - - public string Render(string key, string language, params (string Key, string Value)[] placeholders) - { - var template = Get(key, language); - foreach (var (k, v) in placeholders) - template = template.Replace($"{{{{{k}}}}}", v, StringComparison.OrdinalIgnoreCase); - return template; - } - - private void EnsureCacheLoaded() - { - if (DateTime.UtcNow - _loadedAt < CacheTtl) return; - - try - { - using var scope = _scopeFactory.CreateScope(); - var db = scope.ServiceProvider.GetRequiredService(); - var rows = db.Templates.AsNoTracking().ToList(); - var fresh = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - foreach (var row in rows) - fresh[CacheKey(row.Key, row.Language)] = row.Value; - - _cache = fresh; - _loadedAt = DateTime.UtcNow; - _logger.LogDebug("Template cache refreshed. {Count} templates loaded.", rows.Count); - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to refresh template cache. Serving stale cache."); - } - } - - private static string CacheKey(string key, string language) => $"{key}::{language}"; -} diff --git a/Apis/myai-models/Services/ITemplateService.cs b/Apis/myai-models/Services/ITemplateService.cs deleted file mode 100644 index 50eaad8..0000000 --- a/Apis/myai-models/Services/ITemplateService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace MyAi.Models.Services; - -public interface ITemplateService -{ - string Get(string key, string language = "en"); - string Render(string key, string language, params (string Key, string Value)[] placeholders); -} diff --git a/Apis/myai-models/myai-models.csproj b/Apis/myai-models/myai-models.csproj deleted file mode 100644 index cf8d4c5..0000000 --- a/Apis/myai-models/myai-models.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net10.0 - MyAi.Models - enable - enable - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - -