Files
picpeak/backend/src/services/expirationChecker.js
T
paul 9932621e14 fix: comprehensive boolean compatibility for PostgreSQL and SQLite
- Add formatBoolean() usage to all boolean database queries
- Fix 36 boolean comparisons across 18 backend files
- Ensure compatibility between SQLite (0/1) and PostgreSQL (true/false)
- Update all WHERE clauses and UPDATE operations with boolean values

This completes the database compatibility fixes for production deployment.
All boolean operations now work correctly with both database systems.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-14 21:05:18 +02:00

102 lines
3.2 KiB
JavaScript

const cron = require('node-cron');
const { db } = require('../database/db');
const { archiveEvent } = require('./archiveService');
const { queueEmail } = require('./emailProcessor');
const logger = require('../utils/logger');
const { formatDate } = require('../utils/dateFormatter');
const { formatBoolean } = require('../utils/dbCompat');
function startExpirationChecker() {
// Check every hour for expired events and warnings
cron.schedule('0 * * * *', async () => {
await checkExpirations();
});
logger.info('Expiration checker started');
}
async function checkExpirations() {
try {
const now = new Date();
const warningDate = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 7 days from now
// Check for events needing warning emails
const eventsNeedingWarning = await db('events')
.where('is_active', formatBoolean(true))
.where('is_archived', formatBoolean(false))
.where('expires_at', '<=', warningDate)
.where('expires_at', '>', now);
for (const event of eventsNeedingWarning) {
// Check if warning email already sent
const existingWarning = await db('email_queue')
.where('event_id', event.id)
.where('email_type', 'expiration_warning')
.first();
if (!existingWarning) {
await queueExpirationWarning(event);
}
}
// Check for expired events
const expiredEvents = await db('events')
.where('is_active', formatBoolean(true))
.where('is_archived', formatBoolean(false))
.where('expires_at', '<=', now);
for (const event of expiredEvents) {
await handleExpiredEvent(event);
}
} catch (error) {
logger.error('Error checking expirations:', error);
}
}
async function queueExpirationWarning(event) {
const daysRemaining = Math.ceil((new Date(event.expires_at) - new Date()) / (1000 * 60 * 60 * 24));
// Determine language based on email domain
const emailLang = event.host_email.endsWith('.de') ? 'de' : 'en';
// Queue email to host
await queueEmail(event.id, event.host_email, 'expiration_warning', {
host_name: event.host_name || event.host_email.split('@')[0],
event_name: event.event_name,
days_remaining: daysRemaining.toString(),
expiration_date: await formatDate(event.expires_at, emailLang),
gallery_link: event.share_link
});
logger.info(`Queued expiration warning for event ${event.slug}`);
}
async function handleExpiredEvent(event) {
try {
// Mark as inactive
await db('events').where('id', event.id).update({ is_active: formatBoolean(false) });
// Queue expiration emails
await queueEmail(event.id, event.host_email, 'gallery_expired', {
event_name: event.event_name,
admin_email: event.admin_email
});
// Also notify admin
await queueEmail(event.id, event.admin_email, 'gallery_expired', {
event_name: event.event_name,
admin_email: event.admin_email
});
// Start archiving process
await archiveEvent(event);
logger.info(`Handled expiration for event ${event.slug}`);
} catch (error) {
logger.error(`Error handling expired event ${event.slug}:`, error);
}
}
module.exports = { startExpirationChecker };