using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace LittleShop.Models; public class Customer { [Key] public Guid Id { get; set; } // Telegram Information [Required] public long TelegramUserId { get; set; } [StringLength(100)] public string TelegramUsername { get; set; } = string.Empty; [Required] [StringLength(200)] public string TelegramDisplayName { get; set; } = string.Empty; [StringLength(50)] public string TelegramFirstName { get; set; } = string.Empty; [StringLength(50)] public string TelegramLastName { get; set; } = string.Empty; // Optional Contact Information (if customer provides) [StringLength(100)] public string? Email { get; set; } [StringLength(20)] public string? PhoneNumber { get; set; } // Customer Preferences public bool AllowMarketing { get; set; } = false; public bool AllowOrderUpdates { get; set; } = true; [StringLength(10)] public string Language { get; set; } = "en"; [StringLength(10)] public string Timezone { get; set; } = "UTC"; // Customer Metrics public int TotalOrders { get; set; } = 0; [Column(TypeName = "decimal(18,2)")] public decimal TotalSpent { get; set; } = 0; [Column(TypeName = "decimal(18,2)")] public decimal AverageOrderValue { get; set; } = 0; public DateTime FirstOrderDate { get; set; } public DateTime LastOrderDate { get; set; } // Customer Service Notes [StringLength(2000)] public string? CustomerNotes { get; set; } public bool IsBlocked { get; set; } = false; [StringLength(500)] public string? BlockReason { get; set; } // Risk Assessment public int RiskScore { get; set; } = 0; // 0-100, 0 = trusted, 100 = high risk public int SuccessfulOrders { get; set; } = 0; public int CancelledOrders { get; set; } = 0; public int DisputedOrders { get; set; } = 0; // Data Management public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; public DateTime LastActiveAt { get; set; } = DateTime.UtcNow; public DateTime? DataRetentionDate { get; set; } // When to delete this customer's data public bool IsActive { get; set; } = true; // Navigation properties public virtual ICollection Orders { get; set; } = new List(); public virtual ICollection Messages { get; set; } = new List(); // Calculated Properties public string DisplayName => !string.IsNullOrEmpty(TelegramDisplayName) ? TelegramDisplayName : !string.IsNullOrEmpty(TelegramUsername) ? $"@{TelegramUsername}" : $"{TelegramFirstName} {TelegramLastName}".Trim(); public string CustomerType => TotalOrders == 0 ? "New" : TotalOrders == 1 ? "First-time" : TotalOrders < 5 ? "Regular" : TotalOrders < 20 ? "Loyal" : "VIP"; public void UpdateMetrics() { if (Orders?.Any() == true) { TotalOrders = Orders.Count(); TotalSpent = Orders.Sum(o => o.TotalAmount); AverageOrderValue = TotalOrders > 0 ? TotalSpent / TotalOrders : 0; FirstOrderDate = Orders.Min(o => o.CreatedAt); LastOrderDate = Orders.Max(o => o.CreatedAt); SuccessfulOrders = Orders.Count(o => o.Status == Enums.OrderStatus.Delivered); CancelledOrders = Orders.Count(o => o.Status == Enums.OrderStatus.Cancelled); } UpdatedAt = DateTime.UtcNow; // Update risk score based on order history CalculateRiskScore(); } private void CalculateRiskScore() { int score = 0; // New customers have moderate risk if (TotalOrders == 0) score += 30; // High cancellation rate increases risk if (TotalOrders > 0) { var cancellationRate = (double)CancelledOrders / TotalOrders; if (cancellationRate > 0.5) score += 40; else if (cancellationRate > 0.3) score += 20; } // Disputes increase risk significantly score += DisputedOrders * 25; // Long-term customers with good history reduce risk if (TotalOrders > 10 && SuccessfulOrders > 8) score -= 20; if (TotalSpent > 500) score -= 10; // Clamp between 0-100 RiskScore = Math.Max(0, Math.Min(100, score)); } }