From d6f5c00554f85863d2f12728372a7de481b218a4 Mon Sep 17 00:00:00 2001 From: Sam <315859133@qq.com> Date: Thu, 5 Feb 2026 14:54:07 +0800 Subject: [PATCH] feat(risk-control): add repository layer --- .../ILotteryActivityRepository.cs | 13 ++++ .../Repositories/IRiskAlertRepository.cs | 14 ++++ .../Repositories/IRiskRuleRepository.cs | 14 ++++ .../Repositories/IRiskScoreRepository.cs | 14 ++++ .../Repositories/LotteryActivityRepository.cs | 54 ++++++++++++++++ .../Repositories/RiskAlertRepository.cs | 59 +++++++++++++++++ .../Repositories/RiskRuleRepository.cs | 59 +++++++++++++++++ .../Repositories/RiskScoreRepository.cs | 58 +++++++++++++++++ .../RiskControlDbContext.cs | 64 +++++++++++++++++++ 9 files changed, 349 insertions(+) create mode 100644 Fengling.RiskControl.Domain/Repositories/ILotteryActivityRepository.cs create mode 100644 Fengling.RiskControl.Domain/Repositories/IRiskAlertRepository.cs create mode 100644 Fengling.RiskControl.Domain/Repositories/IRiskRuleRepository.cs create mode 100644 Fengling.RiskControl.Domain/Repositories/IRiskScoreRepository.cs create mode 100644 Fengling.RiskControl.Infrastructure/Repositories/LotteryActivityRepository.cs create mode 100644 Fengling.RiskControl.Infrastructure/Repositories/RiskAlertRepository.cs create mode 100644 Fengling.RiskControl.Infrastructure/Repositories/RiskRuleRepository.cs create mode 100644 Fengling.RiskControl.Infrastructure/Repositories/RiskScoreRepository.cs create mode 100644 Fengling.RiskControl.Infrastructure/RiskControlDbContext.cs diff --git a/Fengling.RiskControl.Domain/Repositories/ILotteryActivityRepository.cs b/Fengling.RiskControl.Domain/Repositories/ILotteryActivityRepository.cs new file mode 100644 index 0000000..d39fbf5 --- /dev/null +++ b/Fengling.RiskControl.Domain/Repositories/ILotteryActivityRepository.cs @@ -0,0 +1,13 @@ +using Fengling.RiskControl.Domain.Aggregates.LotteryActivities; + +namespace Fengling.RiskControl.Domain.Repositories; + +public interface ILotteryActivityRepository +{ + Task GetByIdAsync(long id); + Task> GetByMemberIdAsync(long memberId); + Task> GetRecentByMemberIdAsync(long memberId, int count); + Task AddAsync(LotteryActivity activity); + Task UpdateAsync(LotteryActivity activity); + Task DeleteAsync(LotteryActivity activity); +} diff --git a/Fengling.RiskControl.Domain/Repositories/IRiskAlertRepository.cs b/Fengling.RiskControl.Domain/Repositories/IRiskAlertRepository.cs new file mode 100644 index 0000000..45338b3 --- /dev/null +++ b/Fengling.RiskControl.Domain/Repositories/IRiskAlertRepository.cs @@ -0,0 +1,14 @@ +using Fengling.RiskControl.Domain.Aggregates.RiskAlerts; + +namespace Fengling.RiskControl.Domain.Repositories; + +public interface IRiskAlertRepository +{ + Task GetByIdAsync(long id); + Task> GetByMemberIdAsync(long memberId); + Task> GetPendingAlertsAsync(); + Task> GetAlertsByPriorityAsync(RiskAlertPriority priority); + Task AddAsync(RiskAlert alert); + Task UpdateAsync(RiskAlert alert); + Task DeleteAsync(RiskAlert alert); +} diff --git a/Fengling.RiskControl.Domain/Repositories/IRiskRuleRepository.cs b/Fengling.RiskControl.Domain/Repositories/IRiskRuleRepository.cs new file mode 100644 index 0000000..bedc434 --- /dev/null +++ b/Fengling.RiskControl.Domain/Repositories/IRiskRuleRepository.cs @@ -0,0 +1,14 @@ +using Fengling.RiskControl.Domain.Aggregates.RiskRules; + +namespace Fengling.RiskControl.Domain.Repositories; + +public interface IRiskRuleRepository +{ + Task GetByIdAsync(long id); + Task> GetActiveRulesAsync(); + Task> GetRulesByTypeAsync(RiskRuleType type); + Task> GetRulesForEvaluationAsync(string entityType, string actionType); + Task AddAsync(RiskRule rule); + Task UpdateAsync(RiskRule rule); + Task DeleteAsync(RiskRule rule); +} diff --git a/Fengling.RiskControl.Domain/Repositories/IRiskScoreRepository.cs b/Fengling.RiskControl.Domain/Repositories/IRiskScoreRepository.cs new file mode 100644 index 0000000..9c0620d --- /dev/null +++ b/Fengling.RiskControl.Domain/Repositories/IRiskScoreRepository.cs @@ -0,0 +1,14 @@ +using Fengling.RiskControl.Domain.Aggregates.RiskScores; + +namespace Fengling.RiskControl.Domain.Repositories; + +public interface IRiskScoreRepository +{ + Task GetByIdAsync(long id); + Task GetByMemberAndEntityAsync(long memberId, string entityType, string entityId); + Task GetActiveByMemberAndEntityTypeAsync(long memberId, string entityType); + Task> GetByMemberIdAsync(long memberId); + Task AddAsync(RiskScore score); + Task UpdateAsync(RiskScore score); + Task DeleteAsync(RiskScore score); +} diff --git a/Fengling.RiskControl.Infrastructure/Repositories/LotteryActivityRepository.cs b/Fengling.RiskControl.Infrastructure/Repositories/LotteryActivityRepository.cs new file mode 100644 index 0000000..3b9a4ef --- /dev/null +++ b/Fengling.RiskControl.Infrastructure/Repositories/LotteryActivityRepository.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore; +using Fengling.RiskControl.Domain.Aggregates.LotteryActivities; +using Fengling.RiskControl.Domain.Repositories; + +namespace Fengling.RiskControl.Infrastructure.Repositories; + +public class LotteryActivityRepository : ILotteryActivityRepository +{ + private readonly RiskControlDbContext _context; + + public LotteryActivityRepository(RiskControlDbContext context) + { + _context = context; + } + + public async Task GetByIdAsync(long id) + { + return await _context.LotteryActivities.FindAsync(id); + } + + public async Task> GetByMemberIdAsync(long memberId) + { + return await _context.LotteryActivities + .Where(l => l.MemberId == memberId) + .OrderByDescending(l => l.CreatedAt) + .ToListAsync(); + } + + public async Task> GetRecentByMemberIdAsync(long memberId, int count) + { + return await _context.LotteryActivities + .Where(l => l.MemberId == memberId) + .OrderByDescending(l => l.CreatedAt) + .Take(count) + .ToListAsync(); + } + + public async Task AddAsync(LotteryActivity activity) + { + await _context.LotteryActivities.AddAsync(activity); + } + + public async Task UpdateAsync(LotteryActivity activity) + { + _context.LotteryActivities.Update(activity); + await Task.CompletedTask; + } + + public async Task DeleteAsync(LotteryActivity activity) + { + _context.LotteryActivities.Remove(activity); + await Task.CompletedTask; + } +} diff --git a/Fengling.RiskControl.Infrastructure/Repositories/RiskAlertRepository.cs b/Fengling.RiskControl.Infrastructure/Repositories/RiskAlertRepository.cs new file mode 100644 index 0000000..559a917 --- /dev/null +++ b/Fengling.RiskControl.Infrastructure/Repositories/RiskAlertRepository.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore; +using Fengling.RiskControl.Domain.Aggregates.RiskAlerts; +using Fengling.RiskControl.Domain.Repositories; + +namespace Fengling.RiskControl.Infrastructure.Repositories; + +public class RiskAlertRepository : IRiskAlertRepository +{ + private readonly RiskControlDbContext _context; + + public RiskAlertRepository(RiskControlDbContext context) + { + _context = context; + } + + public async Task GetByIdAsync(long id) + { + return await _context.RiskAlerts.FindAsync(id); + } + + public async Task> GetByMemberIdAsync(long memberId) + { + return await _context.RiskAlerts + .Where(a => a.MemberId == memberId) + .ToListAsync(); + } + + public async Task> GetPendingAlertsAsync() + { + return await _context.RiskAlerts + .Where(a => a.Status == RiskAlertStatus.Pending) + .OrderByDescending(a => a.Priority) + .ToListAsync(); + } + + public async Task> GetAlertsByPriorityAsync(RiskAlertPriority priority) + { + return await _context.RiskAlerts + .Where(a => a.Priority == priority) + .ToListAsync(); + } + + public async Task AddAsync(RiskAlert alert) + { + await _context.RiskAlerts.AddAsync(alert); + } + + public async Task UpdateAsync(RiskAlert alert) + { + _context.RiskAlerts.Update(alert); + await Task.CompletedTask; + } + + public async Task DeleteAsync(RiskAlert alert) + { + _context.RiskAlerts.Remove(alert); + await Task.CompletedTask; + } +} diff --git a/Fengling.RiskControl.Infrastructure/Repositories/RiskRuleRepository.cs b/Fengling.RiskControl.Infrastructure/Repositories/RiskRuleRepository.cs new file mode 100644 index 0000000..cb96f37 --- /dev/null +++ b/Fengling.RiskControl.Infrastructure/Repositories/RiskRuleRepository.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore; +using Fengling.RiskControl.Domain.Aggregates.RiskRules; +using Fengling.RiskControl.Domain.Repositories; + +namespace Fengling.RiskControl.Infrastructure.Repositories; + +public class RiskRuleRepository : IRiskRuleRepository +{ + private readonly RiskControlDbContext _context; + + public RiskRuleRepository(RiskControlDbContext context) + { + _context = context; + } + + public async Task GetByIdAsync(long id) + { + return await _context.RiskRules.FindAsync(id); + } + + public async Task> GetActiveRulesAsync() + { + return await _context.RiskRules + .Where(r => r.IsActive) + .OrderByDescending(r => r.Priority) + .ToListAsync(); + } + + public async Task> GetRulesByTypeAsync(RiskRuleType type) + { + return await _context.RiskRules + .Where(r => r.RuleType == type && r.IsActive) + .ToListAsync(); + } + + public async Task> GetRulesForEvaluationAsync(string entityType, string actionType) + { + return await _context.RiskRules + .Where(r => r.IsActive) + .ToListAsync(); + } + + public async Task AddAsync(RiskRule rule) + { + await _context.RiskRules.AddAsync(rule); + } + + public async Task UpdateAsync(RiskRule rule) + { + _context.RiskRules.Update(rule); + await Task.CompletedTask; + } + + public async Task DeleteAsync(RiskRule rule) + { + _context.RiskRules.Remove(rule); + await Task.CompletedTask; + } +} diff --git a/Fengling.RiskControl.Infrastructure/Repositories/RiskScoreRepository.cs b/Fengling.RiskControl.Infrastructure/Repositories/RiskScoreRepository.cs new file mode 100644 index 0000000..ed8c2aa --- /dev/null +++ b/Fengling.RiskControl.Infrastructure/Repositories/RiskScoreRepository.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore; +using Fengling.RiskControl.Domain.Aggregates.RiskScores; +using Fengling.RiskControl.Domain.Repositories; + +namespace Fengling.RiskControl.Infrastructure.Repositories; + +public class RiskScoreRepository : IRiskScoreRepository +{ + private readonly RiskControlDbContext _context; + + public RiskScoreRepository(RiskControlDbContext context) + { + _context = context; + } + + public async Task GetByIdAsync(long id) + { + return await _context.RiskScores.FindAsync(id); + } + + public async Task GetByMemberAndEntityAsync(long memberId, string entityType, string entityId) + { + return await _context.RiskScores + .FirstOrDefaultAsync(s => s.MemberId == memberId && s.EntityType == entityType && s.EntityId == entityId); + } + + public async Task GetActiveByMemberAndEntityTypeAsync(long memberId, string entityType) + { + return await _context.RiskScores + .Where(s => s.MemberId == memberId && s.EntityType == entityType) + .OrderByDescending(s => s.CreatedAt) + .FirstOrDefaultAsync(); + } + + public async Task> GetByMemberIdAsync(long memberId) + { + return await _context.RiskScores + .Where(s => s.MemberId == memberId) + .ToListAsync(); + } + + public async Task AddAsync(RiskScore score) + { + await _context.RiskScores.AddAsync(score); + } + + public async Task UpdateAsync(RiskScore score) + { + _context.RiskScores.Update(score); + await Task.CompletedTask; + } + + public async Task DeleteAsync(RiskScore score) + { + _context.RiskScores.Remove(score); + await Task.CompletedTask; + } +} diff --git a/Fengling.RiskControl.Infrastructure/RiskControlDbContext.cs b/Fengling.RiskControl.Infrastructure/RiskControlDbContext.cs new file mode 100644 index 0000000..78918a8 --- /dev/null +++ b/Fengling.RiskControl.Infrastructure/RiskControlDbContext.cs @@ -0,0 +1,64 @@ +using Microsoft.EntityFrameworkCore; +using NetCorePal.Extensions.Domain; +using Fengling.RiskControl.Domain.Aggregates.RiskRules; +using Fengling.RiskControl.Domain.Aggregates.RiskScores; +using Fengling.RiskControl.Domain.Aggregates.RiskAlerts; +using Fengling.RiskControl.Domain.Aggregates.LotteryActivities; + +namespace Fengling.RiskControl.Infrastructure; + +public class RiskControlDbContext : DbContext +{ + public DbSet RiskRules => Set(); + public DbSet RiskScores => Set(); + public DbSet RiskAlerts => Set(); + public DbSet LotteryActivities => Set(); + + private RiskControlDbContext() { } + + public RiskControlDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(builder => + { + builder.ToTable("rc_risk_rules"); + builder.HasKey(r => r.Id); + builder.Property(r => r.Name).HasMaxLength(100).IsRequired(); + builder.Property(r => r.Description).HasMaxLength(500); + builder.Property(r => r.ConfigJson).HasColumnName("config_json"); + builder.Property(r => r.IsActive).HasDefaultValue(true); + }); + + modelBuilder.Entity(builder => + { + builder.ToTable("rc_risk_scores"); + builder.HasKey(s => s.Id); + builder.Property(s => s.MemberId).IsRequired(); + builder.Property(s => s.EntityType).HasMaxLength(50).IsRequired(); + builder.Property(s => s.EntityId).HasMaxLength(100).IsRequired(); + }); + + modelBuilder.Entity(builder => + { + builder.ToTable("rc_risk_alerts"); + builder.HasKey(a => a.Id); + builder.Property(a => a.MemberId).IsRequired(); + builder.Property(a => a.AlertType).HasMaxLength(50).IsRequired(); + builder.Property(a => a.Description).HasMaxLength(500); + }); + + modelBuilder.Entity(builder => + { + builder.ToTable("rc_lottery_activities"); + builder.HasKey(l => l.Id); + builder.Property(l => l.MemberId).IsRequired(); + builder.Property(l => l.ActivityType).HasMaxLength(50).IsRequired(); + builder.Property(l => l.IpAddress).HasMaxLength(50); + builder.Property(l => l.DeviceId).HasMaxLength(100); + }); + } +}