98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
/**
|
||
* @module algo.followUpScheduler
|
||
*
|
||
* Follow-Up Scheduling Algorithm
|
||
* ===============================
|
||
*
|
||
* Determines the due date for follow-up activities created by the
|
||
* opportunity workflow. The follow-up is always assigned to the user
|
||
* who triggered its creation.
|
||
*
|
||
* ## TODO — Calendar-aware scheduling
|
||
*
|
||
* This module currently uses a **dummy algorithm** that schedules the
|
||
* follow-up for the next business day at 10:00 AM local time.
|
||
*
|
||
* It needs to be replaced with an availability-aware algorithm that:
|
||
* 1. Reads the assigned user's calendar (Microsoft Graph / CW schedule).
|
||
* 2. Finds the earliest open slot of sufficient duration.
|
||
* 3. Respects company-wide blackout dates (holidays, company events).
|
||
* 4. Accounts for the user's working-hours preferences.
|
||
*
|
||
* Until that integration is complete, the simple "next business day"
|
||
* heuristic is used as a placeholder.
|
||
*/
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Types
|
||
// ---------------------------------------------------------------------------
|
||
|
||
export interface FollowUpScheduleInput {
|
||
/** The user who triggered the activity (follow-up is assigned to them). */
|
||
triggeredByUserId: string;
|
||
|
||
/** Optional override for "now" — useful for testing. */
|
||
now?: Date;
|
||
}
|
||
|
||
export interface FollowUpScheduleResult {
|
||
/** Suggested due date for the follow-up activity. */
|
||
dueDate: Date;
|
||
|
||
/** ISO string version for CW API payloads. */
|
||
dueDateIso: string;
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Core
|
||
// ---------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Schedule a follow-up activity.
|
||
*
|
||
* Returns a suggested `dueDate` for the follow-up activity.
|
||
* Currently uses dummy logic: next business day at 10:00 AM.
|
||
*
|
||
* @param input - Scheduling parameters
|
||
* @returns The scheduled follow-up date
|
||
*/
|
||
export function scheduleFollowUp(
|
||
input: FollowUpScheduleInput,
|
||
): FollowUpScheduleResult {
|
||
const now = input.now ?? new Date();
|
||
const dueDate = getNextBusinessDay(now);
|
||
|
||
// Set to 10:00 AM
|
||
dueDate.setHours(10, 0, 0, 0);
|
||
|
||
return {
|
||
dueDate,
|
||
dueDateIso: dueDate.toISOString(),
|
||
};
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Helpers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Returns the next business day (Mon–Fri) from the given date.
|
||
* If the given date is already a weekday before 10 AM, returns
|
||
* the NEXT business day (not the same day).
|
||
*/
|
||
function getNextBusinessDay(from: Date): Date {
|
||
const result = new Date(from);
|
||
|
||
// Always advance at least one day
|
||
result.setDate(result.getDate() + 1);
|
||
|
||
const day = result.getDay();
|
||
|
||
// Saturday → Monday (+2)
|
||
if (day === 6) result.setDate(result.getDate() + 2);
|
||
// Sunday → Monday (+1)
|
||
if (day === 0) result.setDate(result.getDate() + 1);
|
||
|
||
return result;
|
||
}
|