Notifications cronjob

This commit is contained in:
2026-02-01 22:29:48 -06:00
parent 48e0884bf7
commit 8ca10d0b35
5 changed files with 367 additions and 7 deletions

View File

@@ -0,0 +1,269 @@
import { Request, Response } from 'express';
import { triggerNegativeFlowDetection } from '../jobs/negativeFlowDetection';
import { AuthenticatedRequest } from '../middleware/auth.middleware';
import { query } from '../config/database';
/**
* POST /api/test/create-negative-flow-meter
* Create a test meter with negative flow for testing notifications
*/
export async function createTestMeterWithNegativeFlow(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
console.log('🧪 [Test] Creating test meter with negative flow...');
// Get first active concentrator
const concentratorResult = await query(`
SELECT id, project_id
FROM concentrators
WHERE status = 'ACTIVE'
LIMIT 1
`);
if (concentratorResult.rows.length === 0) {
res.status(400).json({
success: false,
error: 'No active concentrators found',
message: 'Please create a concentrator first before creating test meter',
});
return;
}
const concentrator = concentratorResult.rows[0];
// Check if test meter already exists
const existingMeterResult = await query(`
SELECT id FROM meters WHERE serial_number = 'TEST-NEGATIVE-001'
`);
let meterId: string;
let action: string;
if (existingMeterResult.rows.length > 0) {
// Update existing test meter
meterId = existingMeterResult.rows[0].id;
action = 'updated';
await query(`
UPDATE meters
SET
last_reading_value = -25.75,
last_reading_at = CURRENT_TIMESTAMP,
status = 'ACTIVE',
updated_at = CURRENT_TIMESTAMP
WHERE id = $1
`, [meterId]);
console.log(`✅ [Test] Test meter updated: ${meterId}`);
} else {
// Create new test meter
action = 'created';
const createResult = await query(`
INSERT INTO meters (
serial_number,
meter_id,
name,
concentrator_id,
location,
type,
status,
last_reading_value,
last_reading_at,
installation_date,
created_at,
updated_at
) VALUES (
'TEST-NEGATIVE-001',
'TEST-NEG-001',
'Test Meter - Negative Flow',
$1,
'Test Location - Building A',
'LORA',
'ACTIVE',
-25.75,
CURRENT_TIMESTAMP,
'2024-01-01',
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
) RETURNING id
`, [concentrator.id]);
meterId = createResult.rows[0].id;
console.log(`✅ [Test] Test meter created: ${meterId}`);
}
// Get the created/updated meter details
const meterDetails = await query(`
SELECT
m.id,
m.serial_number,
m.name,
m.last_reading_value,
m.status,
m.concentrator_id,
c.project_id
FROM meters m
JOIN concentrators c ON c.id = m.concentrator_id
WHERE m.id = $1
`, [meterId]);
res.status(200).json({
success: true,
message: `Test meter ${action} successfully`,
data: {
action,
meter: meterDetails.rows[0],
instructions: {
next_step: 'Trigger the notification job',
endpoint: 'POST /api/test/trigger-negative-flow',
},
},
});
} catch (error) {
console.error('❌ [Test] Error creating test meter:', error);
res.status(500).json({
success: false,
error: 'Failed to create test meter',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
}
/**
* POST /api/test/trigger-negative-flow
* Manually trigger the negative flow detection job for testing
* This endpoint simulates what the cron job does at 1:00 AM
*/
export async function triggerNegativeFlowJob(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
console.log('🧪 [Test] Manually triggering negative flow detection...');
await triggerNegativeFlowDetection();
res.status(200).json({
success: true,
message: 'Negative flow detection job triggered successfully',
timestamp: new Date().toISOString(),
});
} catch (error) {
console.error('❌ [Test] Error triggering negative flow detection:', error);
res.status(500).json({
success: false,
error: 'Failed to trigger negative flow detection',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
}
/**
* GET /api/test/negative-flow-meters
* Get list of meters with negative flow for testing
*/
export async function getNegativeFlowMeters(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
const { getMetersWithNegativeFlow } = await import('../services/notification.service');
const meters = await getMetersWithNegativeFlow();
res.status(200).json({
success: true,
data: {
count: meters.length,
meters: meters,
},
});
} catch (error) {
console.error('❌ [Test] Error fetching negative flow meters:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch negative flow meters',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
}
/**
* GET /api/test/notifications-info
* Get information about the notification system
*/
export async function getNotificationsInfo(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
// Count notifications by type
const typeCountResult = await query(`
SELECT notification_type, COUNT(*) as count
FROM notifications
GROUP BY notification_type
`);
// Count unread notifications
const unreadResult = await query(`
SELECT COUNT(*) as count
FROM notifications
WHERE is_read = false
`);
// Recent notifications
const recentResult = await query(`
SELECT *
FROM notifications
ORDER BY created_at DESC
LIMIT 10
`);
res.status(200).json({
success: true,
data: {
totalUnread: parseInt(unreadResult.rows[0].count, 10),
byType: typeCountResult.rows,
recentNotifications: recentResult.rows,
},
});
} catch (error) {
console.error('❌ [Test] Error fetching notifications info:', error);
res.status(500).json({
success: false,
error: 'Failed to fetch notifications info',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
}
/**
* DELETE /api/test/cleanup-test-data
* Clean up test meter and notifications
*/
export async function cleanupTestData(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
console.log('🧹 [Test] Cleaning up test data...');
// Delete notifications for test meter
const notificationsResult = await query(`
DELETE FROM notifications
WHERE meter_serial_number = 'TEST-NEGATIVE-001'
RETURNING id
`);
// Delete test meter
const meterResult = await query(`
DELETE FROM meters
WHERE serial_number = 'TEST-NEGATIVE-001'
RETURNING id
`);
res.status(200).json({
success: true,
message: 'Test data cleaned up successfully',
data: {
notifications_deleted: notificationsResult.rows.length,
meters_deleted: meterResult.rows.length,
},
});
} catch (error) {
console.error('❌ [Test] Error cleaning up test data:', error);
res.status(500).json({
success: false,
error: 'Failed to clean up test data',
message: error instanceof Error ? error.message : 'Unknown error',
});
}
}