Agenda refactor
This commit is contained in:
parent
fe6655f913
commit
946a110054
@ -418,11 +418,14 @@ export async function syncInfomaniakCalendar(
|
||||
});
|
||||
|
||||
// Create a map of existing events by externalEventId (UID) for fast lookup
|
||||
// Use type assertion to handle case where Prisma client doesn't recognize externalEventId yet
|
||||
type EventType = typeof existingEvents[number];
|
||||
const existingEventsByExternalId = new Map<string, EventType>();
|
||||
for (const event of existingEvents) {
|
||||
if (event.externalEventId) {
|
||||
existingEventsByExternalId.set(event.externalEventId, event);
|
||||
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
||||
const externalId = (event as any).externalEventId;
|
||||
if (externalId) {
|
||||
existingEventsByExternalId.set(externalId, event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,7 +444,9 @@ export async function syncInfomaniakCalendar(
|
||||
if (!existingEvent) {
|
||||
existingEvent = existingEvents.find(
|
||||
(e: EventType) => {
|
||||
if (!e.externalEventId && // Only match events that don't have externalEventId yet
|
||||
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
||||
const hasExternalId = !!(e as any).externalEventId;
|
||||
if (!hasExternalId && // Only match events that don't have externalEventId yet
|
||||
e.title === caldavEvent.summary) {
|
||||
const timeDiff = Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime());
|
||||
return timeDiff < 60000; // Within 1 minute
|
||||
@ -478,10 +483,18 @@ export async function syncInfomaniakCalendar(
|
||||
});
|
||||
updated++;
|
||||
} catch (updateError: any) {
|
||||
// If externalEventId field doesn't exist, retry without it
|
||||
if (updateError?.message?.includes('externalEventId') || updateError?.code === 'P2009') {
|
||||
logger.warn('externalEventId field not available, updating without it', {
|
||||
// If externalEventId field doesn't exist in Prisma client (even though it exists in DB),
|
||||
// retry without it. This can happen if Prisma client wasn't regenerated after migration.
|
||||
const errorMessage = updateError?.message || '';
|
||||
const errorCode = updateError?.code || '';
|
||||
|
||||
if (errorMessage.includes('externalEventId') ||
|
||||
errorMessage.includes('Unknown argument') ||
|
||||
errorCode === 'P2009' ||
|
||||
errorCode === 'P1012') {
|
||||
logger.warn('externalEventId field not recognized by Prisma client, updating without it', {
|
||||
eventId: existingEvent.id,
|
||||
error: errorMessage.substring(0, 200),
|
||||
});
|
||||
const { externalEventId, ...dataWithoutExternalId } = baseEventData;
|
||||
await prisma.event.update({
|
||||
@ -505,9 +518,18 @@ export async function syncInfomaniakCalendar(
|
||||
});
|
||||
created++;
|
||||
} catch (createError: any) {
|
||||
// If externalEventId field doesn't exist, retry without it
|
||||
if (createError?.message?.includes('externalEventId') || createError?.code === 'P2009') {
|
||||
logger.warn('externalEventId field not available, creating without it');
|
||||
// If externalEventId field doesn't exist in Prisma client (even though it exists in DB),
|
||||
// retry without it. This can happen if Prisma client wasn't regenerated after migration.
|
||||
const errorMessage = createError?.message || '';
|
||||
const errorCode = createError?.code || '';
|
||||
|
||||
if (errorMessage.includes('externalEventId') ||
|
||||
errorMessage.includes('Unknown argument') ||
|
||||
errorCode === 'P2009' ||
|
||||
errorCode === 'P1012') {
|
||||
logger.warn('externalEventId field not recognized by Prisma client, creating without it', {
|
||||
error: errorMessage.substring(0, 200),
|
||||
});
|
||||
const { externalEventId, ...dataWithoutExternalId } = baseEventData;
|
||||
await prisma.event.create({
|
||||
data: {
|
||||
|
||||
@ -440,10 +440,13 @@ export async function syncMicrosoftCalendar(
|
||||
});
|
||||
|
||||
// Create a map of existing events by externalEventId (Microsoft ID) for fast lookup
|
||||
// Use type assertion to handle case where Prisma client doesn't recognize externalEventId yet
|
||||
const existingEventsByExternalId = new Map<string, typeof existingEvents[0]>();
|
||||
for (const event of existingEvents) {
|
||||
if (event.externalEventId) {
|
||||
existingEventsByExternalId.set(event.externalEventId, event);
|
||||
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
||||
const externalId = (event as any).externalEventId;
|
||||
if (externalId) {
|
||||
existingEventsByExternalId.set(externalId, event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,7 +480,9 @@ export async function syncMicrosoftCalendar(
|
||||
// Priority 2: Fallback to checking description for [MS_ID:xxx] (backward compatibility)
|
||||
if (!existingEvent && microsoftId) {
|
||||
existingEvent = existingEvents.find((e) => {
|
||||
if (!e.externalEventId && e.description && e.description.includes(`[MS_ID:${microsoftId}]`)) {
|
||||
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
||||
const hasExternalId = !!(e as any).externalEventId;
|
||||
if (!hasExternalId && e.description && e.description.includes(`[MS_ID:${microsoftId}]`)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -487,10 +492,16 @@ export async function syncMicrosoftCalendar(
|
||||
// Priority 3: Fallback to title + date matching for events without externalEventId
|
||||
if (!existingEvent) {
|
||||
existingEvent = existingEvents.find(
|
||||
(e) =>
|
||||
!e.externalEventId && // Only match events that don't have externalEventId yet
|
||||
e.title === caldavEvent.summary &&
|
||||
Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime()) < 60000 // Within 1 minute
|
||||
(e) => {
|
||||
// Access externalEventId safely (may not be in Prisma type if client not regenerated)
|
||||
const hasExternalId = !!(e as any).externalEventId;
|
||||
if (!hasExternalId && // Only match events that don't have externalEventId yet
|
||||
e.title === caldavEvent.summary) {
|
||||
const timeDiff = Math.abs(new Date(e.start).getTime() - caldavEvent.start.getTime());
|
||||
return timeDiff < 60000; // Within 1 minute
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -529,10 +540,18 @@ export async function syncMicrosoftCalendar(
|
||||
microsoftId,
|
||||
});
|
||||
} catch (updateError: any) {
|
||||
// If externalEventId field doesn't exist, retry without it
|
||||
if (updateError?.message?.includes('externalEventId') || updateError?.code === 'P2009') {
|
||||
logger.warn('externalEventId field not available, updating without it', {
|
||||
// If externalEventId field doesn't exist in Prisma client (even though it exists in DB),
|
||||
// retry without it. This can happen if Prisma client wasn't regenerated after migration.
|
||||
const errorMessage = updateError?.message || '';
|
||||
const errorCode = updateError?.code || '';
|
||||
|
||||
if (errorMessage.includes('externalEventId') ||
|
||||
errorMessage.includes('Unknown argument') ||
|
||||
errorCode === 'P2009' ||
|
||||
errorCode === 'P1012') {
|
||||
logger.warn('externalEventId field not recognized by Prisma client, updating without it', {
|
||||
eventId: existingEvent.id,
|
||||
error: errorMessage.substring(0, 200),
|
||||
});
|
||||
const { externalEventId, ...dataWithoutExternalId } = baseEventData;
|
||||
await prisma.event.update({
|
||||
@ -562,9 +581,18 @@ export async function syncMicrosoftCalendar(
|
||||
start: caldavEvent.start.toISOString(),
|
||||
});
|
||||
} catch (createError: any) {
|
||||
// If externalEventId field doesn't exist, retry without it
|
||||
if (createError?.message?.includes('externalEventId') || createError?.code === 'P2009') {
|
||||
logger.warn('externalEventId field not available, creating without it');
|
||||
// If externalEventId field doesn't exist in Prisma client (even though it exists in DB),
|
||||
// retry without it. This can happen if Prisma client wasn't regenerated after migration.
|
||||
const errorMessage = createError?.message || '';
|
||||
const errorCode = createError?.code || '';
|
||||
|
||||
if (errorMessage.includes('externalEventId') ||
|
||||
errorMessage.includes('Unknown argument') ||
|
||||
errorCode === 'P2009' ||
|
||||
errorCode === 'P1012') {
|
||||
logger.warn('externalEventId field not recognized by Prisma client, creating without it', {
|
||||
error: errorMessage.substring(0, 200),
|
||||
});
|
||||
const { externalEventId, ...dataWithoutExternalId } = baseEventData;
|
||||
const newEvent = await prisma.event.create({
|
||||
data: {
|
||||
|
||||
81
scripts/verify-and-fix-prisma-client.ts
Normal file
81
scripts/verify-and-fix-prisma-client.ts
Normal file
@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env ts-node
|
||||
|
||||
/**
|
||||
* Script to verify Prisma client is up to date with schema
|
||||
* Run this to check if externalEventId field is available in Prisma client
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function verifyPrismaClient() {
|
||||
try {
|
||||
console.log('Checking if externalEventId field is available in Prisma client...\n');
|
||||
|
||||
// Try to access the externalEventId field in the Event model
|
||||
// If it doesn't exist, TypeScript/Prisma will throw an error at compile time
|
||||
// But we can check at runtime by trying to query with it
|
||||
|
||||
// Check if we can select externalEventId
|
||||
try {
|
||||
const testEvent = await prisma.event.findFirst({
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
externalEventId: true,
|
||||
externalEventUrl: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (testEvent !== null) {
|
||||
console.log('✅ Prisma client recognizes externalEventId and externalEventUrl fields');
|
||||
console.log(' Sample event:', {
|
||||
id: testEvent.id,
|
||||
title: testEvent.title,
|
||||
hasExternalEventId: 'externalEventId' in testEvent,
|
||||
hasExternalEventUrl: 'externalEventUrl' in testEvent,
|
||||
});
|
||||
} else {
|
||||
console.log('⚠️ No events found, but Prisma client seems to recognize the fields');
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error.message?.includes('externalEventId') || error.message?.includes('Unknown argument')) {
|
||||
console.error('❌ Prisma client does NOT recognize externalEventId field');
|
||||
console.error(' Error:', error.message);
|
||||
console.log('\n🔧 Solution:');
|
||||
console.log(' 1. Run: npx prisma generate');
|
||||
console.log(' 2. Restart your Next.js server');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Also check database directly
|
||||
const dbColumns = await prisma.$queryRaw<Array<{ column_name: string; data_type: string }>>`
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'Event'
|
||||
AND column_name IN ('externalEventId', 'externalEventUrl')
|
||||
`;
|
||||
|
||||
console.log('\n📊 Database columns:');
|
||||
if (dbColumns.length === 0) {
|
||||
console.log(' ❌ externalEventId and externalEventUrl columns NOT found in database');
|
||||
console.log(' 🔧 Run the migration: npx prisma migrate deploy');
|
||||
} else {
|
||||
console.log(' ✅ Database columns exist:');
|
||||
dbColumns.forEach(col => {
|
||||
console.log(` - ${col.column_name} (${col.data_type})`);
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.$disconnect();
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
await prisma.$disconnect();
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
verifyPrismaClient();
|
||||
Loading…
Reference in New Issue
Block a user