namespace EntitlementDAL.DTOs; /// Thread 3 (Demo/DemoDB, tracker §49) — one demo "flavor" (industry x geography x /// period), the pool it draws from, and the seed package used to (re)populate it. public class DemoVariantDTO { public int DemoVariantId { get; set; } public string VariantCode { get; set; } = string.Empty; public string VariantName { get; set; } = string.Empty; /// TPARTNERPRODUCT.PartnerProductId — soft reference, no hard FK (mirrors /// MENTITLEMENTPLAN.PartnerProductId's own convention). Null = GB5 default. public int? PartnerProductId { get; set; } /// FK -> MENTITLEMENTPLAN.PlanId — which tier/bundle this variant showcases (e.g. /// "TMS Standard" vs "TMS Professional"). public int? PlanId { get; set; } public string IndustryCode { get; set; } = string.Empty; public string GeographyCode { get; set; } = string.Empty; public string PeriodTag { get; set; } = string.Empty; /// FK -> MENTITLEMENTFEATURE.FeatureId — set when this variant is curated to /// showcase one specific feature rather than/in addition to a whole industry scenario. public int? FeatureId { get; set; } /// JSON array of role codes a prospect may request at Pooled checkout (e.g. /// ["TMS_TRAINER","TMS_LEARNER","TMS_AUTHOR"]) — informational only, validated against real /// MROLE rows inside the pool instance's own database at checkout time. public string AvailableDemoRoleCodes { get; set; } = "[]"; public int DbModelId { get; set; } public int? SeedPackageId { get; set; } /// JSON array of table names safe to clear on a pooled reset — everything else in /// the seed package is treated as fixed reference data, never touched by demo interaction. public string MutableTableList { get; set; } = "[]"; public int PoolTargetSize { get; set; } public short Version { get; set; } public byte Status { get; set; } = 1; public int SortOrder { get; set; } public int CreatedById { get; set; } public DateTime CreatedOn { get; set; } public int ModifiedById { get; set; } public DateTime ModifiedOn { get; set; } public byte SourceType { get; set; } public int TenantId { get; set; } = -1; } public enum DemoPoolState : byte { Available = 0, CheckedOut = 1, Resetting = 2, Retired = 3, } /// One pre-provisioned physical database backing a variant's pool. public class DemoPoolInstanceDTO { public int DemoPoolInstanceId { get; set; } public int DemoVariantId { get; set; } /// SW.MSWCLIENTDATABASE.CLIENTDBID — a plain portable integer, not a real FK (that /// table lives in a physically separate database, same convention as /// MPROVISIONINGJOB.SwClientDatabaseId). public int SwClientDatabaseId { get; set; } /// The pool instance's own physical database has its own local, pre-seeded "demo /// tenant" MCLIENT row — this is its ClientId, used to build a LoginDTO pointed directly at /// that database when creating a real per-prospect MUSER there (Decision 8/9). Portable, not /// a real FK, for the same cross-database reason as SwClientDatabaseId above. Defaults to -1 /// ("not yet known/registered"). public int LocalClientId { get; set; } = -1; public byte PoolState { get; set; } public short Version { get; set; } public byte Status { get; set; } = 1; public int SortOrder { get; set; } public int CreatedById { get; set; } public DateTime CreatedOn { get; set; } public int ModifiedById { get; set; } public DateTime ModifiedOn { get; set; } public byte SourceType { get; set; } public int TenantId { get; set; } = -1; } public enum DemoMode : byte { Pooled = 0, Dedicated = 1, } public enum DemoSessionStatus : byte { Active = 0, PendingApproval = 1, Extended = 2, WarningIssued = 3, Expired = 4, TornDown = 5, } /// One active (or historical) demo engagement — Pooled or Dedicated. public class DemoSessionDTO { public int DemoSessionId { get; set; } public int? DemoVariantId { get; set; } public byte DemoMode { get; set; } public int? DemoPoolInstanceId { get; set; } /// CORRECTED (tracker §49 Decision 9) — a real, required MCLIENT.ClientId in BOTH /// modes now, created by a lightweight registration call (ClientProvisioningBLL.CreateClientAsync) /// before any session is created. Dedicated mode additionally provisions a real physical DB /// for this same ClientId via StartOnboardingAsync; Pooled mode just claims a pool instance. public int ClientId { get; set; } /// Pooled only — portable (non-FK) int: the real per-prospect MUSER row created /// inside the pool instance's own separate physical database at checkout time, sourced from /// the central ClientId's own Name/Email (Decision 8/9 — designed, not yet built). public int? PooledDemoUserId { get; set; } /// Real FK -> TLEAD.LeadId — CORRECTED from an earlier, non-FK portable-int design /// (TLEAD lives in this same shared platform database, not a separate one). Left nullable /// rather than a NOT NULL/-1 sentinel: TLEAD carries 9+ of its own NOT NULL FK constraints, /// making a safe sentinel row a real, unverified cross-module undertaking — null = "no lead" /// imposes no such risk. Set directly for a Direction-B (sales-exec-initiated) session. public int? LeadId { get; set; } public int OwnerUserId { get; set; } /// Pooled only — the role the prospect requested at checkout (e.g. "TMS_TRAINER"), /// resolved against a real MROLE row inside the pool instance's own database when /// PooledDemoUserId was created. Stored here for reporting/audit only. public string? DemoRoleCode { get; set; } public DateTime StartedOn { get; set; } public DateTime ExpiresOn { get; set; } public DateTime? ExtensionRequestedOn { get; set; } public int? ExtensionApprovedById { get; set; } public DateTime? ExtensionApprovedOn { get; set; } public string? ExtensionComment { get; set; } public byte SessionStatus { get; set; } public short Version { get; set; } public byte Status { get; set; } = 1; public int SortOrder { get; set; } public int CreatedById { get; set; } public DateTime CreatedOn { get; set; } public int ModifiedById { get; set; } public DateTime ModifiedOn { get; set; } public byte SourceType { get; set; } public int TenantId { get; set; } = -1; } public class DemoSessionEventDTO { public int DemoSessionEventId { get; set; } public int DemoSessionId { get; set; } public string EventType { get; set; } = string.Empty; public DateTime EventOn { get; set; } public string? EventComment { get; set; } public int CreatedById { get; set; } public DateTime CreatedOn { get; set; } public int TenantId { get; set; } = -1; } public static class DemoSessionEventType { public const string CheckedOut = "CheckedOut"; public const string ExtensionRequested = "ExtensionRequested"; public const string ExtensionApproved = "ExtensionApproved"; public const string ExtensionRejected = "ExtensionRejected"; public const string WarningIssued = "WarningIssued"; public const string Expired = "Expired"; public const string TornDown = "TornDown"; } /// Tracker §49 Decision 9 — captured at the SAME lightweight registration call that /// creates the central MCLIENT/MUSER account (ClientProvisioningBLL.CreateClientAsync), one row /// per ClientId. Drives MDEMOVARIANT selection/recommendation; not a demo-only concept — this is /// the same central "GB instance" account model Thread 0 §1.5 already manages preferences, /// license, and payment through. public class DemoPreferenceDTO { public int ClientId { get; set; } /// Soft reference, no hard FK — mirrors MDEMOVARIANT.PartnerProductId's own convention. public int? PreferredPartnerProductId { get; set; } public int? PreferredPlanId { get; set; } public string PreferredIndustryCode { get; set; } = string.Empty; public string PreferredGeographyCode { get; set; } = string.Empty; public int? PreferredFeatureId { get; set; } public DateTime RequestedOn { get; set; } public short Version { get; set; } public byte Status { get; set; } = 1; public int SortOrder { get; set; } public int CreatedById { get; set; } public DateTime CreatedOn { get; set; } public int ModifiedById { get; set; } public DateTime ModifiedOn { get; set; } public byte SourceType { get; set; } public int TenantId { get; set; } = -1; }