7. Database Tables
All 6 tables live in the Saas schema of the central subscription/Saas database — the same database
Shumoul.MultiTenancyApi uses for tenants, subscriptions, and notifications. They do not live inside every
tenant database. The actual AppSettings rows these tables eventually influence are applied to each
tenant's own resolved database, but only through Shumoul.BackEnd (see Chapter 4 and
Chapter 10) — never written directly by Shumoul.MultiTenancyApi.
7.1 Saas.OnboardingSurveyDefinitions
One row per survey version. The seeder ships a single survey, default-business-setup, version 1.
| Column | Type | Notes |
|---|---|---|
Id | Guid | PK |
Code | string | e.g. default-business-setup |
NameAr / NameEn | string | Display names |
Version | int | The active survey is the highest Version with IsActive = true |
IsActive, DisplayOrder | (from BaseEntity) |
7.2 Saas.OnboardingQuestions
All questions across all survey steps, for all surveys.
| Column | Type | Notes |
|---|---|---|
Id | Guid | PK |
SurveyDefinitionId | Guid | FK → OnboardingSurveyDefinitions |
Key | string | Stable key used in AnswersJson and VisibleWhenJson, e.g. activityType |
TitleAr / TitleEn, DescriptionAr / DescriptionEn | string | Display text |
Type | OnboardingQuestionType enum | SingleChoice, MultiChoice, Boolean |
StepNo | int | Groups questions into wizard steps |
IsRequired | bool | Drives status.currentStep computation |
OptionsJson | string | JSON array of {value, labelAr, labelEn} for choice questions |
VisibleWhenJson | string | JSON condition — e.g. only show hasTables when activityType == "RestaurantCafe" |
7.3 Saas.OnboardingProfiles
The catalog of recommendation outcomes (e.g. RestaurantCafe, Services) a session can be matched to.
| Column | Type | Notes |
|---|---|---|
Id | Guid | PK |
Code | string | Matched against TenantOnboardingSessions.RecommendedProfileCode |
NameAr / NameEn, DescriptionAr / DescriptionEn | string | Display text |
7.4 Saas.OnboardingRules
Condition → settings-patch mapping the recommendation engine evaluates.
| Column | Type | Notes |
|---|---|---|
Id | Guid | PK |
ProfileCode | string? | null = a global/conditional rule evaluated for every session regardless of recommended profile; non-null = a base-profile rule, only evaluated when that profile was recommended |
ConditionJson | string | JSON condition evaluated against the session's answers |
SettingsPatchJson | string | The settings-group/property fragment this rule contributes if its condition matches |
Priority | int | Evaluation/merge order |
ProfileCodehere and the base-profileactivityTypeanswer values are the same value space later formalized as real, FK-able master data — seeSaas.BusinessActivitiesin the Tenant Starter Kit & Product Catalog guide, which every accounting/cost-center/product-catalog starter template is scoped by.
7.5 Saas.TenantOnboardingSessions
One row per tenant per survey — the actual state machine described in Chapter 5.
| Column | Type | Notes |
|---|---|---|
Id | Guid | PK — this is the sessionId returned by answers and required by apply |
TenantId | string | The tenant this session belongs to — always set from the authenticated user's JWT Tenant claim, never from client input |
UserId | Guid | The user who started the session |
SurveyDefinitionId, SurveyVersion | Guid, int | Which survey this session answers |
Status | OnboardingSessionStatus enum | NotStarted=1, InProgress=2, Recommended=3, Applied=4, Skipped=5 |
AnswersJson | string | Merged answers, keyed by question Key |
RecommendedProfileCode | string | Set by recommendation |
GeneratedSettingsPatchJson | string | The patch apply will send to the internal bridge |
GeneratedSummaryJson, GeneratedWarningsJson, GeneratedNextActionsJson | string | Human-readable recommendation output |
CompletedOn, AppliedOn, SkippedOn | DateTime? | Status-transition timestamps |
7.6 Saas.TenantOnboardingApplyLogs
Audit trail — one row per successful apply call.
| Column | Type | Notes |
|---|---|---|
Id | Guid | PK |
TenantId | string | |
SessionId | Guid | FK → TenantOnboardingSessions |
BeforeSettingsJson / AfterSettingsJson | string | Full snapshot of every touched settings group, before and after |
AppliedPatchJson | string | Only the properties that were actually changed |
AppliedBy | Guid | The authenticated user's NameIdentifier — never a system/service-account id (see Chapter 12 verification note) |
AppliedOn | DateTime | |
Notes | string? | Reserved, currently unused |
No apply log row is ever created for a failed apply call — a failure leaves the session at Recommended
with no side effects.
