Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import { Injectable, Logger } from '@nestjs/common'; import { AvailabilityEngine } from './availability.engine'; export interface ConflictResult { hasConflict: boolean; severity: 'warning' | 'blocking' | 'override_allowed' | 'approval_required'; conflictType?: string; reason?: string; } @Injectable() export class ConflictDetectionService { private readonly logger = new Logger(ConflictDetectionService.name); constructor(private readonly availabilityEngine: AvailabilityEngine) {} /** * Checks if scheduling a slot conflicts with other attendees or resources. */ async checkConflicts( tenantId: string, participantIds: string[], resourceIds: string[], startAt: Date, endAt: Date, allowDoubleBooking = false ): Promise<ConflictResult> { const busy = await this.availabilityEngine.findBusyIntervals( tenantId, participantIds, resourceIds, startAt, endAt, false ); if (busy.length === 0) { return { hasConflict: false, severity: 'warning' }; // no conflict } // Determine type of conflict const reasons = busy.map(b => `${b.title || 'Busy'} (${b.startAt.toISOString()} - ${b.endAt.toISOString()})`); if (allowDoubleBooking) { return { hasConflict: true, severity: 'override_allowed', conflictType: 'ParticipantOverlap', reason: `Double booking allowed but conflicts exist: ${reasons.join(', ')}` }; } return { hasConflict: true, severity: 'blocking', conflictType: 'DoubleBooking', reason: `Conflict detected: ${reasons.join(', ')}` }; } } |