From 489f02cb5fc19357e69711c26a52bf4b4ba850eb Mon Sep 17 00:00:00 2001 From: movingsam Date: Wed, 18 Feb 2026 23:34:40 +0800 Subject: [PATCH] refactor: clean up Member module and update Console - Remove redundant PointsRule repositories (use single PointsRuleRepository) - Clean up Member migrations and consolidate to single Init migration - Update Console frontend API and components for Tenant - Add H5LinkService for member H5 integration --- .../Services/PointsProcessingService.cs | 3 - .../Services/PointsRuleMatcher.cs | 2 +- .../IPointsRuleConditionRepository.cs | 10 - .../Repositories/IPointsRuleRepository.cs | 15 - .../DesignTimeApplicationDbContextFactory.cs | 2 +- .../20260122054728_Init.Designer.cs | 140 ---- .../Migrations/20260122054728_Init.cs | 101 --- ...658_AddMemberAndPointsEntities.Designer.cs | 429 ------------- ...260205051658_AddMemberAndPointsEntities.cs | 208 ------ ...0209110951_AddPointsRuleSystem.Designer.cs | 598 ------------------ .../20260209110951_AddPointsRuleSystem.cs | 206 ------ .../20260209163416_ChangeMemberIdToGuid.cs | 72 --- ...ner.cs => 20260217154010_Init.Designer.cs} | 35 +- .../Migrations/20260217154010_Init.cs | 390 ++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 31 +- .../Repositories/IPointsHistoryRepository.cs | 38 -- .../PointsRuleConditionRepository.cs | 32 - .../Repositories/PointsRuleRepository.cs | 44 +- .../1ling.Member.Infrastructure | 1 + .../Endpoints/v1/PointsEndpoints.cs | 14 +- .../Endpoints/v1/PointsRuleEndpoints.cs | 15 +- src/Fengling.Member.Web/Program.cs | 24 +- .../appsettings.Development.json | 2 +- 23 files changed, 482 insertions(+), 1930 deletions(-) delete mode 100644 src/Fengling.Member.Domain/Repositories/IPointsRuleConditionRepository.cs delete mode 100644 src/Fengling.Member.Domain/Repositories/IPointsRuleRepository.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.Designer.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.Designer.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.Designer.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.cs delete mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.cs rename src/Fengling.Member.Infrastructure/Migrations/{20260209163416_ChangeMemberIdToGuid.Designer.cs => 20260217154010_Init.Designer.cs} (96%) create mode 100644 src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.cs delete mode 100644 src/Fengling.Member.Infrastructure/Repositories/IPointsHistoryRepository.cs delete mode 100644 src/Fengling.Member.Infrastructure/Repositories/PointsRuleConditionRepository.cs create mode 100644 src/Fengling.Member.Web/1ling.Member.Infrastructure diff --git a/src/Fengling.Member.Application/Services/PointsProcessingService.cs b/src/Fengling.Member.Application/Services/PointsProcessingService.cs index 1181ca1..c0418d2 100644 --- a/src/Fengling.Member.Application/Services/PointsProcessingService.cs +++ b/src/Fengling.Member.Application/Services/PointsProcessingService.cs @@ -13,7 +13,6 @@ public class PointsProcessingService : IPointsProcessingService { private readonly IPointsAccountCache _cache; private readonly ICodeDistributedLock _lock; - private readonly IPointsHistoryRepository _historyRepository; private readonly IMediator _mediator; private readonly ITenantAccessor _tenantAccessor; private readonly ILogger _logger; @@ -21,14 +20,12 @@ public class PointsProcessingService : IPointsProcessingService public PointsProcessingService( IPointsAccountCache cache, ICodeDistributedLock distributedLock, - IPointsHistoryRepository historyRepository, IMediator mediator, ITenantAccessor tenantAccessor, ILogger logger) { _cache = cache; _lock = distributedLock; - _historyRepository = historyRepository; _mediator = mediator; _tenantAccessor = tenantAccessor; _logger = logger; diff --git a/src/Fengling.Member.Application/Services/PointsRuleMatcher.cs b/src/Fengling.Member.Application/Services/PointsRuleMatcher.cs index d7de4a1..7bd4176 100644 --- a/src/Fengling.Member.Application/Services/PointsRuleMatcher.cs +++ b/src/Fengling.Member.Application/Services/PointsRuleMatcher.cs @@ -1,7 +1,7 @@ using Fengling.Member.Application.Dtos; using Fengling.Member.Domain.Aggregates.PointsRuleModel; using Fengling.Member.Domain.Aggregates.PointsRuleModel.Enums; -using Fengling.Member.Domain.Repositories; +using Fengling.Member.Infrastructure.Repositories; using NetCorePal.Extensions.Domain; namespace Fengling.Member.Application.Services; diff --git a/src/Fengling.Member.Domain/Repositories/IPointsRuleConditionRepository.cs b/src/Fengling.Member.Domain/Repositories/IPointsRuleConditionRepository.cs deleted file mode 100644 index 9317aa3..0000000 --- a/src/Fengling.Member.Domain/Repositories/IPointsRuleConditionRepository.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Fengling.Member.Domain.Aggregates.PointsRuleModel; - -namespace Fengling.Member.Domain.Repositories; - -public interface IPointsRuleConditionRepository -{ - Task> GetByRuleIdAsync(PointsRuleId ruleId); - Task AddAsync(PointsRuleCondition condition); - Task DeleteByRuleIdAsync(PointsRuleId ruleId); -} diff --git a/src/Fengling.Member.Domain/Repositories/IPointsRuleRepository.cs b/src/Fengling.Member.Domain/Repositories/IPointsRuleRepository.cs deleted file mode 100644 index 5af3632..0000000 --- a/src/Fengling.Member.Domain/Repositories/IPointsRuleRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Fengling.Member.Domain.Aggregates.PointsRuleModel; -using Fengling.Member.Domain.Aggregates.PointsRuleModel.Enums; - -namespace Fengling.Member.Domain.Repositories; - -public interface IPointsRuleRepository -{ - Task GetByIdAsync(PointsRuleId id); - Task GetByCodeAsync(string code); - Task> GetActiveRulesAsync(); - Task> GetActiveRulesByDimensionAsync(DimensionType dimensionType, string dimensionValue); - Task AddAsync(PointsRule rule); - Task UpdateAsync(PointsRule rule); - Task DeleteAsync(PointsRuleId id); -} diff --git a/src/Fengling.Member.Infrastructure/DesignTimeApplicationDbContextFactory.cs b/src/Fengling.Member.Infrastructure/DesignTimeApplicationDbContextFactory.cs index 7dec12c..f98e4f8 100644 --- a/src/Fengling.Member.Infrastructure/DesignTimeApplicationDbContextFactory.cs +++ b/src/Fengling.Member.Infrastructure/DesignTimeApplicationDbContextFactory.cs @@ -14,7 +14,7 @@ public class DesignTimeApplicationDbContextFactory: IDesignTimeDbContextFactory< services.AddDbContext(options => { // change connectionstring if you want to run command “dotnet ef database update” - options.UseNpgsql("Host=any;Database=any;Username=any;Password=any", + options.UseNpgsql("Host=192.168.100.10;Database=fengling_member;Username=movingsam;Password=sl52788542", b => { b.MigrationsAssembly(typeof(DesignTimeApplicationDbContextFactory).Assembly.FullName); diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.Designer.cs b/src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.Designer.cs deleted file mode 100644 index 2a1a3f5..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.Designer.cs +++ /dev/null @@ -1,140 +0,0 @@ -// -using System; -using Fengling.Member.Infrastructure; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260122054728_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.CapLock", b => - { - b.Property("Key") - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Instance") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("LastLockTime") - .HasColumnType("TIMESTAMP"); - - b.HasKey("Key"); - - b.ToTable("CAPLock", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.PublishedMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Added") - .HasColumnType("TIMESTAMP"); - - b.Property("Content") - .HasColumnType("TEXT"); - - b.Property("ExpiresAt") - .HasColumnType("TIMESTAMP"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Retries") - .HasColumnType("integer"); - - b.Property("StatusName") - .IsRequired() - .HasMaxLength(40) - .HasColumnType("character varying(40)"); - - b.Property("Version") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("Id"); - - b.HasIndex(new[] { "ExpiresAt", "StatusName" }, "IX_ExpiresAt_StatusName"); - - b.HasIndex(new[] { "Version", "ExpiresAt", "StatusName" }, "IX_Version_ExpiresAt_StatusName"); - - b.ToTable("CAPPublishedMessage", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.ReceivedMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Added") - .HasColumnType("TIMESTAMP"); - - b.Property("Content") - .HasColumnType("TEXT"); - - b.Property("ExpiresAt") - .HasColumnType("TIMESTAMP"); - - b.Property("Group") - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("character varying(400)"); - - b.Property("Retries") - .HasColumnType("integer"); - - b.Property("StatusName") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("Version") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("Id"); - - b.HasIndex(new[] { "ExpiresAt", "StatusName" }, "IX_ExpiresAt_StatusName") - .HasDatabaseName("IX_ExpiresAt_StatusName1"); - - b.HasIndex(new[] { "Version", "ExpiresAt", "StatusName" }, "IX_Version_ExpiresAt_StatusName") - .HasDatabaseName("IX_Version_ExpiresAt_StatusName1"); - - b.ToTable("CAPReceivedMessage", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.cs b/src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.cs deleted file mode 100644 index f4b513e..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260122054728_Init.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - /// - public partial class Init : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "CAPLock", - columns: table => new - { - Key = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), - Instance = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), - LastLockTime = table.Column(type: "TIMESTAMP", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_CAPLock", x => x.Key); - }); - - migrationBuilder.CreateTable( - name: "CAPPublishedMessage", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Version = table.Column(type: "character varying(20)", maxLength: 20, nullable: true), - Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), - Content = table.Column(type: "TEXT", nullable: true), - Retries = table.Column(type: "integer", nullable: true), - Added = table.Column(type: "TIMESTAMP", nullable: false), - ExpiresAt = table.Column(type: "TIMESTAMP", nullable: true), - StatusName = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CAPPublishedMessage", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "CAPReceivedMessage", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Version = table.Column(type: "character varying(20)", maxLength: 20, nullable: true), - Name = table.Column(type: "character varying(400)", maxLength: 400, nullable: false), - Group = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), - Content = table.Column(type: "TEXT", nullable: true), - Retries = table.Column(type: "integer", nullable: true), - Added = table.Column(type: "TIMESTAMP", nullable: false), - ExpiresAt = table.Column(type: "TIMESTAMP", nullable: true), - StatusName = table.Column(type: "character varying(50)", maxLength: 50, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CAPReceivedMessage", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_ExpiresAt_StatusName", - table: "CAPPublishedMessage", - columns: new[] { "ExpiresAt", "StatusName" }); - - migrationBuilder.CreateIndex( - name: "IX_Version_ExpiresAt_StatusName", - table: "CAPPublishedMessage", - columns: new[] { "Version", "ExpiresAt", "StatusName" }); - - migrationBuilder.CreateIndex( - name: "IX_ExpiresAt_StatusName1", - table: "CAPReceivedMessage", - columns: new[] { "ExpiresAt", "StatusName" }); - - migrationBuilder.CreateIndex( - name: "IX_Version_ExpiresAt_StatusName1", - table: "CAPReceivedMessage", - columns: new[] { "Version", "ExpiresAt", "StatusName" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "CAPLock"); - - migrationBuilder.DropTable( - name: "CAPPublishedMessage"); - - migrationBuilder.DropTable( - name: "CAPReceivedMessage"); - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.Designer.cs b/src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.Designer.cs deleted file mode 100644 index a3cdd7f..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.Designer.cs +++ /dev/null @@ -1,429 +0,0 @@ -// -using System; -using Fengling.Member.Infrastructure; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260205051658_AddMemberAndPointsEntities")] - partial class AddMemberAndPointsEntities - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("FrozenPoints") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasColumnName("frozen_points"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasColumnName("tenant_id"); - - b.Property("TotalPoints") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasColumnName("points"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(1) - .HasColumnName("version"); - - b.HasKey("Id"); - - b.HasIndex("MemberId") - .IsUnique() - .HasDatabaseName("idx_points_account_memberid"); - - b.HasIndex("MemberId", "TenantId") - .HasDatabaseName("idx_points_account_member_tenant"); - - b.ToTable("mka_integraldetails", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("MemberId") - .HasColumnType("bigint"); - - b.Property("Points") - .HasColumnType("integer"); - - b.Property("PointsAccountId") - .HasColumnType("bigint"); - - b.Property("Remark") - .HasColumnType("text"); - - b.Property("SourceId") - .IsRequired() - .HasColumnType("text"); - - b.Property("TransactionType") - .IsRequired() - .HasColumnType("text"); - - b.Property("TransactionTypeCategory") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.HasIndex("PointsAccountId"); - - b.ToTable("PointsTransaction"); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("OpenId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("open_id"); - - b.Property("PhoneNumber") - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasColumnName("phone_number"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasColumnName("status"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasColumnName("tenant_id"); - - b.Property("UnionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("union_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(1) - .HasColumnName("version"); - - b.HasKey("Id"); - - b.HasIndex("OpenId") - .HasDatabaseName("idx_member_openid"); - - b.HasIndex("TenantId") - .HasDatabaseName("idx_member_tenantid"); - - b.HasIndex("UnionId") - .HasDatabaseName("idx_member_unionid"); - - b.HasIndex("TenantId", "PhoneNumber") - .HasDatabaseName("idx_member_tenant_phone"); - - b.ToTable("fls_member", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberTag", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("member_id"); - - b.Property("TagId") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasColumnName("tag_id"); - - b.Property("TagName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("tag_name"); - - b.HasKey("Id"); - - b.HasIndex("TagId") - .HasDatabaseName("idx_membertag_tagid"); - - b.HasIndex("MemberId", "TagId") - .IsUnique() - .HasDatabaseName("idx_membertag_member_tag"); - - b.ToTable("fls_member_tag", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.WechatAuthorization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorizedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("authorized_at"); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("last_login_at"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("member_id"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("open_id"); - - b.Property("UnionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("union_id"); - - b.HasKey("Id"); - - b.HasIndex("MemberId") - .HasDatabaseName("idx_wechat_auth_memberid"); - - b.HasIndex("OpenId") - .IsUnique() - .HasDatabaseName("idx_wechat_auth_openid"); - - b.HasIndex("UnionId") - .HasDatabaseName("idx_wechat_auth_unionid"); - - b.ToTable("fls_wechat_authorization", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.CapLock", b => - { - b.Property("Key") - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Instance") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("LastLockTime") - .HasColumnType("TIMESTAMP"); - - b.HasKey("Key"); - - b.ToTable("CAPLock", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.PublishedMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Added") - .HasColumnType("TIMESTAMP"); - - b.Property("Content") - .HasColumnType("TEXT"); - - b.Property("ExpiresAt") - .HasColumnType("TIMESTAMP"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Retries") - .HasColumnType("integer"); - - b.Property("StatusName") - .IsRequired() - .HasMaxLength(40) - .HasColumnType("character varying(40)"); - - b.Property("Version") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("Id"); - - b.HasIndex(new[] { "ExpiresAt", "StatusName" }, "IX_ExpiresAt_StatusName"); - - b.HasIndex(new[] { "Version", "ExpiresAt", "StatusName" }, "IX_Version_ExpiresAt_StatusName"); - - b.ToTable("CAPPublishedMessage", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.ReceivedMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Added") - .HasColumnType("TIMESTAMP"); - - b.Property("Content") - .HasColumnType("TEXT"); - - b.Property("ExpiresAt") - .HasColumnType("TIMESTAMP"); - - b.Property("Group") - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("character varying(400)"); - - b.Property("Retries") - .HasColumnType("integer"); - - b.Property("StatusName") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("Version") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("Id"); - - b.HasIndex(new[] { "ExpiresAt", "StatusName" }, "IX_ExpiresAt_StatusName") - .HasDatabaseName("IX_ExpiresAt_StatusName1"); - - b.HasIndex(new[] { "Version", "ExpiresAt", "StatusName" }, "IX_Version_ExpiresAt_StatusName") - .HasDatabaseName("IX_Version_ExpiresAt_StatusName1"); - - b.ToTable("CAPReceivedMessage", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsTransaction", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", null) - .WithMany("Transactions") - .HasForeignKey("PointsAccountId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberTag", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.Users.MemberEntity", null) - .WithMany("Tags") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.WechatAuthorization", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.Users.MemberEntity", null) - .WithMany("WechatAuthorizations") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", b => - { - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberEntity", b => - { - b.Navigation("Tags"); - - b.Navigation("WechatAuthorizations"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.cs b/src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.cs deleted file mode 100644 index 7fd7107..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260205051658_AddMemberAndPointsEntities.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - /// - public partial class AddMemberAndPointsEntities : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "fls_member", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - tenant_id = table.Column(type: "bigint", nullable: false), - phone_number = table.Column(type: "character varying(20)", maxLength: 20, nullable: true), - open_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), - union_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), - status = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), - created_at = table.Column(type: "timestamp with time zone", nullable: false), - updated_at = table.Column(type: "timestamp with time zone", nullable: true), - version = table.Column(type: "integer", nullable: false, defaultValue: 1) - }, - constraints: table => - { - table.PrimaryKey("PK_fls_member", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "mka_integraldetails", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - user_id = table.Column(type: "bigint", nullable: false), - tenant_id = table.Column(type: "bigint", nullable: false), - points = table.Column(type: "integer", nullable: false, defaultValue: 0), - frozen_points = table.Column(type: "integer", nullable: false, defaultValue: 0), - version = table.Column(type: "integer", nullable: false, defaultValue: 1), - created_at = table.Column(type: "timestamp with time zone", nullable: false), - updated_at = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_mka_integraldetails", x => x.id); - }); - - migrationBuilder.CreateTable( - name: "fls_member_tag", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - member_id = table.Column(type: "bigint", nullable: false), - tag_id = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), - tag_name = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), - created_at = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_fls_member_tag", x => x.id); - table.ForeignKey( - name: "FK_fls_member_tag_fls_member_member_id", - column: x => x.member_id, - principalTable: "fls_member", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "fls_wechat_authorization", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - member_id = table.Column(type: "bigint", nullable: false), - open_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), - union_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), - authorized_at = table.Column(type: "timestamp with time zone", nullable: false), - last_login_at = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_fls_wechat_authorization", x => x.id); - table.ForeignKey( - name: "FK_fls_wechat_authorization_fls_member_member_id", - column: x => x.member_id, - principalTable: "fls_member", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "PointsTransaction", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - PointsAccountId = table.Column(type: "bigint", nullable: false), - MemberId = table.Column(type: "bigint", nullable: false), - Points = table.Column(type: "integer", nullable: false), - TransactionType = table.Column(type: "text", nullable: false), - SourceId = table.Column(type: "text", nullable: false), - TransactionTypeCategory = table.Column(type: "integer", nullable: false), - Remark = table.Column(type: "text", nullable: true), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PointsTransaction", x => x.Id); - table.ForeignKey( - name: "FK_PointsTransaction_mka_integraldetails_PointsAccountId", - column: x => x.PointsAccountId, - principalTable: "mka_integraldetails", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "idx_member_openid", - table: "fls_member", - column: "open_id"); - - migrationBuilder.CreateIndex( - name: "idx_member_tenant_phone", - table: "fls_member", - columns: new[] { "tenant_id", "phone_number" }); - - migrationBuilder.CreateIndex( - name: "idx_member_tenantid", - table: "fls_member", - column: "tenant_id"); - - migrationBuilder.CreateIndex( - name: "idx_member_unionid", - table: "fls_member", - column: "union_id"); - - migrationBuilder.CreateIndex( - name: "idx_membertag_member_tag", - table: "fls_member_tag", - columns: new[] { "member_id", "tag_id" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "idx_membertag_tagid", - table: "fls_member_tag", - column: "tag_id"); - - migrationBuilder.CreateIndex( - name: "idx_wechat_auth_memberid", - table: "fls_wechat_authorization", - column: "member_id"); - - migrationBuilder.CreateIndex( - name: "idx_wechat_auth_openid", - table: "fls_wechat_authorization", - column: "open_id", - unique: true); - - migrationBuilder.CreateIndex( - name: "idx_wechat_auth_unionid", - table: "fls_wechat_authorization", - column: "union_id"); - - migrationBuilder.CreateIndex( - name: "idx_points_account_member_tenant", - table: "mka_integraldetails", - columns: new[] { "user_id", "tenant_id" }); - - migrationBuilder.CreateIndex( - name: "idx_points_account_memberid", - table: "mka_integraldetails", - column: "user_id", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_PointsTransaction_PointsAccountId", - table: "PointsTransaction", - column: "PointsAccountId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "fls_member_tag"); - - migrationBuilder.DropTable( - name: "fls_wechat_authorization"); - - migrationBuilder.DropTable( - name: "PointsTransaction"); - - migrationBuilder.DropTable( - name: "fls_member"); - - migrationBuilder.DropTable( - name: "mka_integraldetails"); - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.Designer.cs b/src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.Designer.cs deleted file mode 100644 index 0174790..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.Designer.cs +++ /dev/null @@ -1,598 +0,0 @@ -// -using System; -using Fengling.Member.Infrastructure; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20260209110951_AddPointsRuleSystem")] - partial class AddPointsRuleSystem - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("FrozenPoints") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasColumnName("frozen_points"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasColumnName("tenant_id"); - - b.Property("TotalPoints") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(0) - .HasColumnName("points"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(1) - .HasColumnName("version"); - - b.HasKey("Id"); - - b.HasIndex("MemberId") - .IsUnique() - .HasDatabaseName("idx_points_account_memberid"); - - b.HasIndex("MemberId", "TenantId") - .HasDatabaseName("idx_points_account_member_tenant"); - - b.ToTable("mka_integraldetails", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ExpireAt") - .HasColumnType("timestamp with time zone"); - - b.Property("MemberId") - .HasColumnType("bigint"); - - b.Property("Points") - .HasColumnType("integer"); - - b.Property("PointsAccountId") - .HasColumnType("bigint"); - - b.Property("Remark") - .HasColumnType("text"); - - b.Property("SourceId") - .IsRequired() - .HasColumnType("text"); - - b.Property("TransactionType") - .IsRequired() - .HasColumnType("text"); - - b.Property("TransactionTypeCategory") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.HasIndex("PointsAccountId"); - - b.ToTable("PointsTransactions"); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsRuleModel.PointsRule", b => - { - b.Property("Id") - .HasColumnType("uuid") - .HasComment("规则标识"); - - b.Property("BasePoints") - .HasColumnType("integer") - .HasComment("基础积分"); - - b.Property("CalculationMode") - .HasColumnType("integer") - .HasComment("计算模式"); - - b.Property("Code") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasComment("规则编码"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间"); - - b.Property("EffectiveFrom") - .HasColumnType("timestamp with time zone") - .HasComment("生效开始时间"); - - b.Property("EffectiveTo") - .HasColumnType("timestamp with time zone") - .HasComment("生效结束时间"); - - b.Property("IsActive") - .HasColumnType("boolean") - .HasComment("是否启用"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)") - .HasComment("规则名称"); - - b.Property("Priority") - .HasColumnType("integer") - .HasComment("优先级"); - - b.Property("RuleType") - .HasColumnType("integer") - .HasComment("规则类型"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("更新时间"); - - b.Property("ValidityDays") - .HasColumnType("integer") - .HasComment("有效期天数"); - - b.Property("WeightFactor") - .HasPrecision(18, 4) - .HasColumnType("numeric(18,4)") - .HasComment("权重因子"); - - b.HasKey("Id"); - - b.HasIndex("Code") - .IsUnique(); - - b.HasIndex("IsActive"); - - b.ToTable("PointsRules", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsRuleModel.PointsRuleCondition", b => - { - b.Property("Id") - .HasColumnType("uuid") - .HasComment("条件标识"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasComment("创建时间"); - - b.Property("DimensionType") - .HasColumnType("integer") - .HasComment("维度类型"); - - b.Property("DimensionValue") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)") - .HasComment("维度值"); - - b.Property("Operator") - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasComment("操作符"); - - b.Property("RuleId") - .HasColumnType("uuid") - .HasComment("关联规则标识"); - - b.HasKey("Id"); - - b.HasIndex("RuleId", "DimensionType"); - - b.ToTable("PointsRuleConditions", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("OpenId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("open_id"); - - b.Property("PhoneNumber") - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasColumnName("phone_number"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)") - .HasColumnName("status"); - - b.Property("TenantId") - .HasColumnType("bigint") - .HasColumnName("tenant_id"); - - b.Property("UnionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("union_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasDefaultValue(1) - .HasColumnName("version"); - - b.HasKey("Id"); - - b.HasIndex("OpenId") - .HasDatabaseName("idx_member_openid"); - - b.HasIndex("TenantId") - .HasDatabaseName("idx_member_tenantid"); - - b.HasIndex("UnionId") - .HasDatabaseName("idx_member_unionid"); - - b.HasIndex("TenantId", "PhoneNumber") - .HasDatabaseName("idx_member_tenant_phone"); - - b.ToTable("fls_member", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberTag", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("member_id"); - - b.Property("TagId") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)") - .HasColumnName("tag_id"); - - b.Property("TagName") - .HasMaxLength(100) - .HasColumnType("character varying(100)") - .HasColumnName("tag_name"); - - b.HasKey("Id"); - - b.HasIndex("TagId") - .HasDatabaseName("idx_membertag_tagid"); - - b.HasIndex("MemberId", "TagId") - .IsUnique() - .HasDatabaseName("idx_membertag_member_tag"); - - b.ToTable("fls_member_tag", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.OAuthAuthorization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AccessToken") - .HasColumnType("text"); - - b.Property("AuthorizedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone"); - - b.Property("MemberId") - .HasColumnType("bigint"); - - b.Property("OpenId") - .IsRequired() - .HasColumnType("text"); - - b.Property("Provider") - .HasColumnType("integer"); - - b.Property("RefreshToken") - .HasColumnType("text"); - - b.Property("TokenExpiredAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UnionId") - .HasColumnType("text"); - - b.HasKey("Id"); - - b.HasIndex("MemberId"); - - b.ToTable("OAuthAuthorization"); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.WechatAuthorization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AuthorizedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("authorized_at"); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("last_login_at"); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("member_id"); - - b.Property("OpenId") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("open_id"); - - b.Property("UnionId") - .HasMaxLength(64) - .HasColumnType("character varying(64)") - .HasColumnName("union_id"); - - b.HasKey("Id"); - - b.HasIndex("MemberId") - .HasDatabaseName("idx_wechat_auth_memberid"); - - b.HasIndex("OpenId") - .IsUnique() - .HasDatabaseName("idx_wechat_auth_openid"); - - b.HasIndex("UnionId") - .HasDatabaseName("idx_wechat_auth_unionid"); - - b.ToTable("fls_wechat_authorization", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.CapLock", b => - { - b.Property("Key") - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Instance") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("LastLockTime") - .HasColumnType("TIMESTAMP"); - - b.HasKey("Key"); - - b.ToTable("CAPLock", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.PublishedMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Added") - .HasColumnType("TIMESTAMP"); - - b.Property("Content") - .HasColumnType("TEXT"); - - b.Property("ExpiresAt") - .HasColumnType("TIMESTAMP"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Retries") - .HasColumnType("integer"); - - b.Property("StatusName") - .IsRequired() - .HasMaxLength(40) - .HasColumnType("character varying(40)"); - - b.Property("Version") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("Id"); - - b.HasIndex(new[] { "ExpiresAt", "StatusName" }, "IX_ExpiresAt_StatusName"); - - b.HasIndex(new[] { "Version", "ExpiresAt", "StatusName" }, "IX_Version_ExpiresAt_StatusName"); - - b.ToTable("CAPPublishedMessage", (string)null); - }); - - modelBuilder.Entity("NetCorePal.Extensions.DistributedTransactions.CAP.Persistence.ReceivedMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Added") - .HasColumnType("TIMESTAMP"); - - b.Property("Content") - .HasColumnType("TEXT"); - - b.Property("ExpiresAt") - .HasColumnType("TIMESTAMP"); - - b.Property("Group") - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(400) - .HasColumnType("character varying(400)"); - - b.Property("Retries") - .HasColumnType("integer"); - - b.Property("StatusName") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("Version") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("Id"); - - b.HasIndex(new[] { "ExpiresAt", "StatusName" }, "IX_ExpiresAt_StatusName") - .HasDatabaseName("IX_ExpiresAt_StatusName1"); - - b.HasIndex(new[] { "Version", "ExpiresAt", "StatusName" }, "IX_Version_ExpiresAt_StatusName") - .HasDatabaseName("IX_Version_ExpiresAt_StatusName1"); - - b.ToTable("CAPReceivedMessage", (string)null); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsTransaction", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", null) - .WithMany("Transactions") - .HasForeignKey("PointsAccountId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsRuleModel.PointsRuleCondition", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.PointsRuleModel.PointsRule", null) - .WithMany("Conditions") - .HasForeignKey("RuleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberTag", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.Users.MemberEntity", null) - .WithMany("Tags") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.OAuthAuthorization", b => - { - b.HasOne("Fengling.Member.Domain.Aggregates.Users.MemberEntity", null) - .WithMany("OAuthAuthorizations") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", b => - { - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsRuleModel.PointsRule", b => - { - b.Navigation("Conditions"); - }); - - modelBuilder.Entity("Fengling.Member.Domain.Aggregates.Users.MemberEntity", b => - { - b.Navigation("OAuthAuthorizations"); - - b.Navigation("Tags"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.cs b/src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.cs deleted file mode 100644 index b80df7a..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260209110951_AddPointsRuleSystem.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - /// - public partial class AddPointsRuleSystem : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_fls_wechat_authorization_fls_member_member_id", - table: "fls_wechat_authorization"); - - migrationBuilder.DropForeignKey( - name: "FK_PointsTransaction_mka_integraldetails_PointsAccountId", - table: "PointsTransaction"); - - migrationBuilder.DropPrimaryKey( - name: "PK_PointsTransaction", - table: "PointsTransaction"); - - migrationBuilder.RenameTable( - name: "PointsTransaction", - newName: "PointsTransactions"); - - migrationBuilder.RenameIndex( - name: "IX_PointsTransaction_PointsAccountId", - table: "PointsTransactions", - newName: "IX_PointsTransactions_PointsAccountId"); - - migrationBuilder.AddColumn( - name: "ExpireAt", - table: "PointsTransactions", - type: "timestamp with time zone", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddPrimaryKey( - name: "PK_PointsTransactions", - table: "PointsTransactions", - column: "Id"); - - migrationBuilder.CreateTable( - name: "OAuthAuthorization", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - MemberId = table.Column(type: "bigint", nullable: false), - Provider = table.Column(type: "integer", nullable: false), - OpenId = table.Column(type: "text", nullable: false), - UnionId = table.Column(type: "text", nullable: true), - AccessToken = table.Column(type: "text", nullable: true), - RefreshToken = table.Column(type: "text", nullable: true), - TokenExpiredAt = table.Column(type: "timestamp with time zone", nullable: true), - AuthorizedAt = table.Column(type: "timestamp with time zone", nullable: false), - LastLoginAt = table.Column(type: "timestamp with time zone", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OAuthAuthorization", x => x.Id); - table.ForeignKey( - name: "FK_OAuthAuthorization_fls_member_MemberId", - column: x => x.MemberId, - principalTable: "fls_member", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "PointsRules", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false, comment: "规则标识"), - Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: false, comment: "规则名称"), - Code = table.Column(type: "character varying(50)", maxLength: 50, nullable: false, comment: "规则编码"), - RuleType = table.Column(type: "integer", nullable: false, comment: "规则类型"), - BasePoints = table.Column(type: "integer", nullable: false, comment: "基础积分"), - WeightFactor = table.Column(type: "numeric(18,4)", precision: 18, scale: 4, nullable: true, comment: "权重因子"), - ValidityDays = table.Column(type: "integer", nullable: false, comment: "有效期天数"), - Priority = table.Column(type: "integer", nullable: false, comment: "优先级"), - CalculationMode = table.Column(type: "integer", nullable: false, comment: "计算模式"), - IsActive = table.Column(type: "boolean", nullable: false, comment: "是否启用"), - EffectiveFrom = table.Column(type: "timestamp with time zone", nullable: false, comment: "生效开始时间"), - EffectiveTo = table.Column(type: "timestamp with time zone", nullable: true, comment: "生效结束时间"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间"), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "更新时间") - }, - constraints: table => - { - table.PrimaryKey("PK_PointsRules", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "PointsRuleConditions", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false, comment: "条件标识"), - RuleId = table.Column(type: "uuid", nullable: false, comment: "关联规则标识"), - DimensionType = table.Column(type: "integer", nullable: false, comment: "维度类型"), - DimensionValue = table.Column(type: "character varying(200)", maxLength: 200, nullable: false, comment: "维度值"), - Operator = table.Column(type: "character varying(20)", maxLength: 20, nullable: true, comment: "操作符"), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间") - }, - constraints: table => - { - table.PrimaryKey("PK_PointsRuleConditions", x => x.Id); - table.ForeignKey( - name: "FK_PointsRuleConditions_PointsRules_RuleId", - column: x => x.RuleId, - principalTable: "PointsRules", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_OAuthAuthorization_MemberId", - table: "OAuthAuthorization", - column: "MemberId"); - - migrationBuilder.CreateIndex( - name: "IX_PointsRuleConditions_RuleId_DimensionType", - table: "PointsRuleConditions", - columns: new[] { "RuleId", "DimensionType" }); - - migrationBuilder.CreateIndex( - name: "IX_PointsRules_Code", - table: "PointsRules", - column: "Code", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_PointsRules_IsActive", - table: "PointsRules", - column: "IsActive"); - - migrationBuilder.AddForeignKey( - name: "FK_PointsTransactions_mka_integraldetails_PointsAccountId", - table: "PointsTransactions", - column: "PointsAccountId", - principalTable: "mka_integraldetails", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_PointsTransactions_mka_integraldetails_PointsAccountId", - table: "PointsTransactions"); - - migrationBuilder.DropTable( - name: "OAuthAuthorization"); - - migrationBuilder.DropTable( - name: "PointsRuleConditions"); - - migrationBuilder.DropTable( - name: "PointsRules"); - - migrationBuilder.DropPrimaryKey( - name: "PK_PointsTransactions", - table: "PointsTransactions"); - - migrationBuilder.DropColumn( - name: "ExpireAt", - table: "PointsTransactions"); - - migrationBuilder.RenameTable( - name: "PointsTransactions", - newName: "PointsTransaction"); - - migrationBuilder.RenameIndex( - name: "IX_PointsTransactions_PointsAccountId", - table: "PointsTransaction", - newName: "IX_PointsTransaction_PointsAccountId"); - - migrationBuilder.AddPrimaryKey( - name: "PK_PointsTransaction", - table: "PointsTransaction", - column: "Id"); - - migrationBuilder.AddForeignKey( - name: "FK_fls_wechat_authorization_fls_member_member_id", - table: "fls_wechat_authorization", - column: "member_id", - principalTable: "fls_member", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_PointsTransaction_mka_integraldetails_PointsAccountId", - table: "PointsTransaction", - column: "PointsAccountId", - principalTable: "mka_integraldetails", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.cs b/src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.cs deleted file mode 100644 index 45466ae..0000000 --- a/src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Fengling.Member.Infrastructure.Migrations -{ - /// - public partial class ChangeMemberIdToGuid : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "MemberId", - table: "OAuthAuthorization", - type: "uuid", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint"); - - migrationBuilder.AlterColumn( - name: "member_id", - table: "fls_member_tag", - type: "uuid", - nullable: false, - oldClrType: typeof(long), - oldType: "bigint"); - - migrationBuilder.AlterColumn( - name: "id", - table: "fls_member", - type: "uuid", - nullable: false, - comment: "会员标识", - oldClrType: typeof(long), - oldType: "bigint") - .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "MemberId", - table: "OAuthAuthorization", - type: "bigint", - nullable: false, - oldClrType: typeof(Guid), - oldType: "uuid"); - - migrationBuilder.AlterColumn( - name: "member_id", - table: "fls_member_tag", - type: "bigint", - nullable: false, - oldClrType: typeof(Guid), - oldType: "uuid"); - - migrationBuilder.AlterColumn( - name: "id", - table: "fls_member", - type: "bigint", - nullable: false, - oldClrType: typeof(Guid), - oldType: "uuid", - oldComment: "会员标识") - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - } - } -} diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.Designer.cs b/src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.Designer.cs similarity index 96% rename from src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.Designer.cs rename to src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.Designer.cs index 34468d2..8f33feb 100644 --- a/src/Fengling.Member.Infrastructure/Migrations/20260209163416_ChangeMemberIdToGuid.Designer.cs +++ b/src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.Designer.cs @@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Fengling.Member.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20260209163416_ChangeMemberIdToGuid")] - partial class ChangeMemberIdToGuid + [Migration("20260217154010_Init")] + partial class Init { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -27,17 +27,18 @@ namespace Fengling.Member.Infrastructure.Migrations modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", b => { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id") + .HasComment("积分账户标识"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone") .HasColumnName("created_at"); + b.Property("Deleted") + .HasColumnType("boolean"); + b.Property("FrozenPoints") .ValueGeneratedOnAdd() .HasColumnType("integer") @@ -48,6 +49,10 @@ namespace Fengling.Member.Infrastructure.Migrations .HasColumnType("bigint") .HasColumnName("user_id"); + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("integer"); + b.Property("TenantId") .HasColumnType("bigint") .HasColumnName("tenant_id"); @@ -101,8 +106,8 @@ namespace Fengling.Member.Infrastructure.Migrations b.Property("Points") .HasColumnType("integer"); - b.Property("PointsAccountId") - .HasColumnType("bigint"); + b.Property("PointsAccountId") + .HasColumnType("uuid"); b.Property("Remark") .HasColumnType("text"); @@ -111,6 +116,9 @@ namespace Fengling.Member.Infrastructure.Migrations .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("bigint"); + b.Property("TransactionType") .IsRequired() .HasColumnType("text"); @@ -245,6 +253,9 @@ namespace Fengling.Member.Infrastructure.Migrations .HasColumnType("timestamp with time zone") .HasColumnName("created_at"); + b.Property("Deleted") + .HasColumnType("boolean"); + b.Property("OpenId") .HasMaxLength(64) .HasColumnType("character varying(64)") @@ -255,6 +266,10 @@ namespace Fengling.Member.Infrastructure.Migrations .HasColumnType("character varying(20)") .HasColumnName("phone_number"); + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("integer"); + b.Property("Status") .IsRequired() .HasMaxLength(20) diff --git a/src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.cs b/src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.cs new file mode 100644 index 0000000..34b6b75 --- /dev/null +++ b/src/Fengling.Member.Infrastructure/Migrations/20260217154010_Init.cs @@ -0,0 +1,390 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Fengling.Member.Infrastructure.Migrations +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CAPLock", + columns: table => new + { + Key = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Instance = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + LastLockTime = table.Column(type: "TIMESTAMP", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_CAPLock", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "CAPPublishedMessage", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Version = table.Column(type: "character varying(20)", maxLength: 20, nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), + Content = table.Column(type: "TEXT", nullable: true), + Retries = table.Column(type: "integer", nullable: true), + Added = table.Column(type: "TIMESTAMP", nullable: false), + ExpiresAt = table.Column(type: "TIMESTAMP", nullable: true), + StatusName = table.Column(type: "character varying(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CAPPublishedMessage", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CAPReceivedMessage", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Version = table.Column(type: "character varying(20)", maxLength: 20, nullable: true), + Name = table.Column(type: "character varying(400)", maxLength: 400, nullable: false), + Group = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + Content = table.Column(type: "TEXT", nullable: true), + Retries = table.Column(type: "integer", nullable: true), + Added = table.Column(type: "TIMESTAMP", nullable: false), + ExpiresAt = table.Column(type: "TIMESTAMP", nullable: true), + StatusName = table.Column(type: "character varying(50)", maxLength: 50, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CAPReceivedMessage", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "fls_member", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false, comment: "会员标识"), + tenant_id = table.Column(type: "bigint", nullable: false), + phone_number = table.Column(type: "character varying(20)", maxLength: 20, nullable: true), + open_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + union_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + status = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: true), + version = table.Column(type: "integer", nullable: false, defaultValue: 1), + Deleted = table.Column(type: "boolean", nullable: false), + RowVersion = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_fls_member", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "fls_wechat_authorization", + columns: table => new + { + id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + member_id = table.Column(type: "bigint", nullable: false), + open_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: false), + union_id = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + authorized_at = table.Column(type: "timestamp with time zone", nullable: false), + last_login_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_fls_wechat_authorization", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "mka_integraldetails", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false, comment: "积分账户标识"), + user_id = table.Column(type: "bigint", nullable: false), + tenant_id = table.Column(type: "bigint", nullable: false), + points = table.Column(type: "integer", nullable: false, defaultValue: 0), + frozen_points = table.Column(type: "integer", nullable: false, defaultValue: 0), + version = table.Column(type: "integer", nullable: false, defaultValue: 1), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: true), + Deleted = table.Column(type: "boolean", nullable: false), + RowVersion = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_mka_integraldetails", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "PointsRules", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false, comment: "规则标识"), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: false, comment: "规则名称"), + Code = table.Column(type: "character varying(50)", maxLength: 50, nullable: false, comment: "规则编码"), + RuleType = table.Column(type: "integer", nullable: false, comment: "规则类型"), + BasePoints = table.Column(type: "integer", nullable: false, comment: "基础积分"), + WeightFactor = table.Column(type: "numeric(18,4)", precision: 18, scale: 4, nullable: true, comment: "权重因子"), + ValidityDays = table.Column(type: "integer", nullable: false, comment: "有效期天数"), + Priority = table.Column(type: "integer", nullable: false, comment: "优先级"), + CalculationMode = table.Column(type: "integer", nullable: false, comment: "计算模式"), + IsActive = table.Column(type: "boolean", nullable: false, comment: "是否启用"), + EffectiveFrom = table.Column(type: "timestamp with time zone", nullable: false, comment: "生效开始时间"), + EffectiveTo = table.Column(type: "timestamp with time zone", nullable: true, comment: "生效结束时间"), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间"), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "更新时间") + }, + constraints: table => + { + table.PrimaryKey("PK_PointsRules", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "fls_member_tag", + columns: table => new + { + id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + member_id = table.Column(type: "uuid", nullable: false), + tag_id = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + tag_name = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_fls_member_tag", x => x.id); + table.ForeignKey( + name: "FK_fls_member_tag_fls_member_member_id", + column: x => x.member_id, + principalTable: "fls_member", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "OAuthAuthorization", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + MemberId = table.Column(type: "uuid", nullable: false), + Provider = table.Column(type: "integer", nullable: false), + OpenId = table.Column(type: "text", nullable: false), + UnionId = table.Column(type: "text", nullable: true), + AccessToken = table.Column(type: "text", nullable: true), + RefreshToken = table.Column(type: "text", nullable: true), + TokenExpiredAt = table.Column(type: "timestamp with time zone", nullable: true), + AuthorizedAt = table.Column(type: "timestamp with time zone", nullable: false), + LastLoginAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OAuthAuthorization", x => x.Id); + table.ForeignKey( + name: "FK_OAuthAuthorization_fls_member_MemberId", + column: x => x.MemberId, + principalTable: "fls_member", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PointsTransactions", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + PointsAccountId = table.Column(type: "uuid", nullable: false), + MemberId = table.Column(type: "bigint", nullable: false), + TenantId = table.Column(type: "bigint", nullable: false), + Points = table.Column(type: "integer", nullable: false), + TransactionType = table.Column(type: "text", nullable: false), + SourceId = table.Column(type: "text", nullable: false), + TransactionTypeCategory = table.Column(type: "integer", nullable: false), + Remark = table.Column(type: "text", nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ExpireAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PointsTransactions", x => x.Id); + table.ForeignKey( + name: "FK_PointsTransactions_mka_integraldetails_PointsAccountId", + column: x => x.PointsAccountId, + principalTable: "mka_integraldetails", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PointsRuleConditions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false, comment: "条件标识"), + RuleId = table.Column(type: "uuid", nullable: false, comment: "关联规则标识"), + DimensionType = table.Column(type: "integer", nullable: false, comment: "维度类型"), + DimensionValue = table.Column(type: "character varying(200)", maxLength: 200, nullable: false, comment: "维度值"), + Operator = table.Column(type: "character varying(20)", maxLength: 20, nullable: true, comment: "操作符"), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, comment: "创建时间") + }, + constraints: table => + { + table.PrimaryKey("PK_PointsRuleConditions", x => x.Id); + table.ForeignKey( + name: "FK_PointsRuleConditions_PointsRules_RuleId", + column: x => x.RuleId, + principalTable: "PointsRules", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ExpiresAt_StatusName", + table: "CAPPublishedMessage", + columns: new[] { "ExpiresAt", "StatusName" }); + + migrationBuilder.CreateIndex( + name: "IX_Version_ExpiresAt_StatusName", + table: "CAPPublishedMessage", + columns: new[] { "Version", "ExpiresAt", "StatusName" }); + + migrationBuilder.CreateIndex( + name: "IX_ExpiresAt_StatusName1", + table: "CAPReceivedMessage", + columns: new[] { "ExpiresAt", "StatusName" }); + + migrationBuilder.CreateIndex( + name: "IX_Version_ExpiresAt_StatusName1", + table: "CAPReceivedMessage", + columns: new[] { "Version", "ExpiresAt", "StatusName" }); + + migrationBuilder.CreateIndex( + name: "idx_member_openid", + table: "fls_member", + column: "open_id"); + + migrationBuilder.CreateIndex( + name: "idx_member_tenant_phone", + table: "fls_member", + columns: new[] { "tenant_id", "phone_number" }); + + migrationBuilder.CreateIndex( + name: "idx_member_tenantid", + table: "fls_member", + column: "tenant_id"); + + migrationBuilder.CreateIndex( + name: "idx_member_unionid", + table: "fls_member", + column: "union_id"); + + migrationBuilder.CreateIndex( + name: "idx_membertag_member_tag", + table: "fls_member_tag", + columns: new[] { "member_id", "tag_id" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "idx_membertag_tagid", + table: "fls_member_tag", + column: "tag_id"); + + migrationBuilder.CreateIndex( + name: "idx_wechat_auth_memberid", + table: "fls_wechat_authorization", + column: "member_id"); + + migrationBuilder.CreateIndex( + name: "idx_wechat_auth_openid", + table: "fls_wechat_authorization", + column: "open_id", + unique: true); + + migrationBuilder.CreateIndex( + name: "idx_wechat_auth_unionid", + table: "fls_wechat_authorization", + column: "union_id"); + + migrationBuilder.CreateIndex( + name: "idx_points_account_member_tenant", + table: "mka_integraldetails", + columns: new[] { "user_id", "tenant_id" }); + + migrationBuilder.CreateIndex( + name: "idx_points_account_memberid", + table: "mka_integraldetails", + column: "user_id", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OAuthAuthorization_MemberId", + table: "OAuthAuthorization", + column: "MemberId"); + + migrationBuilder.CreateIndex( + name: "IX_PointsRuleConditions_RuleId_DimensionType", + table: "PointsRuleConditions", + columns: new[] { "RuleId", "DimensionType" }); + + migrationBuilder.CreateIndex( + name: "IX_PointsRules_Code", + table: "PointsRules", + column: "Code", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PointsRules_IsActive", + table: "PointsRules", + column: "IsActive"); + + migrationBuilder.CreateIndex( + name: "IX_PointsTransactions_PointsAccountId", + table: "PointsTransactions", + column: "PointsAccountId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CAPLock"); + + migrationBuilder.DropTable( + name: "CAPPublishedMessage"); + + migrationBuilder.DropTable( + name: "CAPReceivedMessage"); + + migrationBuilder.DropTable( + name: "fls_member_tag"); + + migrationBuilder.DropTable( + name: "fls_wechat_authorization"); + + migrationBuilder.DropTable( + name: "OAuthAuthorization"); + + migrationBuilder.DropTable( + name: "PointsRuleConditions"); + + migrationBuilder.DropTable( + name: "PointsTransactions"); + + migrationBuilder.DropTable( + name: "fls_member"); + + migrationBuilder.DropTable( + name: "PointsRules"); + + migrationBuilder.DropTable( + name: "mka_integraldetails"); + } + } +} diff --git a/src/Fengling.Member.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Fengling.Member.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 87d5861..9048744 100644 --- a/src/Fengling.Member.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Fengling.Member.Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -24,17 +24,18 @@ namespace Fengling.Member.Infrastructure.Migrations modelBuilder.Entity("Fengling.Member.Domain.Aggregates.PointsModel.PointsAccount", b => { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id") + .HasComment("积分账户标识"); b.Property("CreatedAt") .HasColumnType("timestamp with time zone") .HasColumnName("created_at"); + b.Property("Deleted") + .HasColumnType("boolean"); + b.Property("FrozenPoints") .ValueGeneratedOnAdd() .HasColumnType("integer") @@ -45,6 +46,10 @@ namespace Fengling.Member.Infrastructure.Migrations .HasColumnType("bigint") .HasColumnName("user_id"); + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("integer"); + b.Property("TenantId") .HasColumnType("bigint") .HasColumnName("tenant_id"); @@ -98,8 +103,8 @@ namespace Fengling.Member.Infrastructure.Migrations b.Property("Points") .HasColumnType("integer"); - b.Property("PointsAccountId") - .HasColumnType("bigint"); + b.Property("PointsAccountId") + .HasColumnType("uuid"); b.Property("Remark") .HasColumnType("text"); @@ -108,6 +113,9 @@ namespace Fengling.Member.Infrastructure.Migrations .IsRequired() .HasColumnType("text"); + b.Property("TenantId") + .HasColumnType("bigint"); + b.Property("TransactionType") .IsRequired() .HasColumnType("text"); @@ -242,6 +250,9 @@ namespace Fengling.Member.Infrastructure.Migrations .HasColumnType("timestamp with time zone") .HasColumnName("created_at"); + b.Property("Deleted") + .HasColumnType("boolean"); + b.Property("OpenId") .HasMaxLength(64) .HasColumnType("character varying(64)") @@ -252,6 +263,10 @@ namespace Fengling.Member.Infrastructure.Migrations .HasColumnType("character varying(20)") .HasColumnName("phone_number"); + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("integer"); + b.Property("Status") .IsRequired() .HasMaxLength(20) diff --git a/src/Fengling.Member.Infrastructure/Repositories/IPointsHistoryRepository.cs b/src/Fengling.Member.Infrastructure/Repositories/IPointsHistoryRepository.cs deleted file mode 100644 index fdeb17f..0000000 --- a/src/Fengling.Member.Infrastructure/Repositories/IPointsHistoryRepository.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Fengling.Member.Domain.Aggregates.PointsModel; - -namespace Fengling.Member.Infrastructure.Repositories; - -/// -/// 积分历史仓储接口 -/// -public interface IPointsHistoryRepository -{ - /// - /// 检查 SourceId 是否已存在(幂等性检查) - /// - Task ExistsBySourceIdAsync(string sourceId, CancellationToken cancellationToken = default); - - /// - /// 获取会员的积分明细(分页) - /// - Task> GetByMemberIdAsync( - long memberId, - int page = 1, - int pageSize = 20, - CancellationToken cancellationToken = default); - - /// - /// 统计会员的积分明细数量 - /// - Task CountByMemberIdAsync(long memberId, CancellationToken cancellationToken = default); - - /// - /// 获取积分明细 - /// - Task GetByIdAsync(long id, CancellationToken cancellationToken = default); - - /// - /// 添加积分明细 - /// - Task AddAsync(PointsTransaction transaction, CancellationToken cancellationToken = default); -} diff --git a/src/Fengling.Member.Infrastructure/Repositories/PointsRuleConditionRepository.cs b/src/Fengling.Member.Infrastructure/Repositories/PointsRuleConditionRepository.cs deleted file mode 100644 index 3068428..0000000 --- a/src/Fengling.Member.Infrastructure/Repositories/PointsRuleConditionRepository.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Fengling.Member.Domain.Aggregates.PointsRuleModel; -using Fengling.Member.Domain.Repositories; - -namespace Fengling.Member.Infrastructure.Repositories; - -public class PointsRuleConditionRepository : IPointsRuleConditionRepository -{ - private readonly ApplicationDbContext _context; - - public PointsRuleConditionRepository(ApplicationDbContext context) - { - _context = context; - } - - public async Task> GetByRuleIdAsync(PointsRuleId ruleId) - { - return await _context.PointsRuleConditions - .Where(x => x.RuleId == ruleId) - .ToListAsync(); - } - - public async Task AddAsync(PointsRuleCondition condition) - { - await _context.PointsRuleConditions.AddAsync(condition); - } - - public async Task DeleteByRuleIdAsync(PointsRuleId ruleId) - { - var conditions = await GetByRuleIdAsync(ruleId); - _context.PointsRuleConditions.RemoveRange(conditions); - } -} diff --git a/src/Fengling.Member.Infrastructure/Repositories/PointsRuleRepository.cs b/src/Fengling.Member.Infrastructure/Repositories/PointsRuleRepository.cs index 9d6424c..daf1ebb 100644 --- a/src/Fengling.Member.Infrastructure/Repositories/PointsRuleRepository.cs +++ b/src/Fengling.Member.Infrastructure/Repositories/PointsRuleRepository.cs @@ -5,25 +5,27 @@ using Microsoft.EntityFrameworkCore; namespace Fengling.Member.Infrastructure.Repositories; -public class PointsRuleRepository : IPointsRuleRepository +public interface IPointsRuleRepository : IRepository { - private readonly ApplicationDbContext _context; - - public PointsRuleRepository(ApplicationDbContext context) - { - _context = context; - } + Task GetByIdAsync(PointsRuleId id); + Task GetByCodeAsync(string code); + Task> GetActiveRulesAsync(); + Task> GetActiveRulesByDimensionAsync(DimensionType dimensionType, string dimensionValue); +} +public class PointsRuleRepository(ApplicationDbContext context) + : RepositoryBase(context), IPointsRuleRepository +{ public async Task GetByIdAsync(PointsRuleId id) { - return await _context.PointsRules + return await DbContext.PointsRules .Include(x => x.Conditions) .FirstOrDefaultAsync(x => x.Id == id); } public async Task GetByCodeAsync(string code) { - return await _context.PointsRules + return await DbContext.PointsRules .Include(x => x.Conditions) .FirstOrDefaultAsync(x => x.Code == code); } @@ -31,7 +33,7 @@ public class PointsRuleRepository : IPointsRuleRepository public async Task> GetActiveRulesAsync() { var now = DateTime.UtcNow; - return await _context.PointsRules + return await DbContext.PointsRules .Include(x => x.Conditions) .Where(x => x.IsActive && x.EffectiveFrom <= now @@ -45,7 +47,7 @@ public class PointsRuleRepository : IPointsRuleRepository string dimensionValue) { var now = DateTime.UtcNow; - return await _context.PointsRules + return await DbContext.PointsRules .Include(x => x.Conditions) .Where(x => x.IsActive && x.EffectiveFrom <= now @@ -54,24 +56,4 @@ public class PointsRuleRepository : IPointsRuleRepository .OrderByDescending(x => x.Priority) .ToListAsync(); } - - public async Task AddAsync(PointsRule rule) - { - await _context.PointsRules.AddAsync(rule); - } - - public async Task UpdateAsync(PointsRule rule) - { - _context.PointsRules.Update(rule); - await Task.CompletedTask; - } - - public async Task DeleteAsync(PointsRuleId id) - { - var rule = await GetByIdAsync(id); - if (rule != null) - { - _context.PointsRules.Remove(rule); - } - } } diff --git a/src/Fengling.Member.Web/1ling.Member.Infrastructure b/src/Fengling.Member.Web/1ling.Member.Infrastructure new file mode 100644 index 0000000..2f2bfd5 --- /dev/null +++ b/src/Fengling.Member.Web/1ling.Member.Infrastructure @@ -0,0 +1 @@ +Unable to retrieve project metadata. Ensure it's an SDK-style project. diff --git a/src/Fengling.Member.Web/Endpoints/v1/PointsEndpoints.cs b/src/Fengling.Member.Web/Endpoints/v1/PointsEndpoints.cs index dbd7330..70cf12c 100644 --- a/src/Fengling.Member.Web/Endpoints/v1/PointsEndpoints.cs +++ b/src/Fengling.Member.Web/Endpoints/v1/PointsEndpoints.cs @@ -128,15 +128,9 @@ public class GetPointsBalanceResponse public int AvailablePoints { get; set; } } -public class GetPointsHistoryEndpoint : Endpoint +public class GetPointsHistoryEndpoint(IPointsHistoryRepository historyRepository) + : Endpoint { - private readonly IPointsHistoryRepository _historyRepository; - - public GetPointsHistoryEndpoint(IPointsHistoryRepository historyRepository) - { - _historyRepository = historyRepository; - } - public override void Configure() { Get("/api/v1/members/{MemberId}/points/history"); @@ -149,13 +143,13 @@ public class GetPointsHistoryEndpoint : Endpoint 0 ? req.Page : 1, req.PageSize > 0 && req.PageSize <= 100 ? req.PageSize : 20, ct); - var totalCount = await _historyRepository.CountByMemberIdAsync(req.MemberId, ct); + var totalCount = await historyRepository.CountByMemberIdAsync(req.MemberId, ct); Response = new GetPointsHistoryResponse { diff --git a/src/Fengling.Member.Web/Endpoints/v1/PointsRuleEndpoints.cs b/src/Fengling.Member.Web/Endpoints/v1/PointsRuleEndpoints.cs index e5143fe..db5545d 100644 --- a/src/Fengling.Member.Web/Endpoints/v1/PointsRuleEndpoints.cs +++ b/src/Fengling.Member.Web/Endpoints/v1/PointsRuleEndpoints.cs @@ -3,7 +3,7 @@ using Fengling.Member.Application.Commands.Points; using Fengling.Member.Application.Dtos; using Fengling.Member.Application.Dtos.PointsRule; using Fengling.Member.Domain.Aggregates.PointsRuleModel; -using Fengling.Member.Domain.Repositories; +using Fengling.Member.Infrastructure.Repositories; using MediatR; namespace Fengling.Member.Web.Endpoints.v1; @@ -60,14 +60,10 @@ public class QueryPointsRulesEndpoint : Endpoint { private readonly IPointsRuleRepository _ruleRepository; - private readonly IPointsRuleConditionRepository _conditionRepository; - public CreatePointsRuleEndpoint( - IPointsRuleRepository ruleRepository, - IPointsRuleConditionRepository conditionRepository) + public CreatePointsRuleEndpoint(IPointsRuleRepository ruleRepository) { _ruleRepository = ruleRepository; - _conditionRepository = conditionRepository; } public override void Configure() @@ -92,8 +88,6 @@ public class CreatePointsRuleEndpoint : Endpoint(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + + + #region 身份认证 var redis = await ConnectionMultiplexer.ConnectAsync(builder.Configuration.GetConnectionString("Redis")!); @@ -144,7 +150,12 @@ try #endregion builder.Services.AddMediatR(cfg => - cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()) + cfg.RegisterServicesFromAssemblies( + Assembly.GetExecutingAssembly(), + typeof(Fengling.Member.Application.Commands.Member.RegisterMemberCommand).Assembly, + typeof(Fengling.Member.Domain.Aggregates.Users.MemberEntity).Assembly, + typeof(Fengling.Member.Infrastructure.Repositories.MemberRepository).Assembly + ) .AddCommandLockBehavior() .AddKnownExceptionValidationBehavior() .AddUnitOfWorkBehaviors()); @@ -185,9 +196,10 @@ try #region Points Rule Services - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); #endregion diff --git a/src/Fengling.Member.Web/appsettings.Development.json b/src/Fengling.Member.Web/appsettings.Development.json index 9c262f3..4a9f1f4 100644 --- a/src/Fengling.Member.Web/appsettings.Development.json +++ b/src/Fengling.Member.Web/appsettings.Development.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "PostgreSQL": "Host=localhost;Database=dev;Username=postgres;Password=123456", + "PostgreSQL": "Host=192.168.100.10;Database=fengling_member;Username=movingsam;Password=sl52788542", "Redis": "81.68.223.70:16379,password=sl52788542" }, "RabbitMQ": {