288 lines
8.1 KiB
TypeScript
288 lines
8.1 KiB
TypeScript
import {
|
|
approveEstimateVersion,
|
|
createEstimate,
|
|
createEstimateExport,
|
|
createEstimateRevision,
|
|
submitEstimateVersion,
|
|
updateEstimateDraft,
|
|
} from "../../packages/application/src/index.js";
|
|
import { PrismaClient } from "../../packages/db/src/index.js";
|
|
import { loadWorkspaceEnv } from "../../packages/db/src/load-workspace-env.js";
|
|
import { EstimateExportFormat } from "../../packages/shared/src/index.js";
|
|
|
|
loadWorkspaceEnv();
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
async function main() {
|
|
const created = await createEstimate(prisma, {
|
|
name: "Codex Smoke Estimate",
|
|
baseCurrency: "EUR",
|
|
assumptions: [
|
|
{
|
|
category: "commercial",
|
|
key: "delivery_model",
|
|
label: "Delivery Model",
|
|
valueType: "string",
|
|
value: "hybrid",
|
|
sortOrder: 0,
|
|
},
|
|
],
|
|
scopeItems: [
|
|
{
|
|
sequenceNo: 1,
|
|
scopeType: "SHOT",
|
|
name: "Smoke Scope",
|
|
technicalSpec: {},
|
|
sortOrder: 0,
|
|
metadata: {},
|
|
},
|
|
],
|
|
demandLines: [
|
|
{
|
|
lineType: "LABOR",
|
|
name: "Senior Comp",
|
|
hours: 40,
|
|
costRateCents: 5000,
|
|
billRateCents: 9000,
|
|
costTotalCents: 200000,
|
|
priceTotalCents: 360000,
|
|
currency: "EUR",
|
|
monthlySpread: {},
|
|
staffingAttributes: {},
|
|
metadata: {},
|
|
},
|
|
],
|
|
resourceSnapshots: [],
|
|
metrics: [
|
|
{
|
|
key: "total_hours",
|
|
label: "Total Hours",
|
|
metricGroup: "summary",
|
|
valueDecimal: 40,
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "total_cost",
|
|
label: "Total Cost",
|
|
metricGroup: "summary",
|
|
valueDecimal: 2000,
|
|
valueCents: 200000,
|
|
currency: "EUR",
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "total_price",
|
|
label: "Total Price",
|
|
metricGroup: "summary",
|
|
valueDecimal: 3600,
|
|
valueCents: 360000,
|
|
currency: "EUR",
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "margin",
|
|
label: "Margin",
|
|
metricGroup: "summary",
|
|
valueDecimal: 1600,
|
|
valueCents: 160000,
|
|
currency: "EUR",
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "margin_percent",
|
|
label: "Margin %",
|
|
metricGroup: "summary",
|
|
valueDecimal: 44.4444,
|
|
metadata: {},
|
|
},
|
|
],
|
|
});
|
|
|
|
try {
|
|
const workingVersion = created.versions[0];
|
|
|
|
const updated = await updateEstimateDraft(prisma, {
|
|
id: created.id,
|
|
name: "Codex Smoke Estimate Updated",
|
|
baseCurrency: "EUR",
|
|
versionLabel: "Working Draft",
|
|
versionNotes: "updated by smoke test",
|
|
assumptions: [
|
|
{
|
|
id: workingVersion.assumptions[0]?.id,
|
|
category: "commercial",
|
|
key: "delivery_model",
|
|
label: "Delivery Model",
|
|
valueType: "string",
|
|
value: "onsite",
|
|
sortOrder: 0,
|
|
},
|
|
],
|
|
scopeItems: workingVersion.scopeItems.map((item, index) => ({
|
|
id: item.id,
|
|
sequenceNo: item.sequenceNo,
|
|
scopeType: item.scopeType,
|
|
...(item.description ? { description: item.description } : {}),
|
|
name: item.name,
|
|
technicalSpec: {},
|
|
sortOrder: index,
|
|
metadata: {},
|
|
})),
|
|
demandLines: workingVersion.demandLines.map((line) => ({
|
|
id: line.id,
|
|
...(line.scopeItemId ? { scopeItemId: line.scopeItemId } : {}),
|
|
...(line.roleId ? { roleId: line.roleId } : {}),
|
|
...(line.resourceId ? { resourceId: line.resourceId } : {}),
|
|
lineType: line.lineType,
|
|
name: line.name,
|
|
hours: 48,
|
|
costRateCents: line.costRateCents,
|
|
billRateCents: line.billRateCents,
|
|
costTotalCents: 240000,
|
|
priceTotalCents: 432000,
|
|
currency: line.currency,
|
|
monthlySpread: {},
|
|
staffingAttributes: {},
|
|
metadata: {},
|
|
})),
|
|
resourceSnapshots: workingVersion.resourceSnapshots.map((snapshot) => ({
|
|
id: snapshot.id,
|
|
...(snapshot.resourceId ? { resourceId: snapshot.resourceId } : {}),
|
|
...(snapshot.sourceEid ? { sourceEid: snapshot.sourceEid } : {}),
|
|
displayName: snapshot.displayName,
|
|
...(snapshot.chapter ? { chapter: snapshot.chapter } : {}),
|
|
...(snapshot.roleId ? { roleId: snapshot.roleId } : {}),
|
|
currency: snapshot.currency,
|
|
lcrCents: snapshot.lcrCents,
|
|
ucrCents: snapshot.ucrCents,
|
|
...(snapshot.fte != null ? { fte: snapshot.fte } : {}),
|
|
...(snapshot.location ? { location: snapshot.location } : {}),
|
|
...(snapshot.country ? { country: snapshot.country } : {}),
|
|
...(snapshot.level ? { level: snapshot.level } : {}),
|
|
...(snapshot.workType ? { workType: snapshot.workType } : {}),
|
|
attributes:
|
|
typeof snapshot.attributes === "object" &&
|
|
snapshot.attributes !== null &&
|
|
!Array.isArray(snapshot.attributes)
|
|
? snapshot.attributes
|
|
: {},
|
|
})),
|
|
metrics: [
|
|
{
|
|
key: "total_hours",
|
|
label: "Total Hours",
|
|
metricGroup: "summary",
|
|
valueDecimal: 48,
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "total_cost",
|
|
label: "Total Cost",
|
|
metricGroup: "summary",
|
|
valueDecimal: 2400,
|
|
valueCents: 240000,
|
|
currency: "EUR",
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "total_price",
|
|
label: "Total Price",
|
|
metricGroup: "summary",
|
|
valueDecimal: 4320,
|
|
valueCents: 432000,
|
|
currency: "EUR",
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "margin",
|
|
label: "Margin",
|
|
metricGroup: "summary",
|
|
valueDecimal: 1920,
|
|
valueCents: 192000,
|
|
currency: "EUR",
|
|
metadata: {},
|
|
},
|
|
{
|
|
key: "margin_percent",
|
|
label: "Margin %",
|
|
metricGroup: "summary",
|
|
valueDecimal: 44.4444,
|
|
metadata: {},
|
|
},
|
|
],
|
|
});
|
|
|
|
const submitted = await submitEstimateVersion(prisma, {
|
|
estimateId: created.id,
|
|
});
|
|
|
|
const approved = await approveEstimateVersion(prisma, {
|
|
estimateId: created.id,
|
|
});
|
|
|
|
const revised = await createEstimateRevision(prisma, {
|
|
estimateId: created.id,
|
|
sourceVersionId:
|
|
approved.versions.find((version) => version.status === "APPROVED")?.id ??
|
|
approved.versions[0]?.id,
|
|
});
|
|
|
|
const exported = await createEstimateExport(prisma, {
|
|
estimateId: created.id,
|
|
versionId: revised.versions.find((version) => version.status === "WORKING")?.id,
|
|
format: EstimateExportFormat.JSON,
|
|
});
|
|
|
|
const refreshed = await prisma.estimate.findUnique({
|
|
where: { id: created.id },
|
|
include: {
|
|
versions: {
|
|
include: {
|
|
assumptions: true,
|
|
demandLines: true,
|
|
metrics: true,
|
|
exports: true,
|
|
},
|
|
orderBy: { versionNumber: "desc" },
|
|
},
|
|
},
|
|
});
|
|
|
|
console.log(
|
|
JSON.stringify({
|
|
createdId: created.id,
|
|
updatedName: updated.name,
|
|
versionLabel: updated.versions[0]?.label ?? null,
|
|
assumptionValue: refreshed?.versions[0]?.assumptions[0]?.value ?? null,
|
|
updatedHours: refreshed?.versions[0]?.demandLines[0]?.hours ?? null,
|
|
metricKeys: refreshed?.versions[0]?.metrics.map((metric) => metric.key) ?? [],
|
|
submittedStatus:
|
|
submitted.versions.find((version) => version.status === "SUBMITTED")?.status ??
|
|
null,
|
|
approvedStatus:
|
|
approved.versions.find((version) => version.status === "APPROVED")?.status ??
|
|
null,
|
|
revisionVersionNumber:
|
|
revised.versions.find((version) => version.status === "WORKING")
|
|
?.versionNumber ?? null,
|
|
exportFileName:
|
|
exported.versions[0]?.exports[0]?.fileName ??
|
|
refreshed?.versions[0]?.exports[0]?.fileName ??
|
|
null,
|
|
}),
|
|
);
|
|
} finally {
|
|
await prisma.estimate.delete({ where: { id: created.id } });
|
|
}
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|