Implement many-to-many TODO user assignments

- Create todo_users junction table for many-to-many relationship
- Add migration to create todo_users table and migrate existing data
- Update validators to accept assignedUserIds array instead of assignedTo
- Update todo service to handle multiple user assignments
- Fetch and return assigned users with each TODO

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
richardtekula
2025-11-24 11:17:28 +01:00
parent 7fd6b9e742
commit 8fd8f991e8
5 changed files with 248 additions and 48 deletions

View File

@@ -0,0 +1,29 @@
-- Migration: Add todo_users junction table and migrate from assignedTo
-- Created: 2025-11-24
-- Description: Allows many-to-many relationship between todos and users
-- Create todo_users junction table
CREATE TABLE IF NOT EXISTS todo_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
todo_id UUID NOT NULL REFERENCES todos(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
assigned_by UUID REFERENCES users(id) ON DELETE SET NULL,
assigned_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT todo_user_unique UNIQUE(todo_id, user_id)
);
-- Create indexes for better query performance
CREATE INDEX IF NOT EXISTS idx_todo_users_todo_id ON todo_users(todo_id);
CREATE INDEX IF NOT EXISTS idx_todo_users_user_id ON todo_users(user_id);
-- Migrate existing assignedTo data to todo_users table
INSERT INTO todo_users (todo_id, user_id, assigned_by, assigned_at)
SELECT id, assigned_to, created_by, created_at
FROM todos
WHERE assigned_to IS NOT NULL;
-- Drop the old assigned_to column
ALTER TABLE todos DROP COLUMN IF EXISTS assigned_to;
-- Add comment
COMMENT ON TABLE todo_users IS 'Junction table for many-to-many relationship between todos and users (assigned users)';

View File

@@ -149,7 +149,6 @@ export const todos = pgTable('todos', {
description: text('description'),
projectId: uuid('project_id').references(() => projects.id, { onDelete: 'cascade' }), // todo môže patriť projektu
companyId: uuid('company_id').references(() => companies.id, { onDelete: 'cascade' }), // alebo firme
assignedTo: uuid('assigned_to').references(() => users.id, { onDelete: 'set null' }), // komu je priradené
status: todoStatusEnum('status').default('pending').notNull(),
priority: todoPriorityEnum('priority').default('medium').notNull(),
dueDate: timestamp('due_date'),
@@ -159,6 +158,17 @@ export const todos = pgTable('todos', {
updatedAt: timestamp('updated_at').defaultNow().notNull(),
});
// Todo Users - many-to-many medzi todos a users (priradení používatelia)
export const todoUsers = pgTable('todo_users', {
id: uuid('id').primaryKey().defaultRandom(),
todoId: uuid('todo_id').references(() => todos.id, { onDelete: 'cascade' }).notNull(),
userId: uuid('user_id').references(() => users.id, { onDelete: 'cascade' }).notNull(),
assignedBy: uuid('assigned_by').references(() => users.id, { onDelete: 'set null' }), // kto pridal používateľa k todo
assignedAt: timestamp('assigned_at').defaultNow().notNull(),
}, (table) => ({
todoUserUnique: unique('todo_user_unique').on(table.todoId, table.userId),
}));
// Notes table - poznámky
export const notes = pgTable('notes', {
id: uuid('id').primaryKey().defaultRandom(),