diff --git a/DysonNetwork.Pass/Lotteries/LotteryController.cs b/DysonNetwork.Pass/Lotteries/LotteryController.cs index a8ce47f..fea18b5 100644 --- a/DysonNetwork.Pass/Lotteries/LotteryController.cs +++ b/DysonNetwork.Pass/Lotteries/LotteryController.cs @@ -44,6 +44,10 @@ public class LotteryController(AppDatabase db, LotteryService lotteryService) : { return BadRequest(err.Message); } + catch (InvalidOperationException err) + { + return BadRequest(err.Message); + } } [HttpGet] @@ -80,21 +84,20 @@ public class LotteryController(AppDatabase db, LotteryService lotteryService) : [RequiredPermission("maintenance", "lotteries.draw.perform")] public async Task PerformLotteryDraw() { - await lotteryService.PerformDailyDrawAsync(); - return Ok("Lottery draw performed successfully."); + await lotteryService.DrawLotteries(); + return Ok(); } [HttpGet("records")] - [Authorize] public async Task>> GetLotteryRecords( [FromQuery] Instant? startDate = null, [FromQuery] Instant? endDate = null, [FromQuery] int offset = 0, [FromQuery] int limit = 20) { - if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized(); - - var query = db.LotteryRecords.AsQueryable(); + var query = db.LotteryRecords + .OrderByDescending(r => r.CreatedAt) + .AsQueryable(); if (startDate.HasValue) query = query.Where(r => r.DrawDate >= startDate.Value); @@ -105,7 +108,6 @@ public class LotteryController(AppDatabase db, LotteryService lotteryService) : Response.Headers["X-Total"] = total.ToString(); var records = await query - .OrderByDescending(r => r.DrawDate) .Skip(offset) .Take(limit) .ToListAsync(); diff --git a/DysonNetwork.Pass/Lotteries/LotteryDrawJob.cs b/DysonNetwork.Pass/Lotteries/LotteryDrawJob.cs index dd7d938..c300ebc 100644 --- a/DysonNetwork.Pass/Lotteries/LotteryDrawJob.cs +++ b/DysonNetwork.Pass/Lotteries/LotteryDrawJob.cs @@ -10,7 +10,7 @@ public class LotteryDrawJob(LotteryService lotteryService, ILogger RegionOneNumbers { get; set; } = new(); + public int RegionTwoNumber { get; set; } + public int Multiplier { get; set; } = 1; +} + +public class LotteryService( + AppDatabase db, + PaymentService paymentService, + WalletService walletService, + ILogger logger) +{ + private readonly ILogger _logger = logger; + private static bool ValidateNumbers(List region1, int region2) { if (region1.Count != 5 || region1.Distinct().Count() != 5) @@ -62,19 +78,33 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle return 10 + (multiplier - 1) * 10; } - public async Task CreateLotteryOrderAsync(Guid accountId, List region1, int region2, int multiplier = 1) + public async Task CreateLotteryOrderAsync(Guid accountId, List region1, int region2, + int multiplier = 1) { if (!ValidateNumbers(region1, region2)) throw new ArgumentException("Invalid lottery numbers"); var now = SystemClock.Instance.GetCurrentInstant(); - var todayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc().ToInstant(); - var hasPurchasedToday = await db.Lotteries.AnyAsync(l => l.AccountId == accountId && l.CreatedAt >= todayStart); + var todayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc() + .ToInstant(); + var hasPurchasedToday = await db.Lotteries.AnyAsync(l => + l.AccountId == accountId && + l.CreatedAt >= todayStart && + l.DrawStatus == LotteryDrawStatus.Pending + ); if (hasPurchasedToday) throw new InvalidOperationException("You can only purchase one lottery per day."); var price = CalculateLotteryPrice(multiplier); + var lotteryData = new LotteryOrderMetaData + { + AccountId = accountId, + RegionOneNumbers = region1, + RegionTwoNumber = region2, + Multiplier = multiplier + }; + return await paymentService.CreateOrderAsync( null, WalletCurrency.SourcePoint, @@ -83,29 +113,33 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle productIdentifier: "lottery", meta: new Dictionary { - ["account_id"] = accountId.ToString(), - ["region_one_numbers"] = region1, - ["region_two_number"] = region2, - ["multiplier"] = multiplier + ["data"] = JsonSerializer.Serialize(lotteryData) }); } public async Task HandleLotteryOrder(SnWalletOrder order) { + if (order.Status == OrderStatus.Finished) + return; // Already processed + if (order.Status != OrderStatus.Paid || - !order.Meta.TryGetValue("account_id", out var accountIdValue) || - !order.Meta.TryGetValue("region_one_numbers", out var region1Value) || - !order.Meta.TryGetValue("region_two_number", out var region2Value) || - !order.Meta.TryGetValue("multiplier", out var multiplierValue)) + !order.Meta.TryGetValue("data", out var dataValue) || + dataValue is null || + dataValue is not JsonElement { ValueKind: JsonValueKind.String } jsonElem) throw new InvalidOperationException("Invalid order."); - var accountId = Guid.Parse((string)accountIdValue!); - var region1Json = (System.Text.Json.JsonElement)region1Value; - var region1 = region1Json.EnumerateArray().Select(e => e.GetInt32()).ToList(); - var region2 = Convert.ToInt32((string)region2Value!); - var multiplier = Convert.ToInt32((string)multiplierValue!); + var jsonString = jsonElem.GetString(); + if (jsonString is null) + throw new InvalidOperationException("Invalid order."); - await CreateTicketAsync(accountId, region1, region2, multiplier); + var data = JsonSerializer.Deserialize(jsonString); + if (data is null) + throw new InvalidOperationException("Invalid order data."); + + await CreateTicketAsync(data.AccountId, data.RegionOneNumbers, data.RegionTwoNumber, data.Multiplier); + + order.Status = OrderStatus.Finished; + await db.SaveChangesAsync(); } private static int CalculateReward(int region1Matches, bool region2Match) @@ -133,6 +167,7 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle var num = random.Next(min, max + 1); if (!numbers.Contains(num)) numbers.Add(num); } + return numbers.OrderBy(n => n).ToList(); } @@ -141,68 +176,101 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle return playerNumbers.Intersect(winningNumbers).Count(); } - public async Task PerformDailyDrawAsync() + public async Task DrawLotteries() { - var now = SystemClock.Instance.GetCurrentInstant(); - var yesterdayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc().ToInstant().Minus(Duration.FromDays(1)); - var todayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc().ToInstant(); - - // Tickets purchased yesterday that are still pending draw - var tickets = await db.Lotteries - .Where(l => l.CreatedAt >= yesterdayStart && l.CreatedAt < todayStart && l.DrawStatus == LotteryDrawStatus.Pending) - .ToListAsync(); - - if (!tickets.Any()) return; - - // Generate winning numbers - var winningRegion1 = GenerateUniqueRandomNumbers(5, 0, 99); - var winningRegion2 = GenerateUniqueRandomNumbers(1, 0, 99)[0]; - - var drawDate = Instant.FromDateTimeUtc(DateTime.Today.AddDays(-1)); // Yesterday's date - - var totalPrizesAwarded = 0; - long totalPrizeAmount = 0; - - // Process each ticket - foreach (var ticket in tickets) + try { - var region1Matches = CountMatches(ticket.RegionOneNumbers, winningRegion1); - var region2Match = ticket.RegionTwoNumber == winningRegion2; - var reward = CalculateReward(region1Matches, region2Match); + _logger.LogInformation("Starting drawing lotteries..."); - if (reward > 0) + var now = SystemClock.Instance.GetCurrentInstant(); + + // All pending lottery tickets + var tickets = await db.Lotteries + .Where(l => l.DrawStatus == LotteryDrawStatus.Pending) + .ToListAsync(); + + if (tickets.Count == 0) { - var wallet = await walletService.GetWalletAsync(ticket.AccountId); - if (wallet != null) - { - await paymentService.CreateTransactionAsync( - payerWalletId: null, - payeeWalletId: wallet.Id, - currency: "isp", - amount: reward, - remarks: $"Lottery prize: {region1Matches} matches{(region2Match ? " + special" : "")}" - ); - totalPrizesAwarded++; - totalPrizeAmount += reward; - } + _logger.LogInformation("No pending lottery tickets"); + return; } - ticket.DrawStatus = LotteryDrawStatus.Drawn; - ticket.DrawDate = drawDate; + _logger.LogInformation("Found {Count} pending lottery tickets for draw", tickets.Count); + + // Generate winning numbers + var winningRegion1 = GenerateUniqueRandomNumbers(5, 0, 99); + var winningRegion2 = GenerateUniqueRandomNumbers(1, 0, 99)[0]; + + _logger.LogInformation("Winning numbers generated: Region1 [{Region1}], Region2 [{Region2}]", + string.Join(",", winningRegion1), winningRegion2); + + var drawDate = Instant.FromDateTimeUtc(new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, + DateTime.UtcNow.Day, 0, 0, 0, DateTimeKind.Utc).AddDays(-1)); // Yesterday's date + + var totalPrizesAwarded = 0; + long totalPrizeAmount = 0; + + // Process each ticket + foreach (var ticket in tickets) + { + var region1Matches = CountMatches(ticket.RegionOneNumbers, winningRegion1); + var region2Match = ticket.RegionTwoNumber == winningRegion2; + var reward = CalculateReward(region1Matches, region2Match); + + // Record match results + ticket.MatchedRegionOneNumbers = ticket.RegionOneNumbers.Intersect(winningRegion1).ToList(); + ticket.MatchedRegionTwoNumber = region2Match ? (int?)winningRegion2 : null; + + if (reward > 0) + { + var wallet = await walletService.GetWalletAsync(ticket.AccountId); + if (wallet != null) + { + await paymentService.CreateTransactionAsync( + payerWalletId: null, + payeeWalletId: wallet.Id, + currency: WalletCurrency.SourcePoint, + amount: reward, + remarks: $"Lottery prize: {region1Matches} matches{(region2Match ? " + special" : "")}" + ); + _logger.LogInformation( + "Awarded {Amount} to account {AccountId} for {Matches} matches{(Special ? \" + special\" : \"\")}", + reward, ticket.AccountId, region1Matches, region2Match ? " + special" : ""); + totalPrizesAwarded++; + totalPrizeAmount += reward; + } + else + { + _logger.LogWarning("Wallet not found for account {AccountId}, skipping prize award", + ticket.AccountId); + } + } + + ticket.DrawStatus = LotteryDrawStatus.Drawn; + ticket.DrawDate = drawDate; + } + + // Save the draw record + var lotteryRecord = new SnLotteryRecord + { + DrawDate = drawDate, + WinningRegionOneNumbers = winningRegion1, + WinningRegionTwoNumber = winningRegion2, + TotalTickets = tickets.Count, + TotalPrizesAwarded = totalPrizesAwarded, + TotalPrizeAmount = totalPrizeAmount + }; + + db.LotteryRecords.Add(lotteryRecord); + await db.SaveChangesAsync(); + + _logger.LogInformation("Daily lottery draw completed: {Prizes} prizes awarded, total amount {Amount}", + totalPrizesAwarded, totalPrizeAmount); } - - // Save the draw record - var lotteryRecord = new SnLotteryRecord + catch (Exception ex) { - DrawDate = drawDate, - WinningRegionOneNumbers = winningRegion1, - WinningRegionTwoNumber = winningRegion2, - TotalTickets = tickets.Count, - TotalPrizesAwarded = totalPrizesAwarded, - TotalPrizeAmount = totalPrizeAmount - }; - - db.LotteryRecords.Add(lotteryRecord); - await db.SaveChangesAsync(); + _logger.LogError(ex, "An error occurred during the daily lottery draw"); + throw; + } } -} +} \ No newline at end of file diff --git a/DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.Designer.cs b/DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.Designer.cs new file mode 100644 index 0000000..9dd1205 --- /dev/null +++ b/DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.Designer.cs @@ -0,0 +1,2620 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using DysonNetwork.Pass; +using DysonNetwork.Shared.GeoIp; +using DysonNetwork.Shared.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NodaTime; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace DysonNetwork.Pass.Migrations +{ + [DbContext(typeof(AppDatabase))] + [Migration("20251024154539_AddDetailLotteriesStatus")] + partial class AddDetailLotteriesStatus + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAbuseReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("reason"); + + b.Property("Resolution") + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("resolution"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("resolved_at"); + + b.Property("ResourceIdentifier") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("resource_identifier"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_abuse_reports"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_abuse_reports_account_id"); + + b.ToTable("abuse_reports", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ActivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("activated_at"); + + b.Property("AutomatedId") + .HasColumnType("uuid") + .HasColumnName("automated_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsSuperuser") + .HasColumnType("boolean") + .HasColumnName("is_superuser"); + + b.Property("Language") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("language"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("Nick") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("nick"); + + b.Property("Region") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("region"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_accounts"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_accounts_name"); + + b.ToTable("accounts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountAuthFactor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("Config") + .HasColumnType("jsonb") + .HasColumnName("config"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EnabledAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("enabled_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Secret") + .HasMaxLength(8196) + .HasColumnType("character varying(8196)") + .HasColumnName("secret"); + + b.Property("Trustworthy") + .HasColumnType("integer") + .HasColumnName("trustworthy"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_auth_factors"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_auth_factors_account_id"); + + b.ToTable("account_auth_factors", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountBadge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("ActivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("activated_at"); + + b.Property("Caption") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("caption"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Label") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("label"); + + b.Property>("Meta") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_badges"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_badges_account_id"); + + b.ToTable("badges", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccessToken") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("access_token"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("LastUsedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_used_at"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("ProvidedIdentifier") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("provided_identifier"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("provider"); + + b.Property("RefreshToken") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("refresh_token"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_connections"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_connections_account_id"); + + b.ToTable("account_connections", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountContact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("content"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsPrimary") + .HasColumnType("boolean") + .HasColumnName("is_primary"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_at"); + + b.HasKey("Id") + .HasName("pk_account_contacts"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_contacts_account_id"); + + b.ToTable("account_contacts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("ActiveBadge") + .HasColumnType("jsonb") + .HasColumnName("active_badge"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("Bio") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("bio"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthday"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("FirstName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("first_name"); + + b.Property("Gender") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("gender"); + + b.Property("LastName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("last_name"); + + b.Property("LastSeenAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_at"); + + b.Property>("Links") + .HasColumnType("jsonb") + .HasColumnName("links"); + + b.Property("Location") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("location"); + + b.Property("MiddleName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("middle_name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("Pronouns") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("pronouns"); + + b.Property("SocialCredits") + .HasColumnType("double precision") + .HasColumnName("social_credits"); + + b.Property("TimeZone") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("time_zone"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UsernameColor") + .HasColumnType("jsonb") + .HasColumnName("username_color"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_account_profiles"); + + b.HasIndex("AccountId") + .IsUnique() + .HasDatabaseName("ix_account_profiles_account_id"); + + b.ToTable("account_profiles", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("BlockedPermissions") + .HasColumnType("jsonb") + .HasColumnName("blocked_permissions"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("reason"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_punishments"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_punishments_account_id"); + + b.ToTable("punishments", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountRelationship", b => + { + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("RelatedId") + .HasColumnType("uuid") + .HasColumnName("related_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Status") + .HasColumnType("smallint") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("AccountId", "RelatedId") + .HasName("pk_account_relationships"); + + b.HasIndex("RelatedId") + .HasDatabaseName("ix_account_relationships_related_id"); + + b.ToTable("account_relationships", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("AppIdentifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("app_identifier"); + + b.Property("Attitude") + .HasColumnType("integer") + .HasColumnName("attitude"); + + b.Property("ClearedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("cleared_at"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsAutomated") + .HasColumnType("boolean") + .HasColumnName("is_automated"); + + b.Property("IsInvisible") + .HasColumnType("boolean") + .HasColumnName("is_invisible"); + + b.Property("IsNotDisturb") + .HasColumnType("boolean") + .HasColumnName("is_not_disturb"); + + b.Property("Label") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("label"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_statuses"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_statuses_account_id"); + + b.ToTable("account_statuses", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnActionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("action"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IpAddress") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ip_address"); + + b.Property("Location") + .HasColumnType("jsonb") + .HasColumnName("location"); + + b.Property>("Meta") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("session_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserAgent") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("user_agent"); + + b.HasKey("Id") + .HasName("pk_action_logs"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_action_logs_account_id"); + + b.ToTable("action_logs", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnApiKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("label"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("session_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_api_keys"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_api_keys_account_id"); + + b.HasIndex("SessionId") + .HasDatabaseName("ix_api_keys_session_id"); + + b.ToTable("api_keys", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthChallenge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("Audiences") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("audiences"); + + b.Property>("BlacklistFactors") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("blacklist_factors"); + + b.Property("ClientId") + .HasColumnType("uuid") + .HasColumnName("client_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("FailedAttempts") + .HasColumnType("integer") + .HasColumnName("failed_attempts"); + + b.Property("IpAddress") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ip_address"); + + b.Property("Location") + .HasColumnType("jsonb") + .HasColumnName("location"); + + b.Property("Nonce") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("nonce"); + + b.Property>("Scopes") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("scopes"); + + b.Property("StepRemain") + .HasColumnType("integer") + .HasColumnName("step_remain"); + + b.Property("StepTotal") + .HasColumnType("integer") + .HasColumnName("step_total"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserAgent") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("user_agent"); + + b.HasKey("Id") + .HasName("pk_auth_challenges"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_auth_challenges_account_id"); + + b.HasIndex("ClientId") + .HasDatabaseName("ix_auth_challenges_client_id"); + + b.ToTable("auth_challenges", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("device_id"); + + b.Property("DeviceLabel") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("device_label"); + + b.Property("DeviceName") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("device_name"); + + b.Property("Platform") + .HasColumnType("integer") + .HasColumnName("platform"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_auth_clients"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_auth_clients_account_id"); + + b.ToTable("auth_clients", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.Property("ChallengeId") + .HasColumnType("uuid") + .HasColumnName("challenge_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("LastGrantedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_granted_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_auth_sessions"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_auth_sessions_account_id"); + + b.HasIndex("ChallengeId") + .HasDatabaseName("ix_auth_sessions_challenge_id"); + + b.ToTable("auth_sessions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnCheckInResult", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BackdatedFrom") + .HasColumnType("timestamp with time zone") + .HasColumnName("backdated_from"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("RewardExperience") + .HasColumnType("integer") + .HasColumnName("reward_experience"); + + b.Property("RewardPoints") + .HasColumnType("numeric") + .HasColumnName("reward_points"); + + b.Property>("Tips") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("tips"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_check_in_results"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_check_in_results_account_id"); + + b.ToTable("account_check_in_results", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnExperienceRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BonusMultiplier") + .HasColumnType("double precision") + .HasColumnName("bonus_multiplier"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Delta") + .HasColumnType("bigint") + .HasColumnName("delta"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason"); + + b.Property("ReasonType") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason_type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_experience_records"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_experience_records_account_id"); + + b.ToTable("experience_records", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnLottery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DrawDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("draw_date"); + + b.Property("DrawStatus") + .HasColumnType("integer") + .HasColumnName("draw_status"); + + b.Property>("MatchedRegionOneNumbers") + .HasColumnType("jsonb") + .HasColumnName("matched_region_one_numbers"); + + b.Property("MatchedRegionTwoNumber") + .HasColumnType("integer") + .HasColumnName("matched_region_two_number"); + + b.Property("Multiplier") + .HasColumnType("integer") + .HasColumnName("multiplier"); + + b.Property>("RegionOneNumbers") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("region_one_numbers"); + + b.Property("RegionTwoNumber") + .HasColumnType("integer") + .HasColumnName("region_two_number"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_lotteries"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_lotteries_account_id"); + + b.ToTable("lotteries", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnLotteryRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DrawDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("draw_date"); + + b.Property("TotalPrizeAmount") + .HasColumnType("bigint") + .HasColumnName("total_prize_amount"); + + b.Property("TotalPrizesAwarded") + .HasColumnType("integer") + .HasColumnName("total_prizes_awarded"); + + b.Property("TotalTickets") + .HasColumnType("integer") + .HasColumnName("total_tickets"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property>("WinningRegionOneNumbers") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("winning_region_one_numbers"); + + b.Property("WinningRegionTwoNumber") + .HasColumnType("integer") + .HasColumnName("winning_region_two_number"); + + b.HasKey("Id") + .HasName("pk_lottery_records"); + + b.ToTable("lottery_records", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnMagicSpell", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property>("Meta") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("Spell") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("spell"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_magic_spells"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_magic_spells_account_id"); + + b.HasIndex("Spell") + .IsUnique() + .HasDatabaseName("ix_magic_spells_spell"); + + b.ToTable("magic_spells", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("key"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_permission_groups"); + + b.ToTable("permission_groups", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroupMember", b => + { + b.Property("GroupId") + .HasColumnType("uuid") + .HasColumnName("group_id"); + + b.Property("Actor") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("actor"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("GroupId", "Actor") + .HasName("pk_permission_group_members"); + + b.ToTable("permission_group_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionNode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Actor") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("actor"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("Area") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("area"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("GroupId") + .HasColumnType("uuid") + .HasColumnName("group_id"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("key"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Value") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("value"); + + b.HasKey("Id") + .HasName("pk_permission_nodes"); + + b.HasIndex("GroupId") + .HasDatabaseName("ix_permission_nodes_group_id"); + + b.HasIndex("Key", "Area", "Actor") + .HasDatabaseName("ix_permission_nodes_key_area_actor"); + + b.ToTable("permission_nodes", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_realms"); + + b.HasIndex("Slug") + .IsUnique() + .HasDatabaseName("ix_realms_slug"); + + b.ToTable("realms", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("RealmId", "AccountId") + .HasName("pk_realm_members"); + + b.ToTable("realm_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSocialCreditRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Delta") + .HasColumnType("double precision") + .HasColumnName("delta"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason"); + + b.Property("ReasonType") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason_type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_social_credit_records"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_social_credit_records_account_id"); + + b.ToTable("social_credit_records", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallets"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_wallets_account_id"); + + b.ToTable("wallets", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletCoupon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("Code") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("code"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DiscountAmount") + .HasColumnType("numeric") + .HasColumnName("discount_amount"); + + b.Property("DiscountRate") + .HasColumnType("double precision") + .HasColumnName("discount_rate"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Identifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("identifier"); + + b.Property("MaxUsage") + .HasColumnType("integer") + .HasColumnName("max_usage"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_coupons"); + + b.ToTable("wallet_coupons", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFund", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatorAccountId") + .HasColumnType("uuid") + .HasColumnName("creator_account_id"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Message") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("SplitType") + .HasColumnType("integer") + .HasColumnName("split_type"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("TotalAmount") + .HasColumnType("numeric") + .HasColumnName("total_amount"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_funds"); + + b.HasIndex("CreatorAccountId") + .HasDatabaseName("ix_wallet_funds_creator_account_id"); + + b.ToTable("wallet_funds", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFundRecipient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("FundId") + .HasColumnType("uuid") + .HasColumnName("fund_id"); + + b.Property("IsReceived") + .HasColumnType("boolean") + .HasColumnName("is_received"); + + b.Property("ReceivedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("received_at"); + + b.Property("RecipientAccountId") + .HasColumnType("uuid") + .HasColumnName("recipient_account_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_fund_recipients"); + + b.HasIndex("FundId") + .HasDatabaseName("ix_wallet_fund_recipients_fund_id"); + + b.HasIndex("RecipientAccountId") + .HasDatabaseName("ix_wallet_fund_recipients_recipient_account_id"); + + b.ToTable("wallet_fund_recipients", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletGift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BasePrice") + .HasColumnType("numeric") + .HasColumnName("base_price"); + + b.Property("CouponId") + .HasColumnType("uuid") + .HasColumnName("coupon_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("FinalPrice") + .HasColumnType("numeric") + .HasColumnName("final_price"); + + b.Property("GiftCode") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("gift_code"); + + b.Property("GifterId") + .HasColumnType("uuid") + .HasColumnName("gifter_id"); + + b.Property("IsOpenGift") + .HasColumnType("boolean") + .HasColumnName("is_open_gift"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("message"); + + b.Property("PaymentDetails") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payment_details"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("payment_method"); + + b.Property("RecipientId") + .HasColumnType("uuid") + .HasColumnName("recipient_id"); + + b.Property("RedeemedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("redeemed_at"); + + b.Property("RedeemerId") + .HasColumnType("uuid") + .HasColumnName("redeemer_id"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("SubscriptionId") + .HasColumnType("uuid") + .HasColumnName("subscription_id"); + + b.Property("SubscriptionIdentifier") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("subscription_identifier"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_gifts"); + + b.HasIndex("CouponId") + .HasDatabaseName("ix_wallet_gifts_coupon_id"); + + b.HasIndex("GiftCode") + .HasDatabaseName("ix_wallet_gifts_gift_code"); + + b.HasIndex("GifterId") + .HasDatabaseName("ix_wallet_gifts_gifter_id"); + + b.HasIndex("RecipientId") + .HasDatabaseName("ix_wallet_gifts_recipient_id"); + + b.HasIndex("RedeemerId") + .HasDatabaseName("ix_wallet_gifts_redeemer_id"); + + b.HasIndex("SubscriptionId") + .IsUnique() + .HasDatabaseName("ix_wallet_gifts_subscription_id"); + + b.ToTable("wallet_gifts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("AppIdentifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("app_identifier"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("PayeeWalletId") + .HasColumnType("uuid") + .HasColumnName("payee_wallet_id"); + + b.Property("ProductIdentifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("product_identifier"); + + b.Property("Remarks") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("remarks"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("TransactionId") + .HasColumnType("uuid") + .HasColumnName("transaction_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_payment_orders"); + + b.HasIndex("PayeeWalletId") + .HasDatabaseName("ix_payment_orders_payee_wallet_id"); + + b.HasIndex("TransactionId") + .HasDatabaseName("ix_payment_orders_transaction_id"); + + b.ToTable("payment_orders", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletPocket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("WalletId") + .HasColumnType("uuid") + .HasColumnName("wallet_id"); + + b.HasKey("Id") + .HasName("pk_wallet_pockets"); + + b.HasIndex("WalletId") + .HasDatabaseName("ix_wallet_pockets_wallet_id"); + + b.ToTable("wallet_pockets", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BasePrice") + .HasColumnType("numeric") + .HasColumnName("base_price"); + + b.Property("BegunAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("begun_at"); + + b.Property("CouponId") + .HasColumnType("uuid") + .HasColumnName("coupon_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("ended_at"); + + b.Property("Identifier") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("identifier"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("IsFreeTrial") + .HasColumnType("boolean") + .HasColumnName("is_free_trial"); + + b.Property("PaymentDetails") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payment_details"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("payment_method"); + + b.Property("RenewalAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("renewal_at"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_subscriptions"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_wallet_subscriptions_account_id"); + + b.HasIndex("CouponId") + .HasDatabaseName("ix_wallet_subscriptions_coupon_id"); + + b.HasIndex("Identifier") + .HasDatabaseName("ix_wallet_subscriptions_identifier"); + + b.HasIndex("Status") + .HasDatabaseName("ix_wallet_subscriptions_status"); + + b.HasIndex("AccountId", "Identifier") + .HasDatabaseName("ix_wallet_subscriptions_account_id_identifier"); + + b.HasIndex("AccountId", "IsActive") + .HasDatabaseName("ix_wallet_subscriptions_account_id_is_active"); + + b.ToTable("wallet_subscriptions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("PayeeWalletId") + .HasColumnType("uuid") + .HasColumnName("payee_wallet_id"); + + b.Property("PayerWalletId") + .HasColumnType("uuid") + .HasColumnName("payer_wallet_id"); + + b.Property("Remarks") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("remarks"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_payment_transactions"); + + b.HasIndex("PayeeWalletId") + .HasDatabaseName("ix_payment_transactions_payee_wallet_id"); + + b.HasIndex("PayerWalletId") + .HasDatabaseName("ix_payment_transactions_payer_wallet_id"); + + b.ToTable("payment_transactions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAbuseReport", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_abuse_reports_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountAuthFactor", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("AuthFactors") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_auth_factors_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountBadge", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Badges") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_badges_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountConnection", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Connections") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_connections_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountContact", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Contacts") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_contacts_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountProfile", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithOne("Profile") + .HasForeignKey("DysonNetwork.Shared.Models.SnAccountProfile", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_profiles_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountPunishment", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_punishments_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountRelationship", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("OutgoingRelationships") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Related") + .WithMany("IncomingRelationships") + .HasForeignKey("RelatedId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_related_id"); + + b.Navigation("Account"); + + b.Navigation("Related"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountStatus", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_statuses_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnActionLog", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_action_logs_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnApiKey", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_keys_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAuthSession", "Session") + .WithMany() + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_keys_auth_sessions_session_id"); + + b.Navigation("Account"); + + b.Navigation("Session"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthChallenge", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Challenges") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_challenges_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAuthClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .HasConstraintName("fk_auth_challenges_auth_clients_client_id"); + + b.Navigation("Account"); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthClient", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_clients_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthSession", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Sessions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_sessions_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAuthChallenge", "Challenge") + .WithMany() + .HasForeignKey("ChallengeId") + .HasConstraintName("fk_auth_sessions_auth_challenges_challenge_id"); + + b.Navigation("Account"); + + b.Navigation("Challenge"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnCheckInResult", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_check_in_results_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnExperienceRecord", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_experience_records_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnLottery", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_lotteries_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnMagicSpell", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .HasConstraintName("fk_magic_spells_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroupMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPermissionGroup", "Group") + .WithMany("Members") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_permission_group_members_permission_groups_group_id"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionNode", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPermissionGroup", "Group") + .WithMany("Nodes") + .HasForeignKey("GroupId") + .HasConstraintName("fk_permission_nodes_permission_groups_group_id"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany("Members") + .HasForeignKey("RealmId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_realm_members_realms_realm_id"); + + b.Navigation("Realm"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSocialCreditRecord", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_social_credit_records_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallets_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFund", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "CreatorAccount") + .WithMany() + .HasForeignKey("CreatorAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_funds_accounts_creator_account_id"); + + b.Navigation("CreatorAccount"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFundRecipient", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWalletFund", "Fund") + .WithMany("Recipients") + .HasForeignKey("FundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_fund_recipients_wallet_funds_fund_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "RecipientAccount") + .WithMany() + .HasForeignKey("RecipientAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_fund_recipients_accounts_recipient_account_id"); + + b.Navigation("Fund"); + + b.Navigation("RecipientAccount"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletGift", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWalletCoupon", "Coupon") + .WithMany() + .HasForeignKey("CouponId") + .HasConstraintName("fk_wallet_gifts_wallet_coupons_coupon_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Gifter") + .WithMany() + .HasForeignKey("GifterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_gifts_accounts_gifter_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Recipient") + .WithMany() + .HasForeignKey("RecipientId") + .HasConstraintName("fk_wallet_gifts_accounts_recipient_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Redeemer") + .WithMany() + .HasForeignKey("RedeemerId") + .HasConstraintName("fk_wallet_gifts_accounts_redeemer_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWalletSubscription", "Subscription") + .WithOne("Gift") + .HasForeignKey("DysonNetwork.Shared.Models.SnWalletGift", "SubscriptionId") + .HasConstraintName("fk_wallet_gifts_wallet_subscriptions_subscription_id"); + + b.Navigation("Coupon"); + + b.Navigation("Gifter"); + + b.Navigation("Recipient"); + + b.Navigation("Redeemer"); + + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletOrder", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "PayeeWallet") + .WithMany() + .HasForeignKey("PayeeWalletId") + .HasConstraintName("fk_payment_orders_wallets_payee_wallet_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWalletTransaction", "Transaction") + .WithMany() + .HasForeignKey("TransactionId") + .HasConstraintName("fk_payment_orders_payment_transactions_transaction_id"); + + b.Navigation("PayeeWallet"); + + b.Navigation("Transaction"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletPocket", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "Wallet") + .WithMany("Pockets") + .HasForeignKey("WalletId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_pockets_wallets_wallet_id"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletSubscription", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_subscriptions_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWalletCoupon", "Coupon") + .WithMany() + .HasForeignKey("CouponId") + .HasConstraintName("fk_wallet_subscriptions_wallet_coupons_coupon_id"); + + b.Navigation("Account"); + + b.Navigation("Coupon"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletTransaction", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "PayeeWallet") + .WithMany() + .HasForeignKey("PayeeWalletId") + .HasConstraintName("fk_payment_transactions_wallets_payee_wallet_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "PayerWallet") + .WithMany() + .HasForeignKey("PayerWalletId") + .HasConstraintName("fk_payment_transactions_wallets_payer_wallet_id"); + + b.Navigation("PayeeWallet"); + + b.Navigation("PayerWallet"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccount", b => + { + b.Navigation("AuthFactors"); + + b.Navigation("Badges"); + + b.Navigation("Challenges"); + + b.Navigation("Connections"); + + b.Navigation("Contacts"); + + b.Navigation("IncomingRelationships"); + + b.Navigation("OutgoingRelationships"); + + b.Navigation("Profile") + .IsRequired(); + + b.Navigation("Sessions"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroup", b => + { + b.Navigation("Members"); + + b.Navigation("Nodes"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => + { + b.Navigation("Pockets"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFund", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletSubscription", b => + { + b.Navigation("Gift"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.cs b/DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.cs new file mode 100644 index 0000000..d926a12 --- /dev/null +++ b/DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DysonNetwork.Pass.Migrations +{ + /// + public partial class AddDetailLotteriesStatus : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn>( + name: "matched_region_one_numbers", + table: "lotteries", + type: "jsonb", + nullable: true); + + migrationBuilder.AddColumn( + name: "matched_region_two_number", + table: "lotteries", + type: "integer", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "matched_region_one_numbers", + table: "lotteries"); + + migrationBuilder.DropColumn( + name: "matched_region_two_number", + table: "lotteries"); + } + } +} diff --git a/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs b/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs index 592065a..a663138 100644 --- a/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs +++ b/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs @@ -1086,6 +1086,14 @@ namespace DysonNetwork.Pass.Migrations .HasColumnType("integer") .HasColumnName("draw_status"); + b.Property>("MatchedRegionOneNumbers") + .HasColumnType("jsonb") + .HasColumnName("matched_region_one_numbers"); + + b.Property("MatchedRegionTwoNumber") + .HasColumnType("integer") + .HasColumnName("matched_region_two_number"); + b.Property("Multiplier") .HasColumnType("integer") .HasColumnName("multiplier"); diff --git a/DysonNetwork.Shared/Models/SnLottery.cs b/DysonNetwork.Shared/Models/SnLottery.cs index 0b2256d..46b4089 100644 --- a/DysonNetwork.Shared/Models/SnLottery.cs +++ b/DysonNetwork.Shared/Models/SnLottery.cs @@ -30,20 +30,25 @@ public class SnLotteryRecord : ModelBase public class SnLottery : ModelBase { - public Guid Id { get; set; } = Guid.NewGuid(); + public Guid Id { get; init; } = Guid.NewGuid(); - public SnAccount Account { get; set; } = null!; - public Guid AccountId { get; set; } + public SnAccount Account { get; init; } = null!; + public Guid AccountId { get; init; } [Column(TypeName = "jsonb")] - public List RegionOneNumbers { get; set; } = new(); // 5 numbers, 0-99, unique + public List RegionOneNumbers { get; set; } = []; // 5 numbers, 0-99, unique [Range(0, 99)] - public int RegionTwoNumber { get; set; } // 1 number, 0-99, can repeat + public int RegionTwoNumber { get; init; } // 1 number, 0-99, can repeat - public int Multiplier { get; set; } = 1; // Default 1x + public int Multiplier { get; init; } = 1; // Default 1x public LotteryDrawStatus DrawStatus { get; set; } = LotteryDrawStatus.Pending; // Status to track draw processing public Instant? DrawDate { get; set; } // Date when this ticket was drawn + + [Column(TypeName = "jsonb")] + public List? MatchedRegionOneNumbers { get; set; } // The actual numbers that matched in region one + + public int? MatchedRegionTwoNumber { get; set; } // The matched number if special number matched (null otherwise) } diff --git a/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs b/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs index 94a222a..34169c4 100644 --- a/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs +++ b/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs @@ -93,7 +93,7 @@ public class BroadcastEventHandler( break; } default: - await msg.NakAsync(cancellationToken: stoppingToken); + // ignore break; } }