refactor: Extract notification logic from todo.service.js

Create todo-notification.service.js with:
- notifyNewTodoAssignment(): push notification for new todo assignments
- notifyUpdatedTodoAssignment(): push notification for updated assignments

todo.service.js now delegates to the notification service instead of
containing inline push notification logic with error handling.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
richardtekula
2026-01-28 07:42:14 +01:00
parent 240dd5f4c8
commit 37dbf1b177
2 changed files with 50 additions and 39 deletions

View File

@@ -0,0 +1,46 @@
import { sendPushNotificationToUsers } from './push.service.js';
import { logger } from '../utils/logger.js';
export const notifyNewTodoAssignment = async (assignedUserIds, title, todoId, excludeUserId) => {
if (!assignedUserIds || !Array.isArray(assignedUserIds) || assignedUserIds.length === 0) {
return;
}
try {
await sendPushNotificationToUsers(
assignedUserIds,
{
title: 'Nová úloha',
body: `Bola vám priradená úloha: ${title}`,
icon: '/icon-192.png',
badge: '/badge-72.png',
data: { url: '/todos', todoId },
},
excludeUserId,
);
} catch (error) {
logger.error('Failed to send push notifications for new todo', error);
}
};
export const notifyUpdatedTodoAssignment = async (newlyAssignedUserIds, title, todoId, excludeUserId) => {
if (!newlyAssignedUserIds || newlyAssignedUserIds.length === 0) {
return;
}
try {
await sendPushNotificationToUsers(
newlyAssignedUserIds,
{
title: 'Priradená úloha',
body: `Bola vám priradená úloha: ${title}`,
icon: '/icon-192.png',
badge: '/badge-72.png',
data: { url: '/todos', todoId },
},
excludeUserId,
);
} catch (error) {
logger.error('Failed to send push notifications for updated todo', error);
}
};

View File

@@ -3,8 +3,7 @@ import { todos, todoUsers, notes, projects, companies, users } from '../db/schem
import { eq, desc, ilike, or, and, inArray, lt, ne, sql } from 'drizzle-orm'; import { eq, desc, ilike, or, and, inArray, lt, ne, sql } from 'drizzle-orm';
import { NotFoundError } from '../utils/errors.js'; import { NotFoundError } from '../utils/errors.js';
import { getAccessibleResourceIds } from '../middlewares/auth/resourceAccessMiddleware.js'; import { getAccessibleResourceIds } from '../middlewares/auth/resourceAccessMiddleware.js';
import { sendPushNotificationToUsers } from './push.service.js'; import { notifyNewTodoAssignment, notifyUpdatedTodoAssignment } from './todo-notification.service.js';
import { logger } from '../utils/logger.js';
import { import {
logTodoCreated, logTodoDeleted, logTodoCompleted, logTodoUpdated, logTodoUncompleted, logTodoCreated, logTodoDeleted, logTodoCompleted, logTodoUpdated, logTodoUncompleted,
} from './audit.service.js'; } from './audit.service.js';
@@ -213,23 +212,7 @@ export const createTodo = async (userId, data, auditContext = null) => {
} }
// Send push notifications to assigned users (excluding creator) // Send push notifications to assigned users (excluding creator)
if (assignedUserIds && Array.isArray(assignedUserIds) && assignedUserIds.length > 0) { await notifyNewTodoAssignment(assignedUserIds, title, newTodo.id, userId);
try {
await sendPushNotificationToUsers(
assignedUserIds,
{
title: 'Nová úloha',
body: `Bola vám priradená úloha: ${title}`,
icon: '/icon-192.png',
badge: '/badge-72.png',
data: { url: '/todos', todoId: newTodo.id },
},
userId // exclude creator
);
} catch (error) {
logger.error('Failed to send push notifications for new todo', error);
}
}
if (auditContext) { if (auditContext) {
await logTodoCreated(auditContext.userId, newTodo.id, newTodo.title, auditContext.ipAddress, auditContext.userAgent); await logTodoCreated(auditContext.userId, newTodo.id, newTodo.title, auditContext.ipAddress, auditContext.userAgent);
@@ -333,29 +316,11 @@ export const updateTodo = async (todoId, data, updatedByUserId = null, auditCont
await db.insert(todoUsers).values(todoUserInserts); await db.insert(todoUsers).values(todoUserInserts);
// Find newly assigned users (not in existing list) // Send push notifications to newly assigned users
const newlyAssignedUserIds = assignedUserIds.filter( const newlyAssignedUserIds = assignedUserIds.filter(
id => !existingUserIds.includes(id) id => !existingUserIds.includes(id)
); );
await notifyUpdatedTodoAssignment(newlyAssignedUserIds, updated.title, todoId, updatedByUserId);
// Send push notifications to newly assigned users
if (newlyAssignedUserIds.length > 0) {
try {
await sendPushNotificationToUsers(
newlyAssignedUserIds,
{
title: 'Priradená úloha',
body: `Bola vám priradená úloha: ${updated.title}`,
icon: '/icon-192.png',
badge: '/badge-72.png',
data: { url: '/todos', todoId: todoId },
},
updatedByUserId // exclude user making the change
);
} catch (error) {
logger.error('Failed to send push notifications for updated todo', error);
}
}
} }
} }