feat: Add user management APIs, status enum, enhanced notifications
- Add updateUser and resetUserPassword admin endpoints - Change company status from boolean to enum (registered, lead, customer, inactive) - Add 'important' event type to calendar validators and email templates - Add 1-hour-before event notifications cron job - Add 18:00 evening notifications for next-day events - Add contact description field support - Fix count() function usage in admin service - Add SQL migrations for schema changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
24
src/db/migrations/fix_status_type.sql
Normal file
24
src/db/migrations/fix_status_type.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
-- Fix: Convert status column from boolean to company_status enum
|
||||
-- The previous migration renamed is_active to status but kept the boolean type
|
||||
|
||||
-- Step 1: Add a temporary column with the correct enum type
|
||||
ALTER TABLE "companies" ADD COLUMN "status_new" company_status;
|
||||
|
||||
-- Step 2: Migrate data - convert boolean to enum
|
||||
-- true (active) -> 'registered', false (inactive) -> 'inactive'
|
||||
UPDATE "companies" SET "status_new" =
|
||||
CASE
|
||||
WHEN "status"::text = 'true' OR "status"::text = 't' THEN 'registered'::company_status
|
||||
WHEN "status"::text = 'false' OR "status"::text = 'f' THEN 'inactive'::company_status
|
||||
ELSE 'registered'::company_status
|
||||
END;
|
||||
|
||||
-- Step 3: Drop the old column
|
||||
ALTER TABLE "companies" DROP COLUMN "status";
|
||||
|
||||
-- Step 4: Rename the new column
|
||||
ALTER TABLE "companies" RENAME COLUMN "status_new" TO "status";
|
||||
|
||||
-- Step 5: Set the default and not null constraint
|
||||
ALTER TABLE "companies" ALTER COLUMN "status" SET DEFAULT 'registered';
|
||||
ALTER TABLE "companies" ALTER COLUMN "status" SET NOT NULL;
|
||||
38
src/db/migrations/hotfix_migration.sql
Normal file
38
src/db/migrations/hotfix_migration.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
-- Hotfix Migration Script
|
||||
-- Run this manually after accepting drizzle-kit push prompts
|
||||
|
||||
-- 1. Create the company_status enum type if it doesn't exist
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE company_status AS ENUM ('registered', 'lead', 'customer', 'inactive');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
-- 2. Add the status column to companies table if it doesn't exist
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE companies ADD COLUMN status company_status NOT NULL DEFAULT 'registered';
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN null;
|
||||
END $$;
|
||||
|
||||
-- 3. Migrate data from is_active to status (if is_active column exists)
|
||||
DO $$ BEGIN
|
||||
UPDATE companies SET status = CASE
|
||||
WHEN is_active = true THEN 'customer'::company_status
|
||||
ELSE 'inactive'::company_status
|
||||
END;
|
||||
EXCEPTION
|
||||
WHEN undefined_column THEN null;
|
||||
END $$;
|
||||
|
||||
-- 4. Drop the is_active column (optional - run after verifying migration)
|
||||
-- ALTER TABLE companies DROP COLUMN IF EXISTS is_active;
|
||||
|
||||
-- 5. Add description column to personal_contacts if it doesn't exist
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE personal_contacts ADD COLUMN description TEXT;
|
||||
EXCEPTION
|
||||
WHEN duplicate_column THEN null;
|
||||
END $$;
|
||||
|
||||
-- Note: Event type 'important' is stored as text, no schema change needed for events table
|
||||
@@ -5,6 +5,7 @@ export const roleEnum = pgEnum('role', ['admin', 'member']);
|
||||
export const projectStatusEnum = pgEnum('project_status', ['active', 'completed', 'on_hold', 'cancelled']);
|
||||
export const todoStatusEnum = pgEnum('todo_status', ['pending', 'in_progress', 'completed', 'cancelled']);
|
||||
export const todoPriorityEnum = pgEnum('todo_priority', ['low', 'medium', 'high', 'urgent']);
|
||||
export const companyStatusEnum = pgEnum('company_status', ['registered', 'lead', 'customer', 'inactive']);
|
||||
|
||||
// Users table - používatelia systému
|
||||
export const users = pgTable('users', {
|
||||
@@ -89,6 +90,7 @@ export const personalContacts = pgTable('personal_contacts', {
|
||||
phone: text('phone').notNull(),
|
||||
email: text('email').notNull(),
|
||||
secondaryEmail: text('secondary_email'),
|
||||
description: text('description'), // popis kontaktu
|
||||
createdAt: timestamp('created_at').defaultNow().notNull(),
|
||||
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
||||
}, (table) => ({
|
||||
@@ -128,7 +130,7 @@ export const companies = pgTable('companies', {
|
||||
phone: text('phone'),
|
||||
email: text('email'),
|
||||
website: text('website'),
|
||||
isActive: boolean('is_active').default(true).notNull(), // či je firma aktívna
|
||||
status: companyStatusEnum('status').default('registered').notNull(), // stav firmy
|
||||
createdBy: uuid('created_by').references(() => users.id, { onDelete: 'set null' }),
|
||||
createdAt: timestamp('created_at').defaultNow().notNull(),
|
||||
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
||||
|
||||
Reference in New Issue
Block a user