chore(repo): checkpoint current capakraken implementation state
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Updates PlanarchyExamples.xlsx with missing columns and documentation.
|
||||
* Adds: Display Name, Email, Skills, Planarchy Notes columns to EID sheet.
|
||||
* Adds: Start Date, End Date, Status, Planarchy Notes columns to Projects sheet.
|
||||
* Updates CapaKrakenExamples.xlsx with missing columns and documentation.
|
||||
* Adds: Display Name, Email, Skills, CapaKraken Notes columns to EID sheet.
|
||||
* Adds: Start Date, End Date, Status, CapaKraken Notes columns to Projects sheet.
|
||||
*/
|
||||
|
||||
import ExcelJS from "exceljs";
|
||||
@@ -11,7 +11,7 @@ import { dirname, join } from "path";
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const EXCEL_PATH = join(__dirname, "../../../samples/PlanarchyExamples.xlsx");
|
||||
const EXCEL_PATH = join(__dirname, "../../../samples/CapaKrakenExamples.xlsx");
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -23,7 +23,7 @@ function toDisplayName(eid) {
|
||||
}
|
||||
|
||||
function toEmail(eid) {
|
||||
return `${eid}@planarchy.example`;
|
||||
return `${eid}@capakraken.example`;
|
||||
}
|
||||
|
||||
function computeSkillLabel(chapter, typeOfWork) {
|
||||
@@ -36,8 +36,8 @@ function computeSkillLabel(chapter, typeOfWork) {
|
||||
return typeOfWork;
|
||||
}
|
||||
|
||||
function computePlanarchyEid(eid) {
|
||||
// In Planarchy the EID stays as firstname.lastname (unique key)
|
||||
function computeCapaKrakenEid(eid) {
|
||||
// In CapaKraken the EID stays as firstname.lastname (unique key)
|
||||
return eid;
|
||||
}
|
||||
|
||||
@@ -139,28 +139,28 @@ async function main() {
|
||||
// Column N: Display Name
|
||||
// Column O: Email
|
||||
// Column P: Skills (derived)
|
||||
// Column Q: Description / Notes for Planarchy
|
||||
// Column Q: Description / Notes for CapaKraken
|
||||
|
||||
const newEidCols = [
|
||||
{
|
||||
col: 14, // N
|
||||
header: "Display Name\n(auto-generated)",
|
||||
doc: "Full display name derived from EID (firstname.lastname → Firstname Lastname). Used as the person's name in Planarchy.",
|
||||
doc: "Full display name derived from EID (firstname.lastname → Firstname Lastname). Used as the person's name in CapaKraken.",
|
||||
},
|
||||
{
|
||||
col: 15, // O
|
||||
header: "Email\n(generated)",
|
||||
doc: "Generated email: firstname.lastname@planarchy.example. Required unique field in Planarchy. Replace with real email in production.",
|
||||
doc: "Generated email: firstname.lastname@capakraken.example. Required unique field in CapaKraken. Replace with real email in production.",
|
||||
},
|
||||
{
|
||||
col: 16, // P
|
||||
header: "Skills\n(derived from Chapter)",
|
||||
doc: "Skill tags assigned based on Chapter + Type of Work. Format: 'SkillA | SkillB'. Stored as JSON array in Planarchy with proficiency 1-5. Senior (LCR ≥ 118) → 5, Mid-Senior (LCR ≥ 95) → 4, Mid → 3.",
|
||||
doc: "Skill tags assigned based on Chapter + Type of Work. Format: 'SkillA | SkillB'. Stored as JSON array in CapaKraken with proficiency 1-5. Senior (LCR >= 118) -> 5, Mid-Senior (LCR >= 95) -> 4, Mid -> 3.",
|
||||
},
|
||||
{
|
||||
col: 17, // Q
|
||||
header: "Planarchy Notes",
|
||||
doc: "How data maps to Planarchy:\n• EID = unique key (col A)\n• Chapter = chapter field\n• LCR / UCR → multiply by 100 for integer cents (€85.00 → 8500)\n• Hours fraction × 8 = daily availability hours\n• Chargeability → multiply by 100 for % (0.75 → 75%)\n• Employee type, City, Client Unit → stored in dynamicFields JSONB",
|
||||
header: "CapaKraken Notes",
|
||||
doc: "How data maps to CapaKraken:\n- EID = unique key (col A)\n- Chapter = chapter field\n- LCR / UCR -> multiply by 100 for integer cents (EUR85.00 -> 8500)\n- Hours fraction x 8 = daily availability hours\n- Chargeability -> multiply by 100 for % (0.75 -> 75%)\n- Employee type, City, Client Unit -> stored in dynamicFields JSONB",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -214,18 +214,18 @@ async function main() {
|
||||
|
||||
// Also add doc notes to existing header columns A-M in row 1
|
||||
const eidExistingDocs = [
|
||||
"Unique identifier. Used as EID in Planarchy (no EMP-XXX prefix needed). e.g. steve.rogers",
|
||||
"Team / department. Maps to 'chapter' field in Planarchy.",
|
||||
"Unique identifier. Used as EID in CapaKraken (no EMP-XXX prefix needed). e.g. steve.rogers",
|
||||
"Team / department. Maps to 'chapter' field in CapaKraken.",
|
||||
"Specialization within chapter. Stored in dynamicFields.workType.",
|
||||
"Assigned client account. Stored in dynamicFields.clientUnit.",
|
||||
"Unit-specific field. Currently unused — can be stored in dynamicFields.",
|
||||
"Office city location. Stored in dynamicFields.city.",
|
||||
"Employment type: Employee or Freelancer. Stored in dynamicFields.employeeType.",
|
||||
"Loaded Cost Rate (LCR) in EUR/h. Multiply × 100 for Planarchy cents. e.g. 133.77 → 13377",
|
||||
"Loaded Cost Rate (LCR) in EUR/h. Multiply × 100 for CapaKraken cents. e.g. 133.77 → 13377",
|
||||
"Unloaded/Utilization Cost Rate (UCR) in EUR/h. Multiply × 100 for cents.",
|
||||
"FTE fraction (1.0 = 40h/week, 0.8 = 4 days, 0.5 = 20h/week). Combined with col K for availability JSON.",
|
||||
"Available weekdays. 'all' = Mon-Fri. Specific days listed = only those days active at 8h.",
|
||||
"Chargeability target as decimal. Multiply × 100 for Planarchy % (0.75 → 75%).",
|
||||
"Chargeability target as decimal. Multiply × 100 for CapaKraken % (0.75 → 75%).",
|
||||
"(unused)",
|
||||
];
|
||||
for (let c = 1; c <= 13; c++) {
|
||||
@@ -254,12 +254,12 @@ async function main() {
|
||||
{
|
||||
col: 19, // S
|
||||
header: "Status\n(derived)",
|
||||
doc: "Planarchy status derived from 'is ordered' + win probability + date:\n• COMPLETED: ordered + 100% + past dates\n• ACTIVE: ordered + 100% + current/future\n• ON_HOLD: ordered but paused\n• DRAFT: not ordered or low win probability",
|
||||
doc: "CapaKraken status derived from 'is ordered' + win probability + date:\n• COMPLETED: ordered + 100% + past dates\n• ACTIVE: ordered + 100% + current/future\n• ON_HOLD: ordered but paused\n• DRAFT: not ordered or low win probability",
|
||||
},
|
||||
{
|
||||
col: 20, // T
|
||||
header: "Planarchy Notes",
|
||||
doc: "How data maps to Planarchy:\n• Col C (short code) → shortCode (unique key)\n• Col B → name\n• BD/CH/UN → OrderType: BD / CHARGEABLE / INTERNAL\n• Internal/External → allocationType: INT / EXT\n• Resource Costs (col I) × 100 = budgetCents in Planarchy\n• Col H (chargability %) → stored in dynamicFields.chargeabilityPercent\n• Col J (person hours) → stored in dynamicFields.personHoursSold\n• Col O (classification) → stored in dynamicFields.classification",
|
||||
header: "CapaKraken Notes",
|
||||
doc: "How data maps to CapaKraken:\n• Col C (short code) → shortCode (unique key)\n• Col B → name\n• BD/CH/UN → OrderType: BD / CHARGEABLE / INTERNAL\n• Internal/External → allocationType: INT / EXT\n• Resource Costs (col I) × 100 = budgetCents in CapaKraken\n• Col H (chargability %) → stored in dynamicFields.chargeabilityPercent\n• Col J (person hours) → stored in dynamicFields.personHoursSold\n• Col O (classification) → stored in dynamicFields.classification",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -286,21 +286,21 @@ async function main() {
|
||||
|
||||
const projExistingDocs = [
|
||||
"Client Unit tag. e.g. [DAI]=Daimler, [PAG]=Porsche AG, [BMW], [JLR]=Jaguar Land Rover. Stored in dynamicFields.clientUnit.",
|
||||
"Full project name → maps to Planarchy 'name' field.",
|
||||
"Short internal project code (5-6 chars) → maps to Planarchy 'shortCode' (unique key). e.g. JLFJFL",
|
||||
"Full project name → maps to CapaKraken 'name' field.",
|
||||
"Short internal project code (5-6 chars) → maps to CapaKraken 'shortCode' (unique key). e.g. JLFJFL",
|
||||
"'yes'/'no' — whether the project is formally ordered. Drives status: yes+100% → ACTIVE/COMPLETED.",
|
||||
"Order type: BD=Business Development, CH=Chargeable, UN=Internal/Unordered. Maps to Planarchy OrderType.",
|
||||
"Win probability 0-100. Used in Planarchy 'winProbability' field for pipeline forecasting.",
|
||||
"Allocation type: Internal → INT, External → EXT. Maps to Planarchy 'allocationType' field.",
|
||||
"Order type: BD=Business Development, CH=Chargeable, UN=Internal/Unordered. Maps to CapaKraken OrderType.",
|
||||
"Win probability 0-100. Used in CapaKraken 'winProbability' field for pipeline forecasting.",
|
||||
"Allocation type: Internal → INT, External → EXT. Maps to CapaKraken 'allocationType' field.",
|
||||
"Chargeability % as decimal. Stored in dynamicFields.chargeabilityPercent.",
|
||||
"Planned resource cost in EUR. Multiply × 100 for Planarchy budgetCents. e.g. 78799 → 7879900 cents.",
|
||||
"Planned resource cost in EUR. Multiply × 100 for CapaKraken budgetCents. e.g. 78799 → 7879900 cents.",
|
||||
"Person hours planned/sold. Stored in dynamicFields.personHoursSold for budget tracking.",
|
||||
"Team staffing (empty in source). Would list assigned EIDs. Handled by Allocations in Planarchy.",
|
||||
"Team staffing (empty in source). Would list assigned EIDs. Handled by Allocations in CapaKraken.",
|
||||
"Day project sold (empty in source). Could be stored as dynamicFields.dateSold.",
|
||||
"Project start date (empty in source → synthesized in col Q). Maps to Planarchy 'startDate'.",
|
||||
"Project end date (empty in source → synthesized in col R). Maps to Planarchy 'endDate'.",
|
||||
"Project start date (empty in source → synthesized in col Q). Maps to CapaKraken 'startDate'.",
|
||||
"Project end date (empty in source → synthesized in col R). Maps to CapaKraken 'endDate'.",
|
||||
"Confidentiality: Confidential / Not Confidential. Stored in dynamicFields.classification.",
|
||||
"Responsible EID / Owner (empty in source). Would map to a PM allocation in Planarchy.",
|
||||
"Responsible EID / Owner (empty in source). Would map to a PM allocation in CapaKraken.",
|
||||
];
|
||||
for (let c = 1; c <= 16; c++) {
|
||||
const doc = projExistingDocs[c - 1];
|
||||
@@ -329,15 +329,15 @@ async function main() {
|
||||
projSheet.getColumn(19).width = 16;
|
||||
projSheet.getColumn(20).width = 50;
|
||||
|
||||
// ─── Add a "Planarchy Data Model" sheet ──────────────────────────────────
|
||||
// ─── Add a "CapaKraken Data Model" sheet ──────────────────────────────────
|
||||
|
||||
let modelSheet = workbook.getWorksheet("Planarchy Data Model");
|
||||
let modelSheet = workbook.getWorksheet("CapaKraken Data Model");
|
||||
if (!modelSheet) {
|
||||
modelSheet = workbook.addWorksheet("Planarchy Data Model");
|
||||
modelSheet = workbook.addWorksheet("CapaKraken Data Model");
|
||||
}
|
||||
|
||||
const modelData = [
|
||||
["Planarchy Data Model — Field Reference", "", "", "", ""],
|
||||
["CapaKraken Data Model — Field Reference", "", "", "", ""],
|
||||
["", "", "", "", ""],
|
||||
["RESOURCE FIELDS", "", "", "", ""],
|
||||
["Field", "Type", "Required", "Example", "Description"],
|
||||
@@ -393,7 +393,7 @@ async function main() {
|
||||
// Style title row
|
||||
const titleCell = modelSheet.getCell(1, 1);
|
||||
titleCell.font = { bold: true, size: 14, color: { argb: "FF4F46E5" } };
|
||||
titleCell.value = "Planarchy Data Model — Field Reference";
|
||||
titleCell.value = "CapaKraken Data Model — Field Reference";
|
||||
|
||||
// Style section headers and field headers
|
||||
const sectionRows = [3, 17, 31];
|
||||
@@ -421,7 +421,7 @@ async function main() {
|
||||
console.log(`✅ Excel updated: ${EXCEL_PATH}`);
|
||||
console.log(" - EID_Informationen: added Display Name, Email, Skills, Notes columns");
|
||||
console.log(" - Projektinfomartionen: added Start Date, End Date, Status, Notes columns");
|
||||
console.log(" - Added new sheet: 'Planarchy Data Model' (field reference)");
|
||||
console.log(" - Added new sheet: 'CapaKraken Data Model' (field reference)");
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
|
||||
Reference in New Issue
Block a user