Initial project import
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using MiaoJiZhang.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence;
|
||||
|
||||
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<User> Users => Set<User>();
|
||||
public DbSet<UserFeaturePermission> UserFeaturePermissions => Set<UserFeaturePermission>();
|
||||
public DbSet<AiCompanionSetting> AiCompanionSettings => Set<AiCompanionSetting>();
|
||||
public DbSet<Ledger> Ledgers => Set<Ledger>();
|
||||
public DbSet<Category> Categories => Set<Category>();
|
||||
public DbSet<Transaction> Transactions => Set<Transaction>();
|
||||
public DbSet<Budget> Budgets => Set<Budget>();
|
||||
public DbSet<ChatMessage> ChatMessages => Set<ChatMessage>();
|
||||
public DbSet<AppConfig> AppConfigs => Set<AppConfig>();
|
||||
public DbSet<AiPersona> AiPersonas => Set<AiPersona>();
|
||||
public DbSet<AiAvatar> AiAvatars => Set<AiAvatar>();
|
||||
public DbSet<Sticker> Stickers => Set<Sticker>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder b)
|
||||
{
|
||||
b.Entity<User>(e =>
|
||||
{
|
||||
e.HasIndex(x => x.Username).IsUnique();
|
||||
e.Property(x => x.Username).HasMaxLength(32);
|
||||
e.Property(x => x.Nickname).HasMaxLength(32);
|
||||
// 预留字段索引(唯一但允许 null)
|
||||
e.HasIndex(x => x.Email).IsUnique();
|
||||
e.HasIndex(x => x.Phone).IsUnique();
|
||||
e.HasIndex(x => x.WeChatOpenId).IsUnique();
|
||||
e.HasIndex(x => x.AccountClosureScheduledAt);
|
||||
e.HasOne(x => x.AiCompanion).WithOne(x => x.User)
|
||||
.HasForeignKey<AiCompanionSetting>(x => x.UserId);
|
||||
});
|
||||
|
||||
b.Entity<UserFeaturePermission>(e =>
|
||||
{
|
||||
e.Property(x => x.PermissionKey).HasMaxLength(32);
|
||||
e.HasIndex(x => new { x.UserId, x.PermissionKey }).IsUnique();
|
||||
e.HasOne(x => x.User).WithMany(x => x.FeaturePermissions)
|
||||
.HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
b.Entity<Transaction>(e =>
|
||||
{
|
||||
e.Property(x => x.Amount).HasPrecision(12, 2);
|
||||
e.HasIndex(x => new { x.LedgerId, x.OccurredAt });
|
||||
e.HasIndex(x => new { x.UserId, x.IsDeleted });
|
||||
e.Property(x => x.ClientRequestId).HasMaxLength(64);
|
||||
e.HasIndex(x => new { x.UserId, x.ClientRequestId }).IsUnique();
|
||||
e.HasQueryFilter(x => !x.IsDeleted); // 软删除全局过滤
|
||||
});
|
||||
|
||||
b.Entity<Category>(e => e.Property(x => x.ColorKey).HasMaxLength(32));
|
||||
|
||||
b.Entity<Budget>(e =>
|
||||
{
|
||||
e.Property(x => x.Amount).HasPrecision(12, 2);
|
||||
e.HasIndex(x => new { x.LedgerId, x.Period, x.CategoryId }).IsUnique();
|
||||
});
|
||||
|
||||
b.Entity<ChatMessage>(e => e.HasIndex(x => new { x.UserId, x.CreatedAt }));
|
||||
b.Entity<AppConfig>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
b.Entity<AiPersona>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
b.Entity<AiAvatar>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
b.Entity<Sticker>(e => e.HasIndex(x => x.Key).IsUnique());
|
||||
|
||||
// MySQL DATETIME has no timezone metadata. Preserve stored UTC wall-clock
|
||||
// values and restore DateTimeKind.Utc whenever EF materializes them.
|
||||
var utcDateTimeConverter = new ValueConverter<DateTime, DateTime>(
|
||||
value => value.Kind == DateTimeKind.Local
|
||||
? value.ToUniversalTime()
|
||||
: DateTime.SpecifyKind(value, DateTimeKind.Utc),
|
||||
value => DateTime.SpecifyKind(value, DateTimeKind.Utc));
|
||||
var nullableUtcDateTimeConverter = new ValueConverter<DateTime?, DateTime?>(
|
||||
value => value.HasValue
|
||||
? value.Value.Kind == DateTimeKind.Local
|
||||
? value.Value.ToUniversalTime()
|
||||
: DateTime.SpecifyKind(value.Value, DateTimeKind.Utc)
|
||||
: value,
|
||||
value => value.HasValue
|
||||
? DateTime.SpecifyKind(value.Value, DateTimeKind.Utc)
|
||||
: value);
|
||||
|
||||
foreach (var property in b.Model.GetEntityTypes().SelectMany(entity => entity.GetProperties()))
|
||||
{
|
||||
if (property.ClrType == typeof(DateTime))
|
||||
{
|
||||
property.SetValueConverter(utcDateTimeConverter);
|
||||
}
|
||||
else if (property.ClrType == typeof(DateTime?))
|
||||
{
|
||||
property.SetValueConverter(nullableUtcDateTimeConverter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
using MiaoJiZhang.Domain.Entities;
|
||||
using MiaoJiZhang.Domain.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence;
|
||||
|
||||
/// <summary>启动种子:默认分类、AI 形象/性格、品牌配置</summary>
|
||||
public static class DbSeeder
|
||||
{
|
||||
public static async Task SeedAsync(AppDbContext db)
|
||||
{
|
||||
if (!await db.AiAvatars.AnyAsync())
|
||||
{
|
||||
db.AiAvatars.AddRange(
|
||||
new AiAvatar { Key = "cat", DefaultName = "小账喵", SpeechTic = "喵" },
|
||||
new AiAvatar { Key = "dog", DefaultName = "阿福汪", SpeechTic = "汪" },
|
||||
new AiAvatar { Key = "robot", DefaultName = "账小智", SpeechTic = "" });
|
||||
}
|
||||
|
||||
if (!await db.AiPersonas.AnyAsync())
|
||||
{
|
||||
db.AiPersonas.AddRange(
|
||||
new AiPersona { Key = "sassy_cat", Name = "毒舌猫娘", Description = "嘴上嫌弃,心里关心,乱花钱会被吐槽", SampleLine = "又点外卖?你的钱包已经瘦成纸片了{tic}!", PromptTemplate = "你是用户的记账助手,性格毒舌但关心用户。回复末尾口癖:{tic}。", Version = 1 },
|
||||
new AiPersona { Key = "gentle", Name = "温柔小暖", Description = "永远鼓励你,温柔提醒不施压", SampleLine = "记好啦,偶尔犒劳自己也是应该的呀", PromptTemplate = "你是用户的记账助手,性格温柔鼓励。口癖:{tic}。", Version = 1 },
|
||||
new AiPersona { Key = "strict", Name = "严格管家", Description = "专业理性,盯紧预算,数据说话", SampleLine = "本笔支出使餐饮预算达到 87%,请注意。", PromptTemplate = "你是用户的记账管家,专业理性,用数据说话,不用口癖。", Version = 1 },
|
||||
new AiPersona { Key = "meme", Name = "沙雕损友", Description = "玩梗高手,表情包狂魔,快乐记账", SampleLine = "家人们谁懂啊,他又双叒叕买奶茶了", PromptTemplate = "你是用户的记账损友,爱玩梗爱发表情包。口癖:{tic}。", Version = 1 });
|
||||
}
|
||||
|
||||
if (!await db.Categories.AnyAsync(c => c.UserId == null))
|
||||
{
|
||||
string[,] expense =
|
||||
{
|
||||
{ "餐饮", "food", "coral" },
|
||||
{ "饮品", "cup", "cyan" },
|
||||
{ "购物", "cart", "blue" },
|
||||
{ "交通", "metro", "teal" },
|
||||
{ "住房", "house", "sand" },
|
||||
{ "娱乐", "game", "violet" },
|
||||
{ "医疗", "pill", "red" },
|
||||
{ "学习", "book", "indigo" },
|
||||
{ "服饰", "shirt", "plum" },
|
||||
{ "人情", "gift", "rose" },
|
||||
{ "旅行", "plane", "sky" },
|
||||
{ "其他", "tag", "graphite" },
|
||||
};
|
||||
for (var i = 0; i < expense.GetLength(0); i++)
|
||||
db.Categories.Add(new Category
|
||||
{
|
||||
Type = TransactionType.Expense,
|
||||
Name = expense[i, 0],
|
||||
IconKey = expense[i, 1],
|
||||
ColorKey = expense[i, 2],
|
||||
SortOrder = i,
|
||||
});
|
||||
|
||||
string[,] income =
|
||||
{
|
||||
{ "工资", "money", "mint" },
|
||||
{ "兼职", "briefcase", "forest" },
|
||||
{ "理财", "chart", "navy" },
|
||||
{ "红包", "gift", "orange" },
|
||||
{ "报销", "card", "amber" },
|
||||
{ "奖金", "sparkle", "aqua" },
|
||||
{ "其他", "tag", "lime" },
|
||||
};
|
||||
for (var i = 0; i < income.GetLength(0); i++)
|
||||
db.Categories.Add(new Category
|
||||
{
|
||||
Type = TransactionType.Income,
|
||||
Name = income[i, 0],
|
||||
IconKey = income[i, 1],
|
||||
ColorKey = income[i, 2],
|
||||
SortOrder = i,
|
||||
});
|
||||
}
|
||||
|
||||
if (!await db.Stickers.AnyAsync())
|
||||
{
|
||||
db.Stickers.AddRange(
|
||||
new Sticker { Key = "salary", Label = "发工资啦", GroupKey = "ai_exclusive", TriggerTags = "salary" },
|
||||
new Sticker { Key = "forgive", Label = "求原谅", GroupKey = "ai_exclusive", TriggerTags = "forgive" },
|
||||
new Sticker { Key = "fire", Label = "剁手警告", GroupKey = "ai_exclusive", TriggerTags = "over_budget" },
|
||||
new Sticker { Key = "empty_wallet", Label = "钱包空空", GroupKey = "ai_exclusive" },
|
||||
new Sticker { Key = "angry", Label = "生气", GroupKey = "ai_exclusive" },
|
||||
new Sticker { Key = "happy", Label = "开心", GroupKey = "ai_exclusive" },
|
||||
new Sticker { Key = "treat", Label = "犒劳自己", GroupKey = "classic" },
|
||||
new Sticker { Key = "shopping_joy", Label = "购物狂喜", GroupKey = "classic" });
|
||||
}
|
||||
|
||||
if (!await db.AppConfigs.AnyAsync())
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
db.AppConfigs.AddRange(
|
||||
new AppConfig { Key = "brand.app_name", Value = "记之", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "brand.slogan", Value = "会聊天的记账本 · 让 AI 帮你管钱", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "brand.logo_url", Value = "", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "llm.protocol", Value = "chat_completions", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "llm.base_url", Value = "https://api.openai.com/v1", Version = 1, UpdatedAt = now },
|
||||
|
||||
new AppConfig { Key = "llm.model", Value = "gpt-4o-mini", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "llm.max_tokens", Value = "1024", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "llm.temperature", Value = "0.8", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "limit.daily_ai_messages", Value = "200", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "limit.daily_ai_messages_per_user", Value = "50", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "limit.max_monthly_budget", Value = "99999999", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "feature.ocr_enabled", Value = "true", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "feature.voice_enabled", Value = "true", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "feature.ai_auto_book", Value = "true", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "feature.sticker_enabled", Value = "true", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "system.default_ledger_name", Value = "日常账本", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "system.max_ledgers_per_user", Value = "10", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "feature.screenshot_bookkeeping_enabled", Value = "true", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "permission.default.ai_enabled", Value = "true", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "quota.default_ai_chat_limit", Value = "50", Version = 1, UpdatedAt = now },
|
||||
new AppConfig { Key = "quota.default_ai_chat_period", Value = "day", Version = 1, UpdatedAt = now });
|
||||
}
|
||||
|
||||
var appName = await db.AppConfigs.FirstOrDefaultAsync(config => config.Key == "brand.app_name");
|
||||
if (appName?.Value is "喵记账" or "喵记")
|
||||
{
|
||||
appName.Value = "记之";
|
||||
appName.Version++;
|
||||
appName.UpdatedAt = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
backend/MiaoJiZhang.Infrastructure/Persistence/Migrations/20260720063643_InitialBaseline.Designer.cs
Generated
+548
@@ -0,0 +1,548 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using MiaoJiZhang.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260720063643_InitialBaseline")]
|
||||
partial class InitialBaseline
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiAvatar", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("DefaultName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("SpeechTic")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AiAvatars");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiCompanionSetting", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("AvatarKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("CustomName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PersonaKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("ProactiveLevel")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RoastLevel")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("StickerFrequency")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AiCompanionSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiPersona", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PromptTemplate")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("SampleLine")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Version")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AiPersonas");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AppConfig", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Version")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AppConfigs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Budget", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(12, 2)
|
||||
.HasColumnType("decimal(12,2)");
|
||||
|
||||
b.Property<long?>("CategoryId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("LedgerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Period")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LedgerId", "Period", "CategoryId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Budgets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Category", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("IconKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.ChatMessage", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("Role")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("TransactionId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "CreatedAt");
|
||||
|
||||
b.ToTable("ChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Ledger", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("IconKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsDefault")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<long>("OwnerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Ledgers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Sticker", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("GroupKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TriggerTags")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Stickers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Transaction", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(12, 2)
|
||||
.HasColumnType("decimal(12,2)");
|
||||
|
||||
b.Property<long>("CategoryId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<long>("LedgerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Note")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OccurredAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PaymentMethod")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("SourceChatMessageId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("SourceText")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.HasIndex("LedgerId", "OccurredAt");
|
||||
|
||||
b.HasIndex("UserId", "IsDeleted");
|
||||
|
||||
b.ToTable("Transactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<int>("AppMode")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("AppleUserId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("EmailVerified")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsBanned")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTime?>("LastLoginAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("varchar(32)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("PhoneVerified")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("varchar(32)");
|
||||
|
||||
b.Property<string>("WeChatOpenId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("WeChatUnionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Email")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("WeChatOpenId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiCompanionSetting", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.User", "User")
|
||||
.WithOne("AiCompanion")
|
||||
.HasForeignKey("MiaoJiZhang.Domain.Entities.AiCompanionSetting", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Budget", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.Ledger", "Ledger")
|
||||
.WithMany("Budgets")
|
||||
.HasForeignKey("LedgerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ledger");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Ledger", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.User", "Owner")
|
||||
.WithMany("Ledgers")
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Transaction", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.Ledger", "Ledger")
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("LedgerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
|
||||
b.Navigation("Ledger");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Ledger", b =>
|
||||
{
|
||||
b.Navigation("Budgets");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("AiCompanion");
|
||||
|
||||
b.Navigation("Ledgers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+431
@@ -0,0 +1,431 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialBaseline : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AiAvatars",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Key = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
DefaultName = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
SpeechTic = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ImageUrl = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AiAvatars", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AiPersonas",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Key = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Description = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
SampleLine = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PromptTemplate = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Version = table.Column<int>(type: "int", nullable: false),
|
||||
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AiPersonas", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AppConfigs",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Key = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Value = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Version = table.Column<int>(type: "int", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AppConfigs", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Categories",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: true),
|
||||
Type = table.Column<int>(type: "int", nullable: false),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IconKey = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
SortOrder = table.Column<int>(type: "int", nullable: false),
|
||||
IsDeleted = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Categories", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ChatMessages",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Role = table.Column<int>(type: "int", nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false),
|
||||
Content = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TransactionId = table.Column<long>(type: "bigint", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ChatMessages", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Stickers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Key = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Label = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
ImageUrl = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
GroupKey = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
TriggerTags = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Stickers", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Username = table.Column<string>(type: "varchar(32)", maxLength: 32, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PasswordHash = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Nickname = table.Column<string>(type: "varchar(32)", maxLength: 32, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
AvatarUrl = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Email = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
EmailVerified = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
Phone = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PhoneVerified = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
WeChatOpenId = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
WeChatUnionId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
AppleUserId = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
AppMode = table.Column<int>(type: "int", nullable: false),
|
||||
IsBanned = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
LastLoginAt = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AiCompanionSettings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
AvatarKey = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CustomName = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PersonaKey = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
RoastLevel = table.Column<int>(type: "int", nullable: false),
|
||||
StickerFrequency = table.Column<int>(type: "int", nullable: false),
|
||||
ProactiveLevel = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AiCompanionSettings", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AiCompanionSettings_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Ledgers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
OwnerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IconKey = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsDefault = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Ledgers", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Ledgers_Users_OwnerId",
|
||||
column: x => x.OwnerId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Budgets",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
LedgerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
CategoryId = table.Column<long>(type: "bigint", nullable: true),
|
||||
Period = table.Column<int>(type: "int", nullable: false),
|
||||
Amount = table.Column<decimal>(type: "decimal(12,2)", precision: 12, scale: 2, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Budgets", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Budgets_Ledgers_LedgerId",
|
||||
column: x => x.LedgerId,
|
||||
principalTable: "Ledgers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Transactions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
LedgerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
CategoryId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false),
|
||||
Amount = table.Column<decimal>(type: "decimal(12,2)", precision: 12, scale: 2, nullable: false),
|
||||
Note = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PaymentMethod = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
OccurredAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
Source = table.Column<int>(type: "int", nullable: false),
|
||||
SourceText = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
SourceChatMessageId = table.Column<long>(type: "bigint", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Transactions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Transactions_Categories_CategoryId",
|
||||
column: x => x.CategoryId,
|
||||
principalTable: "Categories",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Transactions_Ledgers_LedgerId",
|
||||
column: x => x.LedgerId,
|
||||
principalTable: "Ledgers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AiAvatars_Key",
|
||||
table: "AiAvatars",
|
||||
column: "Key",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AiCompanionSettings_UserId",
|
||||
table: "AiCompanionSettings",
|
||||
column: "UserId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AiPersonas_Key",
|
||||
table: "AiPersonas",
|
||||
column: "Key",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AppConfigs_Key",
|
||||
table: "AppConfigs",
|
||||
column: "Key",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Budgets_LedgerId_Period_CategoryId",
|
||||
table: "Budgets",
|
||||
columns: new[] { "LedgerId", "Period", "CategoryId" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ChatMessages_UserId_CreatedAt",
|
||||
table: "ChatMessages",
|
||||
columns: new[] { "UserId", "CreatedAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Ledgers_OwnerId",
|
||||
table: "Ledgers",
|
||||
column: "OwnerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Stickers_Key",
|
||||
table: "Stickers",
|
||||
column: "Key",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Transactions_CategoryId",
|
||||
table: "Transactions",
|
||||
column: "CategoryId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Transactions_LedgerId_OccurredAt",
|
||||
table: "Transactions",
|
||||
columns: new[] { "LedgerId", "OccurredAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Transactions_UserId_IsDeleted",
|
||||
table: "Transactions",
|
||||
columns: new[] { "UserId", "IsDeleted" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_Email",
|
||||
table: "Users",
|
||||
column: "Email",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_Phone",
|
||||
table: "Users",
|
||||
column: "Phone",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_Username",
|
||||
table: "Users",
|
||||
column: "Username",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_WeChatOpenId",
|
||||
table: "Users",
|
||||
column: "WeChatOpenId",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AiAvatars");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AiCompanionSettings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AiPersonas");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AppConfigs");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Budgets");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ChatMessages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Stickers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Transactions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Categories");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Ledgers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
using MiaoJiZhang.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations;
|
||||
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260721120000_AccountClosureAndCategoryIcons")]
|
||||
public partial class AccountClosureAndCategoryIcons : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "AccountClosureRequestedAt",
|
||||
table: "Users",
|
||||
type: "datetime(6)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "AccountClosureScheduledAt",
|
||||
table: "Users",
|
||||
type: "datetime(6)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AuthVersion",
|
||||
table: "Users",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_AccountClosureScheduledAt",
|
||||
table: "Users",
|
||||
column: "AccountClosureScheduledAt");
|
||||
|
||||
migrationBuilder.Sql(
|
||||
"UPDATE Categories SET IconKey = 'cart' WHERE IconKey = 'shopping';");
|
||||
migrationBuilder.Sql(
|
||||
"UPDATE Categories SET IconKey = 'metro' WHERE IconKey = 'transport';");
|
||||
migrationBuilder.Sql(
|
||||
"UPDATE Categories SET IconKey = 'house' WHERE IconKey = 'home';");
|
||||
migrationBuilder.Sql(
|
||||
"UPDATE Categories SET IconKey = 'money' WHERE IconKey = 'salary';");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Users_AccountClosureScheduledAt",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AccountClosureRequestedAt",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AccountClosureScheduledAt",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AuthVersion",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
using MiaoJiZhang.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations;
|
||||
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260721173000_CategoryColors")]
|
||||
public partial class CategoryColors : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ColorKey",
|
||||
table: "Categories",
|
||||
type: "varchar(32)",
|
||||
maxLength: 32,
|
||||
nullable: false,
|
||||
defaultValue: "mint");
|
||||
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'coral' WHERE UserId IS NULL AND Type = 0 AND Name = '餐饮';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'cyan' WHERE UserId IS NULL AND Type = 0 AND Name = '饮品';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'blue' WHERE UserId IS NULL AND Type = 0 AND Name = '购物';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'teal' WHERE UserId IS NULL AND Type = 0 AND Name = '交通';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'sand' WHERE UserId IS NULL AND Type = 0 AND Name = '住房';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'violet' WHERE UserId IS NULL AND Type = 0 AND Name = '娱乐';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'red' WHERE UserId IS NULL AND Type = 0 AND Name = '医疗';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'indigo' WHERE UserId IS NULL AND Type = 0 AND Name = '学习';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'plum' WHERE UserId IS NULL AND Type = 0 AND Name = '服饰';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'rose' WHERE UserId IS NULL AND Type = 0 AND Name = '人情';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'sky' WHERE UserId IS NULL AND Type = 0 AND Name = '旅行';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'graphite' WHERE UserId IS NULL AND Type = 0 AND Name = '其他';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'mint' WHERE UserId IS NULL AND Type = 1 AND Name = '工资';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'forest' WHERE UserId IS NULL AND Type = 1 AND Name = '兼职';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'navy' WHERE UserId IS NULL AND Type = 1 AND Name = '理财';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'orange' WHERE UserId IS NULL AND Type = 1 AND Name = '红包';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'amber' WHERE UserId IS NULL AND Type = 1 AND Name = '报销';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'aqua' WHERE UserId IS NULL AND Type = 1 AND Name = '奖金';");
|
||||
migrationBuilder.Sql("UPDATE Categories SET ColorKey = 'lime' WHERE UserId IS NULL AND Type = 1 AND Name = '其他';");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ColorKey",
|
||||
table: "Categories");
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations;
|
||||
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260721200000_AiPermissionsAndRecognitionIdempotency")]
|
||||
public partial class AiPermissionsAndRecognitionIdempotency : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ClientRequestId",
|
||||
table: "Transactions",
|
||||
type: "varchar(64)",
|
||||
maxLength: 64,
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserFeaturePermissions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<long>(type: "bigint", nullable: false),
|
||||
PermissionKey = table.Column<string>(type: "varchar(32)", maxLength: 32, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UserFeaturePermissions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_UserFeaturePermissions_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Transactions_UserId_ClientRequestId",
|
||||
table: "Transactions",
|
||||
columns: new[] { "UserId", "ClientRequestId" },
|
||||
unique: true);
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserFeaturePermissions_UserId_PermissionKey",
|
||||
table: "UserFeaturePermissions",
|
||||
columns: new[] { "UserId", "PermissionKey" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO UserFeaturePermissions
|
||||
(UserId, PermissionKey, IsEnabled, CreatedAt, UpdatedAt)
|
||||
SELECT Id, 'ai', TRUE, UTC_TIMESTAMP(6), UTC_TIMESTAMP(6)
|
||||
FROM Users
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM UserFeaturePermissions p
|
||||
WHERE p.UserId = Users.Id AND p.PermissionKey = 'ai'
|
||||
);
|
||||
""");
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO AppConfigs (`Key`, Value, Version, UpdatedAt)
|
||||
SELECT 'permission.default.ai_enabled', 'true', 1, UTC_TIMESTAMP(6)
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM AppConfigs
|
||||
WHERE `Key` = 'permission.default.ai_enabled'
|
||||
);
|
||||
""");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(name: "UserFeaturePermissions");
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Transactions_UserId_ClientRequestId",
|
||||
table: "Transactions");
|
||||
migrationBuilder.DropColumn(name: "ClientRequestId", table: "Transactions");
|
||||
migrationBuilder.Sql(
|
||||
"DELETE FROM AppConfigs WHERE `Key` = 'permission.default.ai_enabled';");
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations;
|
||||
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260722030000_AiChatQuotas")]
|
||||
public partial class AiChatQuotas : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AiChatLimit",
|
||||
table: "Users",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 50);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AiChatPeriod",
|
||||
table: "Users",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AiChatUsed",
|
||||
table: "Users",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "AiChatWindowStartedAt",
|
||||
table: "Users",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1970, 1, 1));
|
||||
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE Users
|
||||
SET AiChatWindowStartedAt =
|
||||
CONVERT_TZ(DATE(CONVERT_TZ(UTC_TIMESTAMP(6), '+00:00', '+08:00')), '+08:00', '+00:00');
|
||||
""");
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO AppConfigs (`Key`, Value, Version, UpdatedAt)
|
||||
SELECT 'quota.default_ai_chat_limit', '50', 1, UTC_TIMESTAMP(6)
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM AppConfigs
|
||||
WHERE `Key` = 'quota.default_ai_chat_limit'
|
||||
);
|
||||
""");
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO AppConfigs (`Key`, Value, Version, UpdatedAt)
|
||||
SELECT 'quota.default_ai_chat_period', 'day', 1, UTC_TIMESTAMP(6)
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM AppConfigs
|
||||
WHERE `Key` = 'quota.default_ai_chat_period'
|
||||
);
|
||||
""");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(name: "AiChatLimit", table: "Users");
|
||||
migrationBuilder.DropColumn(name: "AiChatPeriod", table: "Users");
|
||||
migrationBuilder.DropColumn(name: "AiChatUsed", table: "Users");
|
||||
migrationBuilder.DropColumn(name: "AiChatWindowStartedAt", table: "Users");
|
||||
migrationBuilder.Sql(
|
||||
"DELETE FROM AppConfigs WHERE `Key` IN ('quota.default_ai_chat_limit', 'quota.default_ai_chat_period');");
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations;
|
||||
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20260722040000_RepairRecognitionTimestamps")]
|
||||
public partial class RepairRecognitionTimestamps : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE Transactions
|
||||
SET OccurredAt = CreatedAt
|
||||
WHERE Source IN (5, 6, 7)
|
||||
AND OccurredAt < '2000-01-01 00:00:00';
|
||||
""");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
}
|
||||
}
|
||||
+627
@@ -0,0 +1,627 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using MiaoJiZhang.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MiaoJiZhang.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
partial class AppDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiAvatar", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("DefaultName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("SpeechTic")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AiAvatars");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiCompanionSetting", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("AvatarKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("CustomName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PersonaKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("ProactiveLevel")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RoastLevel")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("StickerFrequency")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AiCompanionSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiPersona", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PromptTemplate")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("SampleLine")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Version")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AiPersonas");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AppConfig", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Version")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AppConfigs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Budget", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(12, 2)
|
||||
.HasColumnType("decimal(12,2)");
|
||||
|
||||
b.Property<long?>("CategoryId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("LedgerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Period")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LedgerId", "Period", "CategoryId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Budgets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Category", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("ColorKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("varchar(32)");
|
||||
|
||||
b.Property<string>("IconKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.ChatMessage", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("Role")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("TransactionId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "CreatedAt");
|
||||
|
||||
b.ToTable("ChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Ledger", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("IconKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsDefault")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<long>("OwnerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Ledgers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Sticker", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("GroupKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("TriggerTags")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Stickers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Transaction", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(12, 2)
|
||||
.HasColumnType("decimal(12,2)");
|
||||
|
||||
b.Property<long>("CategoryId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("ClientRequestId")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("varchar(64)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<long>("LedgerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Note")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OccurredAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PaymentMethod")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<long?>("SourceChatMessageId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("SourceText")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.HasIndex("LedgerId", "OccurredAt");
|
||||
|
||||
b.HasIndex("UserId", "IsDeleted");
|
||||
|
||||
b.HasIndex("UserId", "ClientRequestId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Transactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.UserFeaturePermission", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("PermissionKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("varchar(32)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<long>("UserId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "PermissionKey")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("UserFeaturePermissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<int>("AppMode")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("AiChatLimit")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("AiChatPeriod")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("AiChatUsed")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("AiChatWindowStartedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<DateTime?>("AccountClosureRequestedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<DateTime?>("AccountClosureScheduledAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("AppleUserId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("EmailVerified")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("AuthVersion")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IsBanned")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTime?>("LastLoginAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("varchar(32)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<bool>("PhoneVerified")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("varchar(32)");
|
||||
|
||||
b.Property<string>("WeChatOpenId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("WeChatUnionId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountClosureScheduledAt");
|
||||
|
||||
b.HasIndex("Email")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("WeChatOpenId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.AiCompanionSetting", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.User", "User")
|
||||
.WithOne("AiCompanion")
|
||||
.HasForeignKey("MiaoJiZhang.Domain.Entities.AiCompanionSetting", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Budget", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.Ledger", "Ledger")
|
||||
.WithMany("Budgets")
|
||||
.HasForeignKey("LedgerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ledger");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Ledger", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.User", "Owner")
|
||||
.WithMany("Ledgers")
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Transaction", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.Ledger", "Ledger")
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("LedgerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
|
||||
b.Navigation("Ledger");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.UserFeaturePermission", b =>
|
||||
{
|
||||
b.HasOne("MiaoJiZhang.Domain.Entities.User", "User")
|
||||
.WithMany("FeaturePermissions")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.Ledger", b =>
|
||||
{
|
||||
b.Navigation("Budgets");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MiaoJiZhang.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("AiCompanion");
|
||||
|
||||
b.Navigation("FeaturePermissions");
|
||||
|
||||
b.Navigation("Ledgers");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user