Files
HOA_Financial_Platform/backend/src/modules/users/entities/user.entity.ts
olsch01 f1e66966f3 Phase 7: Add user onboarding tour and tenant setup wizard
Feature 1 - How-To Intro Tour (react-joyride):
- 8-step guided walkthrough highlighting Dashboard, Accounts, Assessments,
  Transactions, Budgets, Reports, and AI Investment Planning
- Runs automatically on first login, tracked via has_seen_intro flag on user
- Centralized step config in config/tourSteps.ts for easy text editing
- data-tour attributes on Sidebar nav items and Dashboard for targeting

Feature 2 - Tenant Onboarding Wizard:
- 3-step modal wizard: create operating account, assessment group + units,
  import budget CSV
- Runs after tour completes, tracked via onboardingComplete in org settings JSONB
- Reuses existing API endpoints (POST /accounts, /assessment-groups, /units,
  /budgets/:year/import)

Backend changes:
- Add has_seen_intro column to shared.users + migration
- Add PATCH /auth/intro-seen endpoint to mark tour complete
- Add PATCH /organizations/settings endpoint for org settings updates
- Include hasSeenIntro in login response, settings in switch-org response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:47:45 -05:00

67 lines
1.6 KiB
TypeScript

import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
} from 'typeorm';
import { UserOrganization } from '../../organizations/entities/user-organization.entity';
@Entity({ schema: 'shared', name: 'users' })
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
email: string;
@Column({ name: 'password_hash', nullable: true })
passwordHash: string;
@Column({ name: 'first_name', nullable: true })
firstName: string;
@Column({ name: 'last_name', nullable: true })
lastName: string;
@Column({ nullable: true })
phone: string;
@Column({ name: 'is_email_verified', default: false })
isEmailVerified: boolean;
@Column({ name: 'mfa_enabled', default: false })
mfaEnabled: boolean;
@Column({ name: 'mfa_secret', nullable: true })
mfaSecret: string;
@Column({ name: 'oauth_provider', nullable: true })
oauthProvider: string;
@Column({ name: 'oauth_provider_id', nullable: true })
oauthProviderId: string;
@Column({ name: 'is_superadmin', default: false })
isSuperadmin: boolean;
@Column({ name: 'is_platform_owner', default: false })
isPlatformOwner: boolean;
@Column({ name: 'has_seen_intro', default: false })
hasSeenIntro: boolean;
@Column({ name: 'last_login_at', type: 'timestamptz', nullable: true })
lastLoginAt: Date;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
updatedAt: Date;
@OneToMany(() => UserOrganization, (uo) => uo.user)
userOrganizations: UserOrganization[];
}