Files
iistwin/server/utils/pushTaskUpdated.ts
Ильяс Султанов 1f5ecb6da4 fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric,
  чтобы браузер не округлял значения через input type=number
- пробелы при вставке в number-поля удаляются
- бэкенд нормализует значения number-полей в строку перед сохранением
- добавлен хелпер normalizeFieldValueForStorage

Closes: искажение расчётного счёта и других длинных числовых полей
2026-07-07 21:03:40 +03:00

57 lines
1.8 KiB
TypeScript

import { storage } from '../storage';
import { eventBus } from '../routes/shared';
import { webPushService } from '../services/web-push.service';
/**
* Sends web-push notifications about a task update to all task participants
* who do NOT have an active SSE connection (i.e. are offline).
*
* Recipients = assignedTo + createdBy + all active taskUserAccess members,
* minus the actor who triggered the event.
*/
export async function pushTaskUpdated(opts: {
taskId: number;
organizationId: number;
formId: number;
taskTitle: string;
actorId: number;
}): Promise<void> {
const { taskId, organizationId, formId, taskTitle, actorId } = opts;
try {
const candidates = new Set<number>();
// Core fields: assignedTo / createdBy
const task = await storage.getTask(taskId, organizationId);
if (task) {
if (task.assignedTo) candidates.add(task.assignedTo);
if (task.createdBy) candidates.add(task.createdBy);
}
// All users who have interacted with the task (non-revoked access records)
const accessList = await storage.getTaskUserAccess(taskId, organizationId);
for (const entry of accessList) {
if (!entry.revokedAt) {
candidates.add(entry.userId);
}
}
// Exclude the actor who triggered the event — they see it instantly
candidates.delete(actorId);
for (const uid of candidates) {
if (!eventBus.isUserConnected(uid, organizationId)) {
await webPushService.sendToUser(uid, organizationId, {
title: 'Задача обновлена',
body: taskTitle,
icon: '/favicon.svg',
url: `/forms/${formId}/tasks/${taskId}`,
tag: `task-updated-${taskId}`,
});
}
}
} catch (err) {
console.error('[WebPush] pushTaskUpdated error:', err);
}
}