chore(repo): initialize planarchy workspace
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user