fix: usar display_code activo en comandos y DMs; eliminar fallback al PK

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
main
brobert 1 week ago
parent 26a19add33
commit fb7cc90b77

@ -156,11 +156,8 @@ export class CommandService {
} }
private static resolveTaskIdFromInput(n: number): number | null { private static resolveTaskIdFromInput(n: number): number | null {
// Resolver primero por display_code en tareas activas; si no, por PK
const byCode = TaskService.getActiveTaskByDisplayCode(n); const byCode = TaskService.getActiveTaskByDisplayCode(n);
if (byCode) return byCode.id; return byCode ? byCode.id : null;
const byId = TaskService.getTaskById(n);
return byId ? byId.id : null;
} }
private static async processTareaCommand( private static async processTareaCommand(
@ -903,7 +900,7 @@ export class CommandService {
if (res.now_unassigned) { if (res.now_unassigned) {
const lines = [ const lines = [
`${ICONS.unassigned} ${codeId(resolvedId, res.task?.display_code)} (${resolvedId})`, `${ICONS.unassigned} ${codeId(resolvedId, res.task?.display_code)}`,
`${res.task?.description || '(sin descripción)'}`, `${res.task?.description || '(sin descripción)'}`,
res.task?.due_date ? `${ICONS.date} ${formatDDMM(res.task?.due_date)}` : '', res.task?.due_date ? `${ICONS.date} ${formatDDMM(res.task?.due_date)}` : '',
italic('queda sin responsable.') italic('queda sin responsable.')
@ -1279,8 +1276,8 @@ export class CommandService {
`${description || '(sin descripción)'}`, `${description || '(sin descripción)'}`,
formatDDMM(dueDate) ? `${ICONS.date} ${formatDDMM(dueDate)}` : null, formatDDMM(dueDate) ? `${ICONS.date} ${formatDDMM(dueDate)}` : null,
groupName ? `Grupo: ${groupName}` : null, groupName ? `Grupo: ${groupName}` : null,
`- Completar: \`/t x ${taskId}\``, `- Completar: \`/t x ${createdTask?.display_code}\``,
`- Soltar: \`/t soltar ${taskId}\`` `- Soltar: \`/t soltar ${createdTask?.display_code}\``
].filter(Boolean).join('\n'), ].filter(Boolean).join('\n'),
mentions: [creatorJid] mentions: [creatorJid]
}); });

@ -607,7 +607,7 @@ export class TaskService {
const row = this.dbInstance.prepare(` const row = this.dbInstance.prepare(`
SELECT id, description, due_date, display_code SELECT id, description, due_date, display_code
FROM tasks FROM tasks
WHERE display_code = ? AND COALESCE(completed, 0) = 0 WHERE display_code = ? AND COALESCE(completed, 0) = 0 AND completed_at IS NULL
LIMIT 1 LIMIT 1
`).get(displayCode) as any; `).get(displayCode) as any;
if (!row) return null; if (!row) return null;

@ -36,6 +36,15 @@ describe('CommandService - /t tomar y /t soltar', () => {
return taskId; return taskId;
} }
function getDisplayCode(id: number): number {
const row = memdb.prepare('SELECT display_code FROM tasks WHERE id = ?').get(id) as any;
return Number(row?.display_code || 0);
}
function code4(n: number): string {
return '`' + String(n).padStart(4, '0') + '`';
}
const ctx = (sender: string, message: string) => ({ const ctx = (sender: string, message: string) => ({
sender, sender,
groupId: '', // DM o vacío; sin relevancia para tomar/soltar groupId: '', // DM o vacío; sin relevancia para tomar/soltar
@ -57,13 +66,14 @@ describe('CommandService - /t tomar y /t soltar', () => {
it('tomar: happy y luego already', async () => { it('tomar: happy y luego already', async () => {
const taskId = createTask('Desc tomar', '999', '2025-09-12'); const taskId = createTask('Desc tomar', '999', '2025-09-12');
const r1 = await CommandService.handle(ctx('111', `/t tomar ${taskId}`)); const dc = getDisplayCode(taskId);
const r1 = await CommandService.handle(ctx('111', `/t tomar ${dc}`));
expect(r1[0].message).toContain('Has tomado'); expect(r1[0].message).toContain('Has tomado');
expect(r1[0].message).toContain(String(taskId)); expect(r1[0].message).toContain(code4(dc));
expect(r1[0].message).toContain('Desc tomar'); expect(r1[0].message).toContain('Desc tomar');
expect(r1[0].message).toContain('📅'); // formato dd/MM expect(r1[0].message).toContain('📅'); // formato dd/MM
const r2 = await CommandService.handle(ctx('111', `/t tomar ${taskId}`)); const r2 = await CommandService.handle(ctx('111', `/t tomar ${dc}`));
expect(r2[0].message).toContain('ya la tenías'); expect(r2[0].message).toContain('ya la tenías');
}); });
@ -72,7 +82,8 @@ describe('CommandService - /t tomar y /t soltar', () => {
const comp = TaskService.completeTask(taskId, '111'); const comp = TaskService.completeTask(taskId, '111');
expect(comp.status).toBe('updated'); expect(comp.status).toBe('updated');
const res = await CommandService.handle(ctx('222', `/t tomar ${taskId}`)); const dc = getDisplayCode(taskId);
const res = await CommandService.handle(ctx('222', `/t tomar ${dc}`));
expect(res[0].message).toContain('ya estaba completada'); expect(res[0].message).toContain('ya estaba completada');
}); });
@ -88,13 +99,15 @@ describe('CommandService - /t tomar y /t soltar', () => {
it('soltar: personal única asignación → denegado', async () => { it('soltar: personal única asignación → denegado', async () => {
const taskId = createTask('Desc soltar', '999', '2025-09-12', ['111']); const taskId = createTask('Desc soltar', '999', '2025-09-12', ['111']);
const res = await CommandService.handle(ctx('111', `/t soltar ${taskId}`)); const dc = getDisplayCode(taskId);
const res = await CommandService.handle(ctx('111', `/t soltar ${dc}`));
expect(res[0].message).toContain('No puedes soltar una tarea personal. Márcala como completada para eliminarla'); expect(res[0].message).toContain('No puedes soltar una tarea personal. Márcala como completada para eliminarla');
}); });
it('soltar: not_assigned muestra mensaje informativo', async () => { it('soltar: not_assigned muestra mensaje informativo', async () => {
const taskId = createTask('Nunca asignada a 111', '999', null, ['222']); const taskId = createTask('Nunca asignada a 111', '999', null, ['222']);
const res = await CommandService.handle(ctx('111', `/t soltar ${taskId}`)); const dc = getDisplayCode(taskId);
const res = await CommandService.handle(ctx('111', `/t soltar ${dc}`));
expect(res[0].message).toContain('no la tenías asignada'); expect(res[0].message).toContain('no la tenías asignada');
}); });
@ -103,7 +116,8 @@ describe('CommandService - /t tomar y /t soltar', () => {
const comp = TaskService.completeTask(taskId, '111'); const comp = TaskService.completeTask(taskId, '111');
expect(comp.status).toBe('updated'); expect(comp.status).toBe('updated');
const res = await CommandService.handle(ctx('111', `/t soltar ${taskId}`)); const dc = getDisplayCode(taskId);
const res = await CommandService.handle(ctx('111', `/t soltar ${dc}`));
expect(res[0].message).toContain('ya estaba completada'); expect(res[0].message).toContain('ya estaba completada');
}); });
}); });

Loading…
Cancel
Save