namespace EntitlementBLL.Onboarding; // Wire-contract DTOs for calling SqlWorkbench's real HTTP endpoints (ClientDatabase.svc, // ChangeRequest.svc). Deliberately NOT a project reference to SwDAL — no precedent anywhere // in this repo for one module's BLL referencing another module's DAL/BLL types directly // (confirmed: the only existing cross-module pattern, PAY -> Sales/Finance via // MmIntegrationService, goes over a named HttpClient with its own local request/response // shapes). Field names must match SW's own DTOs exactly — every GB5 host serializes with // PropertyNamingPolicy = null (PascalCase preserved), confirmed live against these same // endpoints in an earlier thread. /// Mirrors SwDAL.DTO.ClientDatabase.ClientDatabaseDTO — only the fields /// SaveClientDatabase actually needs from a caller; the rest are server-populated. public class SwSaveClientDatabaseRequest { public int ClientDbId { get; set; } public string ClientDbCode { get; set; } = string.Empty; public string ClientDbName { get; set; } = string.Empty; public int DbServerId { get; set; } public string DatabaseName { get; set; } = string.Empty; public int DbModelId { get; set; } public byte ClientDbStatus { get; set; } // 0 = Pending public string? Description { get; set; } public byte DatabaseRole { get; set; } // 0 = Main public int TenantId { get; set; } } /// Mirrors SwDAL.DTO.ChangeRequest.ChangeRequestDTO — only the fields a /// ClientProvisioning/FromScripts submission needs. public class SwSaveChangeRequestRequest { public int ChangeRequestId { get; set; } public string Title { get; set; } = string.Empty; public string? Description { get; set; } public int ClientDatabaseId { get; set; } public byte QueryType { get; set; } = 4; // DDL public byte Category { get; set; } = 6; // ChangeRequestCategory.ClientProvisioning public byte ProvisioningMode { get; set; } = 2; // ProvisioningMode.FromScripts public int BaselineUpgradePackageId { get; set; } public int TenantId { get; set; } } /// Just enough of ChangeRequestDTO's real shape to check status after Execute. /// ChangeRequestStatus enum (SwDAL.Enums.SwEnums): Draft=0 Submitted=1 UnderReview=2 /// Approved=3 Rejected=4 Executed=5. public class SwChangeRequestStatusDTO { public int ChangeRequestId { get; set; } public byte CrStatus { get; set; } /// Background-execution state (tracker §37/§43) — mirrors SwDAL's own /// ChangeRequestExecutionStatus byte values: 0=NotQueued 1=Queued 2=Running 3=Done 4=Failed. /// Only meaningful for a CR submitted via QueueChangeRequestExecutionAsync; every /// synchronously-executed CR (the AutoApprove path used before this) stays 0/NotQueued even /// after CrStatus reaches Executed. Lets ResumeOneJobAsync distinguish "still queued/running, /// keep waiting" from "genuinely failed" — a failed background execution never reaches /// CrStatus=Executed at all, so CrStatus alone can't tell the two apart. public byte ExecutionStatus { get; set; } public int ClientDatabaseId { get; set; } /// Tracker §37 Decision 2 — real-time DDL execution progress, populated /// server-side only when this CR's Category == ClientProvisioning. Null otherwise. public int? ScriptsDone { get; set; } public int? ScriptsTotal { get; set; } } /// Mirrors SwDAL.DTO.UpgradePackage.PackageScopeFilterDTO — all fields optional; a /// null field simply excludes that scope's overlay packages from resolution, per /// GetProvisioningChain's own contract. Not yet populated from any real caller-supplied /// data (no UI collects partner/industry/country yet) — passed as an all-null filter today, /// which resolves to Universal packages only. public class SwPackageScopeFilterRequest { public string? PartnerProductCode { get; set; } public string? IndustryCode { get; set; } public string? CountryCode { get; set; } public string? ClientCode { get; set; } } /// Mirrors SwDAL.DTO.UpgradePackage.PackageChainItemDTO. public class SwPackageChainItemDTO { public int PackageId { get; set; } public string PackageCode { get; set; } = string.Empty; public string PackageName { get; set; } = string.Empty; public short SequenceInChain { get; set; } public byte ScopeType { get; set; } } /// Just enough of SwDAL.DTO.ClientDatabase.ClientDatabaseDTO's real shape (tracker §49 /// Decision 8's corrected design) for Entitlement to build a LoginDTO pointed directly at a /// pooled demo instance's own physical database — DatabaseName + ServerConfigId is all /// IQueryExecutor/ApplicationConnection need to resolve a connection, the exact same mechanism /// every other multi-tenant call in this codebase already uses. No new SqlWorkbench endpoint: /// GET /ClientDatabase/GetClientDatabaseById already returns this. public class SwClientDatabaseInfoDTO { public int ClientDbId { get; set; } /// Needed, not DatabaseName, to build a LoginDTO Entitlement's own IQueryExecutor /// can actually resolve — confirmed by reading ApplicationConnection.DatabaseConnectionObject /// directly: it looks up MSERVERCONFIG by CONNECTIONNAME, not the raw physical database name. /// ClientDatabaseProvisioner.RegisterAndLinkServerConfigAsync registers that name as exactly /// $"{ClientDbCode}-{DatabaseRole}".ToUpperInvariant() — "{CLIENTDBCODE}-MAIN" for every /// pooled demo instance, since those are always Main-role databases. public string ClientDbCode { get; set; } = string.Empty; public string DatabaseName { get; set; } = string.Empty; public int DbServerId { get; set; } public int? ServerConfigId { get; set; } }