feat: aplicar fallback getDb() en ResponseQueue y TaskService

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
main
brobert 1 month ago
parent 1300f60f58
commit 77ad9d76c5

@ -1,5 +1,6 @@
import type { Database } from 'bun:sqlite'; import type { Database } from 'bun:sqlite';
import { db } from '../db'; import { db } from '../db';
import { getDb } from '../db/locator';
import { IdentityService } from './identity'; import { IdentityService } from './identity';
import { normalizeWhatsAppId } from '../utils/whatsapp'; import { normalizeWhatsAppId } from '../utils/whatsapp';
import { Metrics } from './metrics'; import { Metrics } from './metrics';
@ -63,6 +64,15 @@ export const ResponseQueue = {
_cleanupRunning: false, _cleanupRunning: false,
_cleanupRunCount: 0, _cleanupRunCount: 0,
getDbInstance(): Database {
const anyThis = this as any;
try {
return (anyThis.dbInstance as Database) ?? getDb();
} catch {
return anyThis.dbInstance as Database;
}
},
nowIso(): string { nowIso(): string {
return toIsoSqlUTC(new Date()); return toIsoSqlUTC(new Date());
}, },
@ -89,12 +99,12 @@ export const ResponseQueue = {
return; return;
} }
const insert = this.dbInstance.prepare(` const insert = this.getDbInstance().prepare(`
INSERT INTO response_queue (recipient, message, metadata, next_attempt_at) INSERT INTO response_queue (recipient, message, metadata, next_attempt_at)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
`); `);
this.dbInstance.transaction((rows: QueuedResponse[]) => { this.getDbInstance().transaction((rows: QueuedResponse[]) => {
for (const r of rows) { for (const r of rows) {
const metadata = const metadata =
r.mentions && r.mentions.length > 0 r.mentions && r.mentions.length > 0
@ -141,7 +151,7 @@ export const ResponseQueue = {
display_code: metadata.display_code ?? null display_code: metadata.display_code ?? null
}; };
const nextAt = delayMs && delayMs > 0 ? this.futureIso(delayMs) : this.nowIso(); const nextAt = delayMs && delayMs > 0 ? this.futureIso(delayMs) : this.nowIso();
this.dbInstance.prepare(` this.getDbInstance().prepare(`
INSERT INTO response_queue (recipient, message, metadata, next_attempt_at) INSERT INTO response_queue (recipient, message, metadata, next_attempt_at)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
`).run(recipient, message, JSON.stringify(metaObj), nextAt); `).run(recipient, message, JSON.stringify(metaObj), nextAt);
@ -151,7 +161,7 @@ export const ResponseQueue = {
// Estadísticas de onboarding por destinatario (consulta simple sobre response_queue) // Estadísticas de onboarding por destinatario (consulta simple sobre response_queue)
getOnboardingStats(recipient: string): { total: number; lastSentAt: string | null; firstInitialAt?: string | null; lastVariant?: 'initial' | 'reminder' | null } { getOnboardingStats(recipient: string): { total: number; lastSentAt: string | null; firstInitialAt?: string | null; lastVariant?: 'initial' | 'reminder' | null } {
if (!recipient) return { total: 0, lastSentAt: null, lastVariant: null }; if (!recipient) return { total: 0, lastSentAt: null, lastVariant: null };
const rows = this.dbInstance.prepare(` const rows = this.getDbInstance().prepare(`
SELECT status, created_at, updated_at, metadata SELECT status, created_at, updated_at, metadata
FROM response_queue FROM response_queue
WHERE recipient = ? AND metadata IS NOT NULL WHERE recipient = ? AND metadata IS NOT NULL
@ -222,7 +232,7 @@ export const ResponseQueue = {
const cutoff = this.futureIso(-24 * 60 * 60 * 1000); const cutoff = this.futureIso(-24 * 60 * 60 * 1000);
// Idempotencia: existe job igual reciente en estados activos? // Idempotencia: existe job igual reciente en estados activos?
const exists = this.dbInstance.prepare(` const exists = this.getDbInstance().prepare(`
SELECT 1 SELECT 1
FROM response_queue FROM response_queue
WHERE metadata = ? WHERE metadata = ?
@ -235,7 +245,7 @@ export const ResponseQueue = {
return; return;
} }
this.dbInstance.prepare(` this.getDbInstance().prepare(`
INSERT INTO response_queue (recipient, message, metadata, next_attempt_at) INSERT INTO response_queue (recipient, message, metadata, next_attempt_at)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
`).run(chatId, '', metadata, this.nowIso()); `).run(chatId, '', metadata, this.nowIso());
@ -385,7 +395,7 @@ export const ResponseQueue = {
claimNextBatch(limit: number): ClaimedItem[] { claimNextBatch(limit: number): ClaimedItem[] {
// Selecciona y marca como 'processing' en una sola sentencia para evitar carreras // Selecciona y marca como 'processing' en una sola sentencia para evitar carreras
const rows = this.dbInstance.prepare(` const rows = this.getDbInstance().prepare(`
UPDATE response_queue UPDATE response_queue
SET status = 'processing', SET status = 'processing',
updated_at = strftime('%Y-%m-%d %H:%M:%f', 'now') updated_at = strftime('%Y-%m-%d %H:%M:%f', 'now')
@ -403,7 +413,7 @@ export const ResponseQueue = {
}, },
markSent(id: number, statusCode?: number) { markSent(id: number, statusCode?: number) {
this.dbInstance.prepare(` this.getDbInstance().prepare(`
UPDATE response_queue UPDATE response_queue
SET status = 'sent', SET status = 'sent',
last_status_code = ?, last_status_code = ?,
@ -412,7 +422,7 @@ export const ResponseQueue = {
`).run(statusCode ?? null, id); `).run(statusCode ?? null, id);
// Recalcular métricas agregadas de onboarding si aplica // Recalcular métricas agregadas de onboarding si aplica
try { try {
const row = this.dbInstance.prepare(`SELECT metadata FROM response_queue WHERE id = ?`).get(id) as { metadata?: string | null } | undefined; const row = this.getDbInstance().prepare(`SELECT metadata FROM response_queue WHERE id = ?`).get(id) as { metadata?: string | null } | undefined;
let meta: any = null; let meta: any = null;
try { meta = row?.metadata ? JSON.parse(String(row.metadata)) : null; } catch {} try { meta = row?.metadata ? JSON.parse(String(row.metadata)) : null; } catch {}
if (meta && meta.kind === 'onboarding') { if (meta && meta.kind === 'onboarding') {
@ -423,7 +433,7 @@ export const ResponseQueue = {
markFailed(id: number, errorMsg: string, statusCode?: number, attempts?: number) { markFailed(id: number, errorMsg: string, statusCode?: number, attempts?: number) {
const msg = (errorMsg || '').toString().slice(0, 500); const msg = (errorMsg || '').toString().slice(0, 500);
this.dbInstance.prepare(` this.getDbInstance().prepare(`
UPDATE response_queue UPDATE response_queue
SET status = 'failed', SET status = 'failed',
attempts = COALESCE(?, attempts), attempts = COALESCE(?, attempts),
@ -436,7 +446,7 @@ export const ResponseQueue = {
requeueWithBackoff(id: number, nextAttempts: number, nextAttemptAt: string, statusCode?: number | null, errorMsg?: string) { requeueWithBackoff(id: number, nextAttempts: number, nextAttemptAt: string, statusCode?: number | null, errorMsg?: string) {
const msg = (errorMsg || '').toString().slice(0, 500) || null; const msg = (errorMsg || '').toString().slice(0, 500) || null;
this.dbInstance.prepare(` this.getDbInstance().prepare(`
UPDATE response_queue UPDATE response_queue
SET status = 'queued', SET status = 'queued',
attempts = ?, attempts = ?,
@ -451,7 +461,7 @@ export const ResponseQueue = {
setOnboardingAggregatesMetrics(): void { setOnboardingAggregatesMetrics(): void {
try { try {
// Total de mensajes de onboarding enviados // Total de mensajes de onboarding enviados
const sentRow = this.dbInstance.prepare(` const sentRow = this.getDbInstance().prepare(`
SELECT COUNT(*) AS c SELECT COUNT(*) AS c
FROM response_queue FROM response_queue
WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%' WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%'
@ -459,7 +469,7 @@ export const ResponseQueue = {
const sentAbs = Number(sentRow?.c || 0); const sentAbs = Number(sentRow?.c || 0);
// Destinatarios únicos con al menos 1 onboarding enviado // Destinatarios únicos con al menos 1 onboarding enviado
const rcptRow = this.dbInstance.prepare(` const rcptRow = this.getDbInstance().prepare(`
SELECT COUNT(DISTINCT recipient) AS c SELECT COUNT(DISTINCT recipient) AS c
FROM response_queue FROM response_queue
WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%' WHERE status = 'sent' AND metadata LIKE '%"kind":"onboarding"%'
@ -467,7 +477,7 @@ export const ResponseQueue = {
const recipientsAbs = Number(rcptRow?.c || 0); const recipientsAbs = Number(rcptRow?.c || 0);
// Usuarios convertidos: last_command_at > primer onboarding enviado // Usuarios convertidos: last_command_at > primer onboarding enviado
const convRow = this.dbInstance.prepare(` const convRow = this.getDbInstance().prepare(`
SELECT COUNT(*) AS c SELECT COUNT(*) AS c
FROM users u FROM users u
JOIN ( JOIN (
@ -566,7 +576,7 @@ export const ResponseQueue = {
const startedAt = Date.now(); const startedAt = Date.now();
try { try {
const res = await cleanupRunOnce(this.dbInstance, { const res = await cleanupRunOnce(this.getDbInstance(), {
retentionDaysSent: this.RETENTION_DAYS_SENT, retentionDaysSent: this.RETENTION_DAYS_SENT,
retentionDaysFailed: this.RETENTION_DAYS_FAILED, retentionDaysFailed: this.RETENTION_DAYS_FAILED,
batchSize: this.CLEANUP_BATCH, batchSize: this.CLEANUP_BATCH,

@ -1,5 +1,6 @@
import type { Database } from 'bun:sqlite'; import type { Database } from 'bun:sqlite';
import { db, ensureUserExists } from '../db'; import { db, ensureUserExists } from '../db';
import { getDb as getGlobalDb } from '../db/locator';
import { AllowedGroups } from '../services/allowed-groups'; import { AllowedGroups } from '../services/allowed-groups';
import { isGroupId } from '../utils/whatsapp'; import { isGroupId } from '../utils/whatsapp';
import { pickNextDisplayCode } from './display-code'; import { pickNextDisplayCode } from './display-code';
@ -21,15 +22,19 @@ type CreateAssignmentInput = {
export class TaskService { export class TaskService {
static dbInstance: Database = db; static dbInstance: Database = db;
private static getDb(): Database {
return ((this as any).dbInstance as Database) ?? getGlobalDb();
}
static createTask(task: CreateTaskInput, assignments: CreateAssignmentInput[] = []): number { static createTask(task: CreateTaskInput, assignments: CreateAssignmentInput[] = []): number {
const runTx = this.dbInstance.transaction(() => { const runTx = this.getDb().transaction(() => {
const insertTask = this.dbInstance.prepare(` const insertTask = this.getDb().prepare(`
INSERT INTO tasks (description, due_date, group_id, created_by, display_code) INSERT INTO tasks (description, due_date, group_id, created_by, display_code)
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)
`); `);
const ensuredCreator = ensureUserExists(task.created_by, this.dbInstance); const ensuredCreator = ensureUserExists(task.created_by, this.getDb());
if (!ensuredCreator) { if (!ensuredCreator) {
throw new Error('No se pudo asegurar created_by'); throw new Error('No se pudo asegurar created_by');
} }
@ -49,14 +54,14 @@ export class TaskService {
} catch {} } catch {}
if (groupIdToInsert) { if (groupIdToInsert) {
const exists = this.dbInstance.prepare(`SELECT 1 FROM groups WHERE id = ? AND COALESCE(is_community,0) = 0`).get(groupIdToInsert); const exists = this.getDb().prepare(`SELECT 1 FROM groups WHERE id = ? AND COALESCE(is_community,0) = 0`).get(groupIdToInsert);
if (!exists) { if (!exists) {
groupIdToInsert = null; groupIdToInsert = null;
} }
} }
// Elegir display_code global reutilizable entre tareas activas // Elegir display_code global reutilizable entre tareas activas
const displayCode = pickNextDisplayCode(this.dbInstance); const displayCode = pickNextDisplayCode(this.getDb());
const runResult = insertTask.run( const runResult = insertTask.run(
task.description, task.description,
@ -68,7 +73,7 @@ export class TaskService {
const taskId = Number((runResult as { lastInsertRowid?: number | bigint }).lastInsertRowid); const taskId = Number((runResult as { lastInsertRowid?: number | bigint }).lastInsertRowid);
if (assignments.length > 0) { if (assignments.length > 0) {
const insertAssignment = this.dbInstance.prepare(` const insertAssignment = this.getDb().prepare(`
INSERT INTO task_assignments (task_id, user_id, assigned_by) INSERT INTO task_assignments (task_id, user_id, assigned_by)
VALUES (?, ?, ?) VALUES (?, ?, ?)
`); `);
@ -76,13 +81,13 @@ export class TaskService {
// Evitar duplicados por (task_id, user_id) tras asegurar usuarios // Evitar duplicados por (task_id, user_id) tras asegurar usuarios
const seen = new Set<string>(); const seen = new Set<string>();
for (const a of assignments) { for (const a of assignments) {
const ensuredUser = ensureUserExists(a.user_id, this.dbInstance); const ensuredUser = ensureUserExists(a.user_id, this.getDb());
if (!ensuredUser) continue; if (!ensuredUser) continue;
if (seen.has(ensuredUser)) continue; if (seen.has(ensuredUser)) continue;
seen.add(ensuredUser); seen.add(ensuredUser);
const ensuredAssigner = const ensuredAssigner =
ensureUserExists(a.assigned_by || ensuredCreator, this.dbInstance) || ensuredCreator; ensureUserExists(a.assigned_by || ensuredCreator, this.getDb()) || ensuredCreator;
insertAssignment.run(taskId, ensuredUser, ensuredAssigner); insertAssignment.run(taskId, ensuredUser, ensuredAssigner);
} }
@ -103,7 +108,7 @@ export class TaskService {
display_code: number | null; display_code: number | null;
assignees: string[]; assignees: string[];
}> { }> {
const rows = this.dbInstance const rows = this.getDb()
.prepare(` .prepare(`
SELECT id, description, due_date, group_id, display_code SELECT id, description, due_date, group_id, display_code
FROM tasks FROM tasks
@ -117,7 +122,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 }>; .all(groupId, limit) as Array<{ id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null }>;
const getAssignees = this.dbInstance.prepare(` const getAssignees = this.getDb().prepare(`
SELECT user_id FROM task_assignments SELECT user_id FROM task_assignments
WHERE task_id = ? WHERE task_id = ?
ORDER BY assigned_at ASC ORDER BY assigned_at ASC
@ -139,7 +144,7 @@ export class TaskService {
display_code: number | null; display_code: number | null;
assignees: string[]; assignees: string[];
}> { }> {
const rows = this.dbInstance const rows = this.getDb()
.prepare(` .prepare(`
SELECT t.id, t.description, t.due_date, t.group_id, t.display_code SELECT t.id, t.description, t.due_date, t.group_id, t.display_code
FROM tasks t FROM tasks t
@ -154,7 +159,7 @@ export class TaskService {
`) `)
.all(userId, limit) as Array<{ id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null }>; .all(userId, limit) as Array<{ id: number; description: string; due_date: string | null; group_id: string | null; display_code: number | null }>;
const getAssignees = this.dbInstance.prepare(` const getAssignees = this.getDb().prepare(`
SELECT user_id FROM task_assignments SELECT user_id FROM task_assignments
WHERE task_id = ? WHERE task_id = ?
ORDER BY assigned_at ASC ORDER BY assigned_at ASC
@ -169,7 +174,7 @@ export class TaskService {
// Contar pendientes del grupo (sin límite) // Contar pendientes del grupo (sin límite)
static countGroupPending(groupId: string): number { static countGroupPending(groupId: string): number {
const row = this.dbInstance const row = this.getDb()
.prepare(` .prepare(`
SELECT COUNT(*) as cnt SELECT COUNT(*) as cnt
FROM tasks FROM tasks
@ -182,7 +187,7 @@ export class TaskService {
// Contar pendientes asignadas al usuario (sin límite) // Contar pendientes asignadas al usuario (sin límite)
static countUserPending(userId: string): number { static countUserPending(userId: string): number {
const row = this.dbInstance const row = this.getDb()
.prepare(` .prepare(`
SELECT COUNT(*) as cnt SELECT COUNT(*) as cnt
FROM tasks t FROM tasks t
@ -199,9 +204,9 @@ export class TaskService {
status: 'updated' | 'already' | 'not_found'; status: 'updated' | 'already' | 'not_found';
task?: { id: number; description: string; due_date: string | null; display_code: number | null }; task?: { id: number; description: string; due_date: string | null; display_code: number | null };
} { } {
const ensured = ensureUserExists(completedBy, this.dbInstance); const ensured = ensureUserExists(completedBy, this.getDb());
const existing = this.dbInstance const existing = this.getDb()
.prepare(` .prepare(`
SELECT id, description, due_date, completed, completed_at, display_code, group_id SELECT id, description, due_date, completed, completed_at, display_code, group_id
FROM tasks FROM tasks
@ -225,7 +230,7 @@ export class TaskService {
}; };
} }
this.dbInstance this.getDb()
.prepare(` .prepare(`
UPDATE tasks UPDATE tasks
SET completed = 1, SET completed = 1,
@ -237,7 +242,7 @@ export class TaskService {
// Fase 2: reacción ✅ al completar dentro del TTL y con gating // Fase 2: reacción ✅ al completar dentro del TTL y con gating
try { try {
enqueueCompletionReactionIfEligible(this.dbInstance, taskId); enqueueCompletionReactionIfEligible(this.getDb(), taskId);
} catch {} } catch {}
return { return {
@ -260,7 +265,7 @@ export class TaskService {
display_code: number | null; display_code: number | null;
assignees: string[]; assignees: string[];
}> { }> {
const rows = this.dbInstance const rows = this.getDb()
.prepare(` .prepare(`
SELECT id, description, due_date, group_id, display_code SELECT id, description, due_date, group_id, display_code
FROM tasks FROM tasks
@ -282,7 +287,7 @@ export class TaskService {
// Contar pendientes sin dueño del grupo (sin límite) // Contar pendientes sin dueño del grupo (sin límite)
static countGroupUnassigned(groupId: string): number { static countGroupUnassigned(groupId: string): number {
const row = this.dbInstance const row = this.getDb()
.prepare(` .prepare(`
SELECT COUNT(*) as cnt SELECT COUNT(*) as cnt
FROM tasks t FROM tasks t
@ -301,12 +306,12 @@ export class TaskService {
status: 'claimed' | 'already' | 'not_found' | 'completed'; status: 'claimed' | 'already' | 'not_found' | 'completed';
task?: { id: number; description: string; due_date: string | null; display_code: number | null }; task?: { id: number; description: string; due_date: string | null; display_code: number | null };
} { } {
const ensuredUser = ensureUserExists(userId, this.dbInstance); const ensuredUser = ensureUserExists(userId, this.getDb());
if (!ensuredUser) { if (!ensuredUser) {
throw new Error('No se pudo asegurar el usuario'); throw new Error('No se pudo asegurar el usuario');
} }
const existing = this.dbInstance const existing = this.getDb()
.prepare(` .prepare(`
SELECT id, description, due_date, group_id, completed, completed_at, display_code SELECT id, description, due_date, group_id, completed, completed_at, display_code
FROM tasks FROM tasks
@ -330,7 +335,7 @@ export class TaskService {
}; };
} }
const already = this.dbInstance const already = this.getDb()
.prepare(`SELECT 1 FROM task_assignments WHERE task_id = ? AND user_id = ?`) .prepare(`SELECT 1 FROM task_assignments WHERE task_id = ? AND user_id = ?`)
.get(taskId, ensuredUser); .get(taskId, ensuredUser);
@ -346,12 +351,12 @@ export class TaskService {
}; };
} }
const insertAssignment = this.dbInstance.prepare(` const insertAssignment = this.getDb().prepare(`
INSERT OR IGNORE INTO task_assignments (task_id, user_id, assigned_by) INSERT OR IGNORE INTO task_assignments (task_id, user_id, assigned_by)
VALUES (?, ?, ?) VALUES (?, ?, ?)
`); `);
this.dbInstance.transaction(() => { this.getDb().transaction(() => {
insertAssignment.run(taskId, ensuredUser, ensuredUser); insertAssignment.run(taskId, ensuredUser, ensuredUser);
})(); })();
@ -372,12 +377,12 @@ export class TaskService {
task?: { id: number; description: string; due_date: string | null; display_code: number | null }; task?: { id: number; description: string; due_date: string | null; display_code: number | null };
now_unassigned?: boolean; // true si tras soltar no quedan asignados now_unassigned?: boolean; // true si tras soltar no quedan asignados
} { } {
const ensuredUser = ensureUserExists(userId, this.dbInstance); const ensuredUser = ensureUserExists(userId, this.getDb());
if (!ensuredUser) { if (!ensuredUser) {
throw new Error('No se pudo asegurar el usuario'); throw new Error('No se pudo asegurar el usuario');
} }
const existing = this.dbInstance const existing = this.getDb()
.prepare(` .prepare(`
SELECT id, description, due_date, group_id, completed, completed_at, display_code SELECT id, description, due_date, group_id, completed, completed_at, display_code
FROM tasks FROM tasks
@ -403,7 +408,7 @@ export class TaskService {
// Regla: no permitir soltar si es tarea personal y el usuario es el único asignatario // Regla: no permitir soltar si es tarea personal y el usuario es el único asignatario
try { try {
const stats = this.dbInstance.prepare(` const stats = this.getDb().prepare(`
SELECT COUNT(*) AS cnt, SELECT COUNT(*) AS cnt,
SUM(CASE WHEN user_id = ? THEN 1 ELSE 0 END) AS mine SUM(CASE WHEN user_id = ? THEN 1 ELSE 0 END) AS mine
FROM task_assignments FROM task_assignments
@ -425,14 +430,14 @@ export class TaskService {
} }
} catch {} } catch {}
const deleteStmt = this.dbInstance.prepare(` const deleteStmt = this.getDb().prepare(`
DELETE FROM task_assignments DELETE FROM task_assignments
WHERE task_id = ? AND user_id = ? WHERE task_id = ? AND user_id = ?
`); `);
const result = deleteStmt.run(taskId, ensuredUser) as { changes?: number }; const result = deleteStmt.run(taskId, ensuredUser) as { changes?: number };
const cntRow = this.dbInstance const cntRow = this.getDb()
.prepare(`SELECT COUNT(*) as cnt FROM task_assignments WHERE task_id = ?`) .prepare(`SELECT COUNT(*) as cnt FROM task_assignments WHERE task_id = ?`)
.get(taskId) as { cnt?: number } | undefined; .get(taskId) as { cnt?: number } | undefined;
const remaining = Number(cntRow?.cnt || 0); const remaining = Number(cntRow?.cnt || 0);
@ -474,7 +479,7 @@ export class TaskService {
completed: number; completed: number;
completed_at: string | null; completed_at: string | null;
} | null { } | null {
const row = this.dbInstance.prepare(` const row = this.getDb().prepare(`
SELECT SELECT
id, id,
description, description,
@ -492,7 +497,7 @@ export class TaskService {
// Buscar tarea activa por display_code global // Buscar tarea activa por display_code global
static getActiveTaskByDisplayCode(displayCode: number): { id: number; description: string; due_date: string | null; display_code: number | null } | null { static getActiveTaskByDisplayCode(displayCode: number): { id: number; description: string; due_date: string | null; display_code: number | null } | null {
const row = this.dbInstance.prepare(` const row = this.getDb().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 AND completed_at IS NULL WHERE display_code = ? AND COALESCE(completed, 0) = 0 AND completed_at IS NULL
@ -542,7 +547,7 @@ export class TaskService {
group_name: string | null; group_name: string | null;
display_code: number | null; display_code: number | null;
}> { }> {
const rows = this.dbInstance const rows = this.getDb()
.prepare(` .prepare(`
SELECT t.id, t.description, t.due_date, t.group_id, t.display_code, g.name AS group_name SELECT t.id, t.description, t.due_date, t.group_id, t.display_code, g.name AS group_name
FROM tasks t FROM tasks t
@ -567,7 +572,7 @@ export class TaskService {
} }
static countAllActive(): number { static countAllActive(): number {
const row = this.dbInstance const row = this.getDb()
.prepare(` .prepare(`
SELECT COUNT(*) AS cnt SELECT COUNT(*) AS cnt
FROM tasks t FROM tasks t

Loading…
Cancel
Save