Files
GPI/src/server/services/notificationService.ts
2026-04-02 11:53:45 +00:00

64 lines
2.5 KiB
TypeScript

import { StockItem, Instrument, Notification, TechnicalDataSheet } from '../lib/compat.js';
import { addMonths, isBefore } from 'date-fns';
export const notificationService = {
async create(data: any & { organizationId: string }) {
return await Notification.create(data);
},
async getByOrganization(organizationId: string) {
return await Notification.find({ organizationId });
},
async checkLowStock(stockItemId: string) {
try {
const item = await StockItem.findById(stockItemId);
if (!item) return;
const ds = await TechnicalDataSheet.findById(item.dataSheetId);
const siblings = await StockItem.find({
organizationId: item.organizationId,
dataSheetId: item.dataSheetId,
color: item.color
});
const totalQuantity = siblings.reduce((sum: number, s: any) => sum + (Number(s.quantity) || 0), 0);
const minStock = item.minStock || 0;
if (totalQuantity <= minStock) {
await this.create({
organizationId: item.organizationId,
title: 'Estoque Baixo',
message: `O item ${ds?.name || item.rrNumber} está com estoque baixo (${totalQuantity} ${item.unit}). Mínimo: ${minStock}.`,
type: 'warning',
metadata: { stockItemId: item.id, triggerType: 'low_stock' }
});
}
} catch (error) {
console.error('Error checking low stock:', error);
}
},
async checkInstruments() {
try {
const instruments = await Instrument.find({});
const today = new Date();
const nextMonth = addMonths(today, 1);
for (const inst of instruments) {
if (inst.nextCalibration && isBefore(new Date(inst.nextCalibration), nextMonth)) {
await this.create({
organizationId: inst.organizationId,
title: 'Calibração Próxima',
message: `O instrumento ${inst.name} (${inst.tag}) requer calibração em ${new Date(inst.nextCalibration).toLocaleDateString()}.`,
type: 'warning',
metadata: { instrumentId: inst.id, triggerType: 'calibration_due' }
});
}
}
} catch (error) {
console.error('Error checking instruments:', error);
}
}
};