Files
CapaKraken/packages/shared/src/constants/dispo-import.ts
T

179 lines
4.8 KiB
TypeScript

import type { WeekdayAvailability } from "../types/resource.js";
export const DISPO_RESOURCE_CHAPTER_BY_TOKEN = {
"2D": "Digital Content Production",
"3D": "Digital Content Production",
PM: "Project Management",
AD: "Art Direction",
} as const;
export const DISPO_ASSIGNMENT_ROLE_BY_TOKEN = {
"2D": "2D Artist",
"3D": "3D Artist",
PM: "Project Manager",
AD: "Art Director",
} as const;
export const DISPO_UTILIZATION_CODE_BY_TOKEN = {
CH: "Chg",
MO: "M&O",
MD: "MD&I",
PD: "PD&R",
AB: "Absence",
NA: "Absence",
UN: null,
} as const;
export const DISPO_UTILIZATION_CATEGORIES = [
{
code: "Chg",
name: "Chargeable",
description: "Billable client project work",
sortOrder: 1,
isDefault: true,
},
{
code: "BD",
name: "Business Development",
description: "Sales, proposals, presales activities",
sortOrder: 2,
isDefault: false,
},
{
code: "MD&I",
name: "Market Development & Initiatives",
description: "R&D, innovation, market development",
sortOrder: 3,
isDefault: false,
},
{
code: "M&O",
name: "Management & Operations",
description: "Internal admin, management overhead",
sortOrder: 4,
isDefault: false,
},
{
code: "PD&R",
name: "People Development & Recruitment",
description: "Training, hiring, onboarding",
sortOrder: 5,
isDefault: false,
},
{
code: "Absence",
name: "Absence & Non Standard",
description: "Vacation, illness, non-standard leave (reduces SAH)",
sortOrder: 6,
isDefault: false,
},
] as const;
export const DISPO_INTERNAL_PROJECT_BUCKETS = [
{
sourceToken: "MO",
shortCode: "INT-MO",
name: "Management & Operations",
utilizationCategoryCode: "M&O",
},
{
sourceToken: "MD",
shortCode: "INT-MD",
name: "Market Development & Initiatives",
utilizationCategoryCode: "MD&I",
},
{
sourceToken: "PD",
shortCode: "INT-PD",
name: "People Development & Recruitment",
utilizationCategoryCode: "PD&R",
},
] as const;
export const DISPO_REQUIRED_ROLE_SEEDS = [
{
name: "2D Artist",
description: "Canonical Dispo assignment role for 2D delivery work",
},
{
name: "3D Artist",
description: "Canonical Dispo assignment role for 3D delivery work",
},
{
name: "Project Manager",
description: "Canonical Dispo assignment role for project management delivery",
},
{
name: "Art Director",
description: "Canonical Dispo assignment role for art direction delivery",
},
] as const;
export type DispoRoleToken = keyof typeof DISPO_ASSIGNMENT_ROLE_BY_TOKEN;
export type DispoChapterToken = keyof typeof DISPO_RESOURCE_CHAPTER_BY_TOKEN;
export type DispoUtilizationToken = keyof typeof DISPO_UTILIZATION_CODE_BY_TOKEN;
export type DispoInternalBucketDefinition = (typeof DISPO_INTERNAL_PROJECT_BUCKETS)[number];
function normalizeDispoTokenValue(value: string): string {
return value.trim().replace(/\s+/g, " ").toUpperCase();
}
function roundToTwoDecimals(value: number): number {
return Math.round(value * 100) / 100;
}
export function normalizeCanonicalResourceIdentity(value: string): string {
return value.trim().toLowerCase();
}
export function resolveCanonicalResourceIdentity(enterpriseId?: string | null, eid?: string | null) {
const normalizedEnterpriseId = enterpriseId ? normalizeCanonicalResourceIdentity(enterpriseId) : null;
const normalizedEid = eid ? normalizeCanonicalResourceIdentity(eid) : null;
const conflict = Boolean(
normalizedEnterpriseId &&
normalizedEid &&
normalizedEnterpriseId !== normalizedEid,
);
return {
canonicalId: conflict ? null : normalizedEnterpriseId ?? normalizedEid,
normalizedEnterpriseId,
normalizedEid,
conflict,
};
}
export function normalizeDispoChapterToken(token?: string | null): string | null {
if (!token) return null;
const normalizedToken = normalizeDispoTokenValue(token) as DispoChapterToken;
return DISPO_RESOURCE_CHAPTER_BY_TOKEN[normalizedToken] ?? null;
}
export function normalizeDispoRoleToken(token?: string | null): string | null {
if (!token) return null;
const normalizedToken = normalizeDispoTokenValue(token) as DispoRoleToken;
return DISPO_ASSIGNMENT_ROLE_BY_TOKEN[normalizedToken] ?? null;
}
export function normalizeDispoUtilizationToken(token?: string | null): string | null {
if (!token) return null;
const normalizedToken = normalizeDispoTokenValue(token) as DispoUtilizationToken;
return DISPO_UTILIZATION_CODE_BY_TOKEN[normalizedToken] ?? null;
}
export function createWeekdayAvailabilityFromFte(
fte: number,
dailyWorkingHours = 8,
): WeekdayAvailability {
const safeFte = Math.min(Math.max(fte, 0), 1);
const hoursPerDay = roundToTwoDecimals(dailyWorkingHours * safeFte);
return {
monday: hoursPerDay,
tuesday: hoursPerDay,
wednesday: hoursPerDay,
thursday: hoursPerDay,
friday: hoursPerDay,
};
}