fix(files): принадлежность файла задаче — дозаполнение task_id/field_id + MCP-проверка с сериализацией значений
Живой тест показал: 77 файлов отслеживаются, но get_task_file отвечал «не относится к задаче» — старые backfill-строки без task_id/field_id (ON CONFLICT DO NOTHING их не обновлял), а проверка по file-полям искала ключ только в строковых значениях (file-поля хранятся объектом/массивом). - MCP get_task_file: поиск ключа в JSON.stringify(value) для нестроковых значений; - trackFileOnDemand: у существующих строк без task_id дозаполняет taskId/fieldId; - startup-backfill: UPDATE task_id/field_id из task_field_values и task_messages для строк с task_id IS NULL.
This commit is contained in:
@@ -997,6 +997,52 @@ async function runStartupDataPatches() {
|
||||
ON CONFLICT (file_key) DO NOTHING
|
||||
`).catch(() => {});
|
||||
|
||||
// Дозаполнение task_id/field_id у старых строк, вставленных без привязки
|
||||
// (ранние версии трекинга). ON CONFLICT DO NOTHING их не обновляет.
|
||||
await db.execute(sql`
|
||||
UPDATE file_uploads fu
|
||||
SET task_id = src.task_id, field_id = src.field_id
|
||||
FROM (
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN elem->>'url' LIKE '%/api/files/%' THEN regexp_replace(elem->>'url', '^.*/api/files/', '')
|
||||
WHEN elem->>'url' LIKE '%/uploads/%' THEN regexp_replace(elem->>'url', '^.*/uploads/', '')
|
||||
END AS fkey,
|
||||
tfv.task_id,
|
||||
tfv.field_id
|
||||
FROM task_field_values tfv
|
||||
JOIN form_fields ff ON tfv.field_id = ff.id
|
||||
CROSS JOIN LATERAL jsonb_array_elements(
|
||||
CASE WHEN jsonb_typeof(tfv.value) = 'array' THEN tfv.value ELSE jsonb_build_array(tfv.value) END
|
||||
) elem
|
||||
WHERE ff.type = 'file'
|
||||
AND (elem->>'url' LIKE '%/api/files/%' OR elem->>'url' LIKE '%/uploads/%')
|
||||
) src
|
||||
WHERE fu.file_key = src.fkey
|
||||
AND src.fkey IS NOT NULL
|
||||
AND fu.task_id IS NULL
|
||||
`).catch(() => {});
|
||||
await db.execute(sql`
|
||||
UPDATE file_uploads fu
|
||||
SET task_id = src.task_id
|
||||
FROM (
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN att->>'url' LIKE '%/api/files/%' THEN regexp_replace(att->>'url', '^.*/api/files/', '')
|
||||
WHEN att->>'url' LIKE '%/uploads/%' THEN regexp_replace(att->>'url', '^.*/uploads/', '')
|
||||
END AS fkey,
|
||||
tm.task_id
|
||||
FROM task_messages tm
|
||||
CROSS JOIN LATERAL jsonb_array_elements(tm.attachments) att
|
||||
WHERE tm.attachments IS NOT NULL
|
||||
AND jsonb_typeof(tm.attachments) = 'array'
|
||||
AND (att->>'url' LIKE '%/api/files/%' OR att->>'url' LIKE '%/uploads/%')
|
||||
) src
|
||||
WHERE fu.file_key = src.fkey
|
||||
AND src.fkey IS NOT NULL
|
||||
AND fu.task_id IS NULL
|
||||
`).catch(() => {});
|
||||
|
||||
// RLS policies are created by migration 0011_rls_tasks_notnull.sql.
|
||||
// Startup only activates ENABLE + FORCE ROW LEVEL SECURITY when ENABLE_RLS=true,
|
||||
// then verifies all tables are correctly protected before allowing traffic.
|
||||
|
||||
Reference in New Issue
Block a user