chore(repo): initialize planarchy workspace
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
pnpm --filter @planarchy/db db:generate
|
||||
exec pnpm --filter @planarchy/web exec next dev -H 0.0.0.0 -p 3100
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@planarchy/eslint-config",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./base": "./src/base.js",
|
||||
"./nextjs": "./src/nextjs.js"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
||||
"@typescript-eslint/parser": "^8.18.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.31.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^9.0.0",
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import prettierConfig from "eslint-config-prettier";
|
||||
|
||||
/** @type {import("eslint").Linter.FlatConfig[]} */
|
||||
export default [
|
||||
{
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
plugins: {
|
||||
"@typescript-eslint": tsPlugin,
|
||||
},
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
project: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
...tsPlugin.configs["recommended"].rules,
|
||||
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"no-console": ["warn", { allow: ["warn", "error"] }],
|
||||
},
|
||||
},
|
||||
prettierConfig,
|
||||
];
|
||||
@@ -0,0 +1,14 @@
|
||||
import baseConfig from "./base.js";
|
||||
|
||||
/** @type {import("eslint").Linter.FlatConfig[]} */
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
rules: {
|
||||
"@typescript-eslint/no-misused-promises": [
|
||||
"error",
|
||||
{ checksVoidReturn: { attributes: false } },
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"plugins": ["prettier-plugin-tailwindcss"]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@planarchy/prettier-config",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"exports": {
|
||||
".": "./index.json"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
import {
|
||||
approveEstimateVersion,
|
||||
createEstimate,
|
||||
createEstimateExport,
|
||||
createEstimateRevision,
|
||||
submitEstimateVersion,
|
||||
updateEstimateDraft,
|
||||
} from "../../packages/application/src/index.js";
|
||||
import { PrismaClient } from "../../packages/db/src/index.js";
|
||||
import { EstimateExportFormat } from "../../packages/shared/src/index.js";
|
||||
|
||||
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();
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022"],
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"strict": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "coverage"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "./base.json",
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"allowJs": true,
|
||||
"jsx": "preserve",
|
||||
"plugins": [{ "name": "next" }],
|
||||
"incremental": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "coverage"]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@planarchy/tsconfig",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"files": ["*.json"],
|
||||
"license": "MIT"
|
||||
}
|
||||
Reference in New Issue
Block a user