using System.Text.Json; using Tiku.Domain.Common; namespace Tiku.Domain.Growth; public sealed class ReferralTrack : AuditableTenantEntity { public Guid? LeadId { get; set; } public Guid? ReferrerUserId { get; set; } public Guid? TargetUserId { get; set; } public string? LegacyId { get; set; } public string EventType { get; set; } = string.Empty; public string? RefCode { get; set; } public string? Source { get; set; } public string? IpAddress { get; set; } public string? UserAgent { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); } public sealed class ReferralCode : AuditableTenantEntity { public Guid UserId { get; set; } public string Code { get; set; } = string.Empty; public ReferralCodeStatus Status { get; set; } = ReferralCodeStatus.Active; public string? Channel { get; set; } public string? LandingPath { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); } public sealed class ReferralLead : AuditableTenantEntity { public Guid StudentUserId { get; set; } public Guid? ReferrerUserId { get; set; } public Guid? FirstTrackId { get; set; } public Guid? AssignedToUserId { get; set; } public Guid? AssignedBy { get; set; } public string? RefCode { get; set; } public string? Source { get; set; } public ReferralLeadBindType BindType { get; set; } = ReferralLeadBindType.FirstTouch; public ReferralLeadStatus Status { get; set; } = ReferralLeadStatus.Protected; public DateTimeOffset? ProtectedUntil { get; set; } public ReferralAssignmentMode? AssignmentMode { get; set; } public DateTimeOffset? AssignedAt { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); public DateTimeOffset BoundAt { get; set; } = DateTimeOffset.UtcNow; } public sealed class ReferralTeamEdge : AuditableTenantEntity { public Guid MemberUserId { get; set; } public Guid? LeaderUserId { get; set; } public ReferralTeamRelationType RelationType { get; set; } = ReferralTeamRelationType.SalesTeam; public ReferralTeamEdgeStatus Status { get; set; } = ReferralTeamEdgeStatus.Active; public JsonElement Metadata { get; set; } = JsonDefaults.Object(); } public sealed class ReferralQrcode : AuditableTenantEntity { public Guid? UserId { get; set; } public string RefCode { get; set; } = string.Empty; public string Scene { get; set; } = string.Empty; public string Page { get; set; } = "pages/index/index"; public string Provider { get; set; } = "wechat-miniapp"; public string? QrcodeUrl { get; set; } public ReferralQrcodeStatus Status { get; set; } = ReferralQrcodeStatus.Pending; public string? ErrorMessage { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); } public sealed class CrmConfig : AuditableTenantEntity { public bool Enabled { get; set; } public string? Url { get; set; } public string? SecretRef { get; set; } public string? FormName { get; set; } public string? ExamType { get; set; } public int? TimeoutSeconds { get; set; } public int? DelaySeconds { get; set; } public ReferralAssignmentMode AssignmentMode { get; set; } = ReferralAssignmentMode.None; public JsonElement AssignmentPool { get; set; } = JsonDefaults.Array(); public int AssignmentCursor { get; set; } public JsonElement AssignmentConfig { get; set; } = JsonDefaults.Object(); } public sealed class CrmWebhookQueueItem : AuditableTenantEntity { public string? LegacyId { get; set; } public string? RecordId { get; set; } public string? LeadId { get; set; } public string? Source { get; set; } public string? Provider { get; set; } public CrmWebhookQueueStatus Status { get; set; } = CrmWebhookQueueStatus.Pending; public DateTimeOffset? ScheduledAt { get; set; } public int Attempts { get; set; } public DateTimeOffset? NextAttemptAt { get; set; } public DateTimeOffset? LastAttemptAt { get; set; } public string? LastError { get; set; } public int? LastHttpCode { get; set; } public string? LastResponseSummary { get; set; } public DateTimeOffset? SentAt { get; set; } public string? IdempotencyKey { get; set; } public string? TargetUrl { get; set; } public JsonElement Payload { get; set; } = JsonDefaults.Object(); } public sealed class CrmWebhookLog : AuditableTenantEntity { public string? LegacyId { get; set; } public string? RecordId { get; set; } public string? LeadId { get; set; } public int? HttpCode { get; set; } public string? Outcome { get; set; } public string? ErrorMessage { get; set; } public string? RequestBody { get; set; } public JsonElement RequestPayload { get; set; } = JsonDefaults.Object(); public string? ResponseSummary { get; set; } public DateTimeOffset? SignedAt { get; set; } public int? Attempt { get; set; } } public sealed class TenantCommissionSetting : AuditableTenantEntity { public decimal DefaultRate { get; set; } = 0.2m; public int MinSettlementCents { get; set; } public CommissionSettlementCycle SettlementCycle { get; set; } = CommissionSettlementCycle.Monthly; public JsonElement Config { get; set; } = JsonDefaults.Object(); public Guid? UpdatedBy { get; set; } } public sealed class CommissionSettlement : AuditableTenantEntity { public Guid ReferrerUserId { get; set; } public Guid? GeneratedBy { get; set; } public Guid? ReviewedBy { get; set; } public Guid? PaidBy { get; set; } public string SettlementNo { get; set; } = string.Empty; public CommissionSettlementStatus Status { get; set; } = CommissionSettlementStatus.Draft; public DateOnly PeriodStart { get; set; } public DateOnly PeriodEnd { get; set; } public int SourceCount { get; set; } public int PaidUserCount { get; set; } public int GrossAmountCents { get; set; } public int CommissionAmountCents { get; set; } public decimal DefaultRate { get; set; } public decimal? EffectiveRate { get; set; } public DateTimeOffset? ReviewedAt { get; set; } public DateTimeOffset? PaidAt { get; set; } public string? PaymentMethod { get; set; } public string? PaymentAccount { get; set; } public string? Remark { get; set; } public JsonElement Metadata { get; set; } = JsonDefaults.Object(); } public sealed class CommissionSettlementItem : AuditableTenantEntity { public Guid? SettlementId { get; set; } public Guid ReferrerUserId { get; set; } public Guid? StudentUserId { get; set; } public CommissionSourceType SourceType { get; set; } = CommissionSourceType.Order; public Guid SourceId { get; set; } public string? SourceNo { get; set; } public DateTimeOffset? SourcePaidAt { get; set; } public int GrossAmountCents { get; set; } public decimal CommissionRate { get; set; } public int CommissionAmountCents { get; set; } public CommissionRateSource RateSource { get; set; } = CommissionRateSource.Default; public string AttributionType { get; set; } = "protected_lead"; public JsonElement Metadata { get; set; } = JsonDefaults.Object(); } public enum ReferralCodeStatus { Active, Disabled } public enum ReferralLeadBindType { FirstTouch, Manual, Imported } public enum ReferralLeadStatus { Protected, Invalid, Released } public enum ReferralAssignmentMode { None, Direct, RoundRobin, Referrer } public enum ReferralTeamRelationType { SalesTeam, AgentNetwork, TeacherClass } public enum ReferralTeamEdgeStatus { Active, Disabled } public enum ReferralQrcodeStatus { Pending, Ready, Failed, Disabled } public enum CrmWebhookQueueStatus { Pending, Processing, Retrying, Sent, Failed, Discarded } public enum CommissionSettlementCycle { Manual, Weekly, Monthly } public enum CommissionSettlementStatus { Draft, PendingReview, Approved, Paid, Rejected, Cancelled } public enum CommissionSourceType { Order, ActivationCode } public enum CommissionRateSource { Batch, Member, Default }