From a72184f82c77b68070cd63afec215794a7b94fb9 Mon Sep 17 00:00:00 2001 From: brobert Date: Mon, 10 Nov 2025 13:58:33 +0100 Subject: [PATCH] fix: inyectar db en AllowedGroups y extraer mappers en src/tasks Co-authored-by: aider (openrouter/openai/gpt-5) --- src/tasks/complete-reaction.ts | 1 + src/tasks/mappers.ts | 67 ++++++++++++++++++++++++++++++++++ src/tasks/service.ts | 47 +++--------------------- 3 files changed, 74 insertions(+), 41 deletions(-) create mode 100644 src/tasks/mappers.ts diff --git a/src/tasks/complete-reaction.ts b/src/tasks/complete-reaction.ts index 73a7f8b..7d49bad 100644 --- a/src/tasks/complete-reaction.ts +++ b/src/tasks/complete-reaction.ts @@ -55,6 +55,7 @@ export function enqueueCompletionReactionIfEligible(db: Database, taskId: number const mode = String(process.env.GROUP_GATING_MODE || 'off').toLowerCase(); if (mode === 'enforce') { let allowed = true; + try { (AllowedGroups as any).dbInstance = db; } catch {} try { allowed = AllowedGroups.isAllowed(chatId); } catch { allowed = true; } if (!allowed) return; } diff --git a/src/tasks/mappers.ts b/src/tasks/mappers.ts new file mode 100644 index 0000000..16e4813 --- /dev/null +++ b/src/tasks/mappers.ts @@ -0,0 +1,67 @@ +/** + * Mapeadores puros para normalizar filas SQLite a DTOs usados por TaskService. + * Mantienen las mismas formas que consumen comandos, recordatorios y API web. + */ + +export function mapTaskListItem( + row: { id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null }, + assignees: string[] +): { + id: number; + description: string; + due_date: string | null; + group_id: string | null; + display_code: number | null; + assignees: string[]; +} { + return { + id: Number(row.id), + description: String(row.description || ''), + due_date: row.due_date ? String(row.due_date) : null, + group_id: row.group_id ? String(row.group_id) : null, + display_code: row.display_code != null ? Number(row.display_code) : null, + assignees: Array.isArray(assignees) ? assignees.map(a => String(a)) : [] + }; +} + +export function mapTaskWithGroupNameRow( + row: { id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null; group_name: string | null } +): { + id: number; + description: string; + due_date: string | null; + group_id: string | null; + group_name: string | null; + display_code: number | null; +} { + return { + id: Number(row.id), + description: String(row.description || ''), + due_date: row.due_date ? String(row.due_date) : null, + group_id: row.group_id ? String(row.group_id) : null, + group_name: row.group_name ? String(row.group_name) : null, + display_code: row.display_code != null ? Number(row.display_code) : null + }; +} + +export function mapTaskDetailsRow( + row: { id?: number; description?: string; due_date?: string | null; group_id?: string | null; display_code?: number | null; completed?: number; completed_at?: string | null } +): { + id: number; + description: string; + due_date: string | null; + group_id: string | null; + display_code: number | null; + completed: number; + completed_at: string | null; +} { + return { + id: Number(row.id), + description: String(row.description || ''), + due_date: row.due_date ? String(row.due_date) : null, + group_id: row.group_id ? String(row.group_id) : null, + display_code: row.display_code != null ? Number(row.display_code) : null, + completed: Number(row.completed || 0), + completed_at: row.completed_at ? String(row.completed_at) : null + }; +} diff --git a/src/tasks/service.ts b/src/tasks/service.ts index f5adfa1..593e8f3 100644 --- a/src/tasks/service.ts +++ b/src/tasks/service.ts @@ -4,6 +4,7 @@ import { AllowedGroups } from '../services/allowed-groups'; import { isGroupId } from '../utils/whatsapp'; import { pickNextDisplayCode } from './display-code'; import { enqueueCompletionReactionIfEligible } from './complete-reaction'; +import { mapTaskListItem, mapTaskWithGroupNameRow, mapTaskDetailsRow } from './mappers'; type CreateTaskInput = { description: string; @@ -125,14 +126,7 @@ export class TaskService { return rows.map((r) => { const assigneesRows = getAssignees.all(r.id) as Array<{ user_id: string }>; const assignees = assigneesRows.map((a) => String(a.user_id)); - return { - id: Number(r.id), - description: String(r.description || ''), - due_date: r.due_date ? String(r.due_date) : null, - group_id: r.group_id ? String(r.group_id) : null, - display_code: r.display_code != null ? Number(r.display_code) : null, - assignees, - }; + return mapTaskListItem(r, assignees); }); } @@ -169,14 +163,7 @@ export class TaskService { return rows.map((r) => { const assigneesRows = getAssignees.all(r.id) as Array<{ user_id: string }>; const assignees = assigneesRows.map((a) => String(a.user_id)); - return { - id: Number(r.id), - description: String(r.description || ''), - due_date: r.due_date ? String(r.due_date) : null, - group_id: r.group_id ? String(r.group_id) : null, - display_code: r.display_code != null ? Number(r.display_code) : null, - assignees, - }; + return mapTaskListItem(r, assignees); }); } @@ -290,14 +277,7 @@ export class TaskService { `) .all(groupId, limit) as Array<{ id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null }>; - return rows.map((r) => ({ - id: Number(r.id), - description: String(r.description || ''), - due_date: r.due_date ? String(r.due_date) : null, - group_id: r.group_id ? String(r.group_id) : null, - display_code: r.display_code != null ? Number(r.display_code) : null, - assignees: [], - })); + return rows.map((r) => mapTaskListItem(r, [])); } // Contar pendientes sin dueño del grupo (sin límite) @@ -507,15 +487,7 @@ export class TaskService { WHERE id = ? `).get(taskId) as { id?: number; description?: string; due_date?: string | null; group_id?: string | null; completed?: number; completed_at?: string | null; display_code?: number | null } | undefined; if (!row) return null; - return { - id: Number(row.id), - description: String(row.description || ''), - due_date: row.due_date ? String(row.due_date) : null, - group_id: row.group_id ? String(row.group_id) : null, - display_code: row.display_code != null ? Number(row.display_code) : null, - completed: Number(row.completed || 0), - completed_at: row.completed_at ? String(row.completed_at) : null, - }; + return mapTaskDetailsRow(row); } // Buscar tarea activa por display_code global @@ -591,14 +563,7 @@ export class TaskService { `) .all(limit) as Array<{ id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null; group_name: string | null }>; - return rows.map(r => ({ - id: Number(r.id), - description: String(r.description || ''), - due_date: r.due_date ? String(r.due_date) : null, - group_id: r.group_id ? String(r.group_id) : null, - group_name: r.group_name ? String(r.group_name) : null, - display_code: r.display_code != null ? Number(r.display_code) : null, - })); + return rows.map(r => mapTaskWithGroupNameRow(r)); } static countAllActive(): number {