diff --git a/src/modules/auth/entities/user.entity.ts b/src/modules/auth/entities/user.entity.ts index 51806a1..0223aad 100644 --- a/src/modules/auth/entities/user.entity.ts +++ b/src/modules/auth/entities/user.entity.ts @@ -34,10 +34,10 @@ export class User { @Column({ type: 'varchar', length: 200, nullable: true }) display_name: string | null; - @Column({ type: 'varchar', length: 255, nullable: true }) + @Column({ type: 'varchar', length: 500, nullable: true }) avatar_url: string | null; - @Column({ type: 'varchar', length: 20, nullable: true }) + @Column({ type: 'varchar', length: 50, nullable: true }) phone: string | null; @Column({ type: 'boolean', default: false }) @@ -45,9 +45,9 @@ export class User { @Column({ type: 'enum', - enum: ['active', 'inactive', 'suspended', 'pending_verification'], + enum: ['pending', 'active', 'inactive', 'suspended', 'pending_verification', 'deleted'], enumName: 'users.user_status', - default: 'pending_verification', + default: 'pending', }) status: string; @@ -102,6 +102,15 @@ export class User { @UpdateDateColumn({ type: 'timestamp with time zone' }) updated_at: Date; + @Column({ type: 'uuid', nullable: true }) + created_by: string | null; + + @Column({ type: 'uuid', nullable: true }) + updated_by: string | null; + + @Column({ type: 'timestamp with time zone', nullable: true }) + deleted_at: Date | null; + // Computed property get fullName(): string { return [this.first_name, this.last_name].filter(Boolean).join(' '); diff --git a/src/modules/rbac/__tests__/rbac.service.spec.ts b/src/modules/rbac/__tests__/rbac.service.spec.ts index 279c4c8..b3803c2 100644 --- a/src/modules/rbac/__tests__/rbac.service.spec.ts +++ b/src/modules/rbac/__tests__/rbac.service.spec.ts @@ -21,12 +21,17 @@ describe('RbacService', () => { tenant_id: 'tenant-123', name: 'Admin', code: 'admin', + slug: 'admin', description: 'Administrator role', + permissions: ['users:read', 'users:write'], + parent_role_id: null, + level: 0, is_system: false, is_active: true, metadata: null, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), + created_by: null, }; const mockSystemRole: Role = { diff --git a/src/modules/rbac/entities/role.entity.ts b/src/modules/rbac/entities/role.entity.ts index d123f20..efe7dd5 100644 --- a/src/modules/rbac/entities/role.entity.ts +++ b/src/modules/rbac/entities/role.entity.ts @@ -19,14 +19,14 @@ export class Role { @Index() tenant_id: string; - @Column({ type: 'varchar', length: 50 }) + @Column({ type: 'varchar', length: 100 }) name: string; @Column({ type: 'varchar', length: 50 }) @Index() code: string; - @Column({ type: 'varchar', length: 50, nullable: true }) + @Column({ type: 'varchar', length: 100, nullable: true }) @Index() slug: string | null; @@ -57,6 +57,9 @@ export class Role { @UpdateDateColumn({ type: 'timestamp with time zone' }) updated_at: Date; + @Column({ type: 'uuid', nullable: true }) + created_by: string | null; + // Relations will be handled via service queries for now // to avoid complex eager loading issues } diff --git a/src/modules/superadmin/__tests__/superadmin.controller.spec.ts b/src/modules/superadmin/__tests__/superadmin.controller.spec.ts index 21d1891..951f283 100644 --- a/src/modules/superadmin/__tests__/superadmin.controller.spec.ts +++ b/src/modules/superadmin/__tests__/superadmin.controller.spec.ts @@ -37,11 +37,18 @@ describe('SuperadminController', () => { logo_url: 'https://example.com/logo.png', plan_id: mockPlanId, status: 'active' as const, + subscription_status: 'active', + stripe_customer_id: 'cus_123', + stripe_subscription_id: 'sub_123', settings: {}, metadata: {}, trial_ends_at: null, + subscription_ends_at: null, created_at: new Date('2024-01-01'), updated_at: new Date('2024-01-01'), + created_by: null, + updated_by: null, + deleted_at: null, userCount: 5, subscription: null, }; @@ -305,11 +312,18 @@ describe('SuperadminController', () => { logo_url: null, plan_id: null, status: 'pending' as const, + subscription_status: null, + stripe_customer_id: null, + stripe_subscription_id: null, settings: null, metadata: null, trial_ends_at: null, + subscription_ends_at: null, created_at: new Date('2024-01-01'), updated_at: new Date('2024-01-01'), + created_by: null, + updated_by: null, + deleted_at: null, }; superadminService.createTenant.mockResolvedValue(createdTenant); @@ -335,11 +349,18 @@ describe('SuperadminController', () => { logo_url: createDto.logo_url ?? null, plan_id: createDto.plan_id ?? null, status: 'active' as const, + subscription_status: null, + stripe_customer_id: null, + stripe_subscription_id: null, settings: null, metadata: null, trial_ends_at: null, + subscription_ends_at: null, created_at: new Date('2024-01-01'), updated_at: new Date('2024-01-01'), + created_by: null, + updated_by: null, + deleted_at: null, }; superadminService.createTenant.mockResolvedValue(createdTenant); diff --git a/src/modules/superadmin/__tests__/superadmin.service.spec.ts b/src/modules/superadmin/__tests__/superadmin.service.spec.ts index 4bef02b..92660b0 100644 --- a/src/modules/superadmin/__tests__/superadmin.service.spec.ts +++ b/src/modules/superadmin/__tests__/superadmin.service.spec.ts @@ -25,11 +25,18 @@ describe('SuperadminService', () => { logo_url: 'https://example.com/logo.png', status: 'active', plan_id: 'plan-123', + subscription_status: 'active', + stripe_customer_id: 'cus_123', + stripe_subscription_id: 'sub_123', trial_ends_at: new Date('2026-02-01'), + subscription_ends_at: null, settings: { theme: 'dark' }, metadata: {}, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), + created_by: null, + updated_by: null, + deleted_at: null, }; const mockUser: Partial = { diff --git a/src/modules/tenants/__tests__/tenants.controller.spec.ts b/src/modules/tenants/__tests__/tenants.controller.spec.ts index 6153a2a..c8e9d2e 100644 --- a/src/modules/tenants/__tests__/tenants.controller.spec.ts +++ b/src/modules/tenants/__tests__/tenants.controller.spec.ts @@ -30,11 +30,18 @@ describe('TenantsController', () => { logo_url: 'https://example.com/logo.png', status: 'active', plan_id: 'plan-123', + subscription_status: 'active', + stripe_customer_id: 'cus_123', + stripe_subscription_id: 'sub_123', trial_ends_at: new Date('2026-02-01'), + subscription_ends_at: null, settings: { theme: 'dark', timezone: 'America/Mexico_City' }, metadata: {}, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), + created_by: null, + updated_by: null, + deleted_at: null, }; const mockPendingTenant: Tenant = { diff --git a/src/modules/tenants/__tests__/tenants.service.spec.ts b/src/modules/tenants/__tests__/tenants.service.spec.ts index a950cc0..afb3761 100644 --- a/src/modules/tenants/__tests__/tenants.service.spec.ts +++ b/src/modules/tenants/__tests__/tenants.service.spec.ts @@ -18,11 +18,18 @@ describe('TenantsService', () => { logo_url: 'https://example.com/logo.png', status: 'active', plan_id: 'plan-123', + subscription_status: 'active', + stripe_customer_id: 'cus_123', + stripe_subscription_id: 'sub_123', trial_ends_at: new Date('2026-02-01'), + subscription_ends_at: null, settings: { theme: 'dark' }, metadata: { industry: 'tech' }, created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-01'), + created_by: null, + updated_by: null, + deleted_at: null, }; beforeEach(async () => { diff --git a/src/modules/tenants/entities/tenant.entity.ts b/src/modules/tenants/entities/tenant.entity.ts index 847fd07..1202056 100644 --- a/src/modules/tenants/entities/tenant.entity.ts +++ b/src/modules/tenants/entities/tenant.entity.ts @@ -22,7 +22,7 @@ export class Tenant { @Column({ type: 'varchar', length: 255, nullable: true }) domain: string | null; - @Column({ type: 'varchar', length: 255, nullable: true }) + @Column({ type: 'varchar', length: 500, nullable: true }) logo_url: string | null; @Column({ @@ -68,6 +68,12 @@ export class Tenant { @UpdateDateColumn({ type: 'timestamp with time zone' }) updated_at: Date; + @Column({ type: 'uuid', nullable: true }) + created_by: string | null; + + @Column({ type: 'uuid', nullable: true }) + updated_by: string | null; + @Column({ type: 'timestamp with time zone', nullable: true }) deleted_at: Date | null; } diff --git a/src/modules/users/__tests__/users.service.spec.ts b/src/modules/users/__tests__/users.service.spec.ts index e894908..013bec0 100644 --- a/src/modules/users/__tests__/users.service.spec.ts +++ b/src/modules/users/__tests__/users.service.spec.ts @@ -16,20 +16,31 @@ describe('UsersService', () => { password_hash: 'hashed_password', first_name: 'John', last_name: 'Doe', + display_name: 'John Doe', avatar_url: 'https://example.com/avatar.png', phone: '+1234567890', + phone_verified: false, status: 'active', + is_owner: false, email_verified: true, email_verified_at: new Date('2026-01-01'), mfa_enabled: false, mfa_secret: null, mfa_backup_codes: null, mfa_enabled_at: null, + password_changed_at: null, + failed_login_attempts: 0, + locked_until: null, last_login_at: new Date('2026-01-07'), last_login_ip: '192.168.1.1', metadata: { preferences: { theme: 'dark' } }, + preferences: { language: 'en' }, + last_activity_at: new Date('2026-01-07'), created_at: new Date('2026-01-01'), updated_at: new Date('2026-01-07'), + created_by: null, + updated_by: null, + deleted_at: null, get fullName() { return [this.first_name, this.last_name].filter(Boolean).join(' '); },