chore(repo): initialize planarchy workspace
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import * as XLSX from "xlsx";
|
||||
import {
|
||||
EstimateExportFormat,
|
||||
EstimateStatus,
|
||||
EstimateVersionStatus,
|
||||
} from "@planarchy/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
serializeEstimateExport,
|
||||
type EstimateExportSource,
|
||||
} from "../estimate/export-serializer.js";
|
||||
|
||||
const createdAt = new Date("2026-03-13T08:00:00.000Z");
|
||||
|
||||
function buildSource(): EstimateExportSource {
|
||||
return {
|
||||
estimate: {
|
||||
id: "est_1",
|
||||
projectId: "project_1",
|
||||
name: "CGI Estimate",
|
||||
opportunityId: "OP-42",
|
||||
baseCurrency: "EUR",
|
||||
status: EstimateStatus.APPROVED,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
},
|
||||
project: {
|
||||
id: "project_1",
|
||||
shortCode: "CGI-001",
|
||||
name: "CGI Project",
|
||||
status: "ACTIVE",
|
||||
startDate: "2026-03-01T00:00:00.000Z",
|
||||
endDate: "2026-04-01T00:00:00.000Z",
|
||||
},
|
||||
version: {
|
||||
id: "ver_1",
|
||||
versionNumber: 1,
|
||||
label: "Approved",
|
||||
status: EstimateVersionStatus.APPROVED,
|
||||
notes: "Ready for export",
|
||||
lockedAt: createdAt,
|
||||
projectSnapshot: {},
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
assumptions: [
|
||||
{
|
||||
id: "assumption_1",
|
||||
category: "commercial",
|
||||
key: "pricingStructure",
|
||||
label: "Pricing Structure",
|
||||
valueType: "string",
|
||||
value: "fixed-bid",
|
||||
sortOrder: 0,
|
||||
notes: null,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
},
|
||||
],
|
||||
scopeItems: [
|
||||
{
|
||||
id: "scope_1",
|
||||
sequenceNo: 10,
|
||||
scopeType: "SHOT",
|
||||
packageCode: "PKG-1",
|
||||
name: "Shot 010",
|
||||
description: "Main hero shot",
|
||||
scene: "Scene 01",
|
||||
page: null,
|
||||
location: "Berlin",
|
||||
assumptionCategory: null,
|
||||
technicalSpec: { resolution: "4K" },
|
||||
frameCount: 120,
|
||||
itemCount: 1,
|
||||
unitMode: "shot",
|
||||
internalComments: null,
|
||||
externalComments: null,
|
||||
metadata: {},
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
},
|
||||
],
|
||||
demandLines: [
|
||||
{
|
||||
id: "line_1",
|
||||
scopeItemId: "scope_1",
|
||||
roleId: "role_1",
|
||||
resourceId: "resource_1",
|
||||
lineType: "LABOR",
|
||||
name: "Comp Artist",
|
||||
chapter: "Compositing",
|
||||
hours: 40,
|
||||
days: 5,
|
||||
fte: 1,
|
||||
rateSource: "resource",
|
||||
costRateCents: 5000,
|
||||
billRateCents: 8000,
|
||||
currency: "EUR",
|
||||
costTotalCents: 200000,
|
||||
priceTotalCents: 320000,
|
||||
monthlySpread: { "2026-03": 40 },
|
||||
staffingAttributes: { location: "Berlin" },
|
||||
metadata: {},
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
},
|
||||
],
|
||||
resourceSnapshots: [
|
||||
{
|
||||
id: "snapshot_1",
|
||||
resourceId: "resource_1",
|
||||
sourceEid: "E100",
|
||||
displayName: "Alex Artist",
|
||||
chapter: "Compositing",
|
||||
roleId: "role_1",
|
||||
currency: "EUR",
|
||||
lcrCents: 5000,
|
||||
ucrCents: 8000,
|
||||
fte: 1,
|
||||
location: "Berlin",
|
||||
country: "DE",
|
||||
level: "Senior",
|
||||
workType: "Remote",
|
||||
attributes: {},
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
},
|
||||
],
|
||||
metrics: [
|
||||
{
|
||||
id: "metric_1",
|
||||
key: "total_hours",
|
||||
label: "Total Hours",
|
||||
metricGroup: "summary",
|
||||
valueDecimal: 40,
|
||||
valueCents: null,
|
||||
currency: null,
|
||||
metadata: {},
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("estimate export serializer", () => {
|
||||
it("creates a structured JSON export payload", () => {
|
||||
const payload = serializeEstimateExport(buildSource(), EstimateExportFormat.JSON);
|
||||
|
||||
expect(payload.encoding).toBe("utf8");
|
||||
expect(payload.mimeType).toBe("application/json; charset=utf-8");
|
||||
expect(payload.summary.totalHours).toBe(40);
|
||||
expect(payload.content).toContain('"estimateId": "est_1"');
|
||||
expect(payload.previewText).toContain('"schemaVersion": 1');
|
||||
});
|
||||
|
||||
it("creates a multi-sheet xlsx export payload", () => {
|
||||
const payload = serializeEstimateExport(buildSource(), EstimateExportFormat.XLSX);
|
||||
const workbook = XLSX.read(payload.content, { type: "base64" });
|
||||
|
||||
expect(payload.encoding).toBe("base64");
|
||||
expect(payload.sheetNames).toEqual([
|
||||
"Overview",
|
||||
"Assumptions",
|
||||
"Scope",
|
||||
"DemandLines",
|
||||
"Resources",
|
||||
"Metrics",
|
||||
]);
|
||||
expect(workbook.SheetNames).toContain("DemandLines");
|
||||
expect(payload.byteLength).toBeGreaterThan(100);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user