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;
}