feat: normalize subscription architecture, integrate pgvector, and implement Stripe webhook subscription management.

This commit is contained in:
2026-05-05 15:07:48 +02:00
parent e21c24b66d
commit 311eaa8b04
29 changed files with 1699 additions and 199 deletions
+25 -9
View File
@@ -1,34 +1,49 @@
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace NexusReader.Domain.Entities;
/// <summary>
/// Extended Identity user for the Nexus AI E-Reader SaaS platform.
/// </summary>
public class NexusUser : IdentityUser
{
/// <summary>
/// Total number of AI tokens allowed for the current billing period.
/// User's display name or full name.
/// </summary>
[MaxLength(100)]
public string? DisplayName { get; set; }
/// <summary>
/// Total AI tokens available for the user (depends on subscription).
/// </summary>
public int AITokenLimit { get; set; }
/// <summary>
/// Number of AI tokens consumed in the current billing period.
/// AI tokens consumed by the user in the current billing period.
/// </summary>
public int AITokensUsed { get; set; }
/// <summary>
/// Unique identifier for the tenant (SaaS multi-tenancy support).
/// Date when the user last performed an AI-related action.
/// </summary>
public DateTime? LastAiActionDate { get; set; }
/// <summary>
/// Multi-tenant identifier.
/// </summary>
[Required]
[MaxLength(128)]
public string TenantId { get; set; } = "global";
/// <summary>
/// Current subscription plan (e.g., "Free", "Pro", "Enterprise").
/// Foreign key for the current subscription plan.
/// </summary>
public string CurrentPlan { get; set; } = "Free";
[Required]
public int SubscriptionPlanId { get; set; }
/// <summary>
/// Navigation property for the current subscription plan.
/// </summary>
public SubscriptionPlan? SubscriptionPlan { get; set; }
/// <summary>
/// Collection of e-books owned by the user.
@@ -43,10 +58,11 @@ public class NexusUser : IdentityUser
/// <summary>
/// ID of the last page read by the user.
/// </summary>
[MaxLength(255)]
public string? LastReadPageId { get; set; }
/// <summary>
/// Timestamp of the last reading progress update.
/// Last read timestamp.
/// </summary>
public DateTime? LastReadAt { get; set; }
}