BEGIN; WITH active_todos AS ( SELECT t.id, t.user_id, t.product_id, t.title, t.description, t.created_at FROM todos t WHERE t.done = false AND t.archived = false AND NOT EXISTS ( SELECT 1 FROM ideas i WHERE i.user_id = t.user_id AND lower(trim(i.title)) = lower(trim(t.title)) ) ), user_base AS ( SELECT ut.user_id, u.idea_code_counter AS base_counter FROM (SELECT DISTINCT user_id FROM active_todos) ut JOIN users u ON u.id = ut.user_id ), ranked AS ( SELECT at.user_id, at.product_id, at.title, at.description, at.created_at, ub.base_counter, ROW_NUMBER() OVER (PARTITION BY at.user_id ORDER BY at.created_at, at.id) AS rn FROM active_todos at JOIN user_base ub ON ub.user_id = at.user_id ), inserted AS ( INSERT INTO ideas ( id, user_id, product_id, code, title, description, status, archived, created_at, updated_at ) SELECT gen_random_uuid()::text, user_id, product_id, 'IDEA-' || lpad((base_counter + rn)::text, 3, '0'), title, description, 'DRAFT', false, created_at, now() FROM ranked RETURNING user_id, (regexp_replace(code, '^IDEA-0*', ''))::int AS used_counter ) UPDATE users u SET idea_code_counter = sub.max_counter FROM ( SELECT user_id, MAX(used_counter) AS max_counter FROM inserted GROUP BY user_id ) sub WHERE u.id = sub.user_id AND sub.max_counter > u.idea_code_counter; DROP TABLE todos; COMMIT;