feat(church-profile): add AI provider/model/key columns + migration

This commit is contained in:
Chris Chen
2026-06-25 13:07:30 -07:00
parent bcaa3e2f25
commit 75905e7036
5 changed files with 2401 additions and 0 deletions
+5
View File
@@ -309,6 +309,11 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
entity.Property(e => e.Website).HasMaxLength(300); entity.Property(e => e.Website).HasMaxLength(300);
entity.Property(e => e.CreatedBy).HasMaxLength(450); entity.Property(e => e.CreatedBy).HasMaxLength(450);
entity.Property(e => e.UpdatedBy).HasMaxLength(450); entity.Property(e => e.UpdatedBy).HasMaxLength(450);
entity.Property(e => e.AiProvider).HasMaxLength(20).HasDefaultValue("Claude");
entity.Property(e => e.ClaudeModel).HasMaxLength(100).HasDefaultValue("claude-haiku-4-5-20251001");
entity.Property(e => e.ClaudeApiKey).HasMaxLength(500);
entity.Property(e => e.GeminiModel).HasMaxLength(100).HasDefaultValue("gemini-2.5-flash-lite");
entity.Property(e => e.GeminiApiKey).HasMaxLength(500);
// Optimistic-concurrency token for safe check-number allocation. // Optimistic-concurrency token for safe check-number allocation.
entity.Property(e => e.xmin).IsRowVersion(); entity.Property(e => e.xmin).IsRowVersion();
}); });
+7
View File
@@ -21,6 +21,13 @@ public class ChurchProfile : AuditableEntity, IAuditable
public string? BankAccountNumber { get; set; } public string? BankAccountNumber { get; set; }
public string? BankRoutingNumber { get; set; } public string? BankRoutingNumber { get; set; }
// ── AI assist provider settings (editable via Church Profile → AI 設定 tab) ──
public string AiProvider { get; set; } = "Claude"; // "Claude" | "Gemini"
public string? ClaudeModel { get; set; } = "claude-haiku-4-5-20251001";
public string? ClaudeApiKey { get; set; } // secret, stored plaintext
public string? GeminiModel { get; set; } = "gemini-2.5-flash-lite";
public string? GeminiApiKey { get; set; } // secret, stored plaintext
/// <summary>Next check number to allocate; consumed (++) when a check is issued.</summary> /// <summary>Next check number to allocate; consumed (++) when a check is issued.</summary>
public int NextCheckNumber { get; set; } = 1001; public int NextCheckNumber { get; set; } = 1001;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,76 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ROLAC.API.Migrations
{
/// <inheritdoc />
public partial class AddChurchAiSettings : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "AiProvider",
table: "ChurchProfiles",
type: "character varying(20)",
maxLength: 20,
nullable: false,
defaultValue: "Claude");
migrationBuilder.AddColumn<string>(
name: "ClaudeApiKey",
table: "ChurchProfiles",
type: "character varying(500)",
maxLength: 500,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ClaudeModel",
table: "ChurchProfiles",
type: "character varying(100)",
maxLength: 100,
nullable: true,
defaultValue: "claude-haiku-4-5-20251001");
migrationBuilder.AddColumn<string>(
name: "GeminiApiKey",
table: "ChurchProfiles",
type: "character varying(500)",
maxLength: 500,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "GeminiModel",
table: "ChurchProfiles",
type: "character varying(100)",
maxLength: 100,
nullable: true,
defaultValue: "gemini-2.5-flash-lite");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AiProvider",
table: "ChurchProfiles");
migrationBuilder.DropColumn(
name: "ClaudeApiKey",
table: "ChurchProfiles");
migrationBuilder.DropColumn(
name: "ClaudeModel",
table: "ChurchProfiles");
migrationBuilder.DropColumn(
name: "GeminiApiKey",
table: "ChurchProfiles");
migrationBuilder.DropColumn(
name: "GeminiModel",
table: "ChurchProfiles");
}
}
}
@@ -439,6 +439,13 @@ namespace ROLAC.API.Migrations
.HasMaxLength(500) .HasMaxLength(500)
.HasColumnType("character varying(500)"); .HasColumnType("character varying(500)");
b.Property<string>("AiProvider")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(20)
.HasColumnType("character varying(20)")
.HasDefaultValue("Claude");
b.Property<string>("BankAccountNumber") b.Property<string>("BankAccountNumber")
.HasMaxLength(50) .HasMaxLength(50)
.HasColumnType("character varying(50)"); .HasColumnType("character varying(50)");
@@ -455,6 +462,16 @@ namespace ROLAC.API.Migrations
.HasMaxLength(100) .HasMaxLength(100)
.HasColumnType("character varying(100)"); .HasColumnType("character varying(100)");
b.Property<string>("ClaudeApiKey")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("ClaudeModel")
.ValueGeneratedOnAdd()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasDefaultValue("claude-haiku-4-5-20251001");
b.Property<DateTimeOffset>("CreatedAt") b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
@@ -467,6 +484,16 @@ namespace ROLAC.API.Migrations
.HasMaxLength(200) .HasMaxLength(200)
.HasColumnType("character varying(200)"); .HasColumnType("character varying(200)");
b.Property<string>("GeminiApiKey")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("GeminiModel")
.ValueGeneratedOnAdd()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasDefaultValue("gemini-2.5-flash-lite");
b.Property<string>("Name") b.Property<string>("Name")
.IsRequired() .IsRequired()
.HasMaxLength(200) .HasMaxLength(200)