refactor(api): extract effort rule support
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildEstimateDemandLineRows,
|
||||
buildEffortRuleCreateManyRows,
|
||||
buildEffortRuleNestedCreateRows,
|
||||
buildEffortRuleSetCreateData,
|
||||
buildEffortRuleSetUpdateData,
|
||||
effortRuleInclude,
|
||||
toEffortRuleEngineInputs,
|
||||
toScopeItemInputs,
|
||||
} from "../router/effort-rule-support.js";
|
||||
|
||||
describe("effort rule support", () => {
|
||||
it("exposes the rule include ordering", () => {
|
||||
expect(effortRuleInclude).toEqual({
|
||||
rules: { orderBy: { sortOrder: "asc" } },
|
||||
});
|
||||
});
|
||||
|
||||
it("builds rule rows and preserves fallback sort order", () => {
|
||||
expect(buildEffortRuleCreateManyRows([
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
chapter: "VFX",
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
},
|
||||
{
|
||||
scopeType: "asset",
|
||||
discipline: "Modeling",
|
||||
unitMode: "per_item",
|
||||
hoursPerUnit: 8,
|
||||
description: "Hero asset",
|
||||
sortOrder: 5,
|
||||
},
|
||||
], "ers_1")).toEqual([
|
||||
{
|
||||
ruleSetId: "ers_1",
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
chapter: "VFX",
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
sortOrder: 0,
|
||||
},
|
||||
{
|
||||
ruleSetId: "ers_1",
|
||||
scopeType: "asset",
|
||||
discipline: "Modeling",
|
||||
unitMode: "per_item",
|
||||
hoursPerUnit: 8,
|
||||
description: "Hero asset",
|
||||
sortOrder: 5,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(buildEffortRuleNestedCreateRows([
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
},
|
||||
])).toEqual([
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
sortOrder: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("builds create and sparse update payloads", () => {
|
||||
expect(buildEffortRuleSetCreateData({
|
||||
name: "VFX Standard",
|
||||
description: "Default effort rules",
|
||||
isDefault: true,
|
||||
rules: [
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
sortOrder: 0,
|
||||
},
|
||||
],
|
||||
})).toEqual({
|
||||
name: "VFX Standard",
|
||||
description: "Default effort rules",
|
||||
isDefault: true,
|
||||
rules: {
|
||||
create: [
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
sortOrder: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(buildEffortRuleSetUpdateData({
|
||||
description: null,
|
||||
isDefault: false,
|
||||
})).toEqual({
|
||||
description: null,
|
||||
isDefault: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("maps scope items and rules into engine inputs", () => {
|
||||
expect(toScopeItemInputs([
|
||||
{
|
||||
name: "Shot_001",
|
||||
scopeType: "shot",
|
||||
frameCount: 100,
|
||||
itemCount: null,
|
||||
unitMode: "per_frame",
|
||||
},
|
||||
])).toEqual([
|
||||
{
|
||||
name: "Shot_001",
|
||||
scopeType: "shot",
|
||||
frameCount: 100,
|
||||
itemCount: null,
|
||||
unitMode: "per_frame",
|
||||
},
|
||||
]);
|
||||
|
||||
expect(toEffortRuleEngineInputs([
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
chapter: null,
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
sortOrder: 0,
|
||||
},
|
||||
])).toEqual([
|
||||
{
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
chapter: null,
|
||||
unitMode: "per_frame",
|
||||
hoursPerUnit: 0.08,
|
||||
sortOrder: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("builds estimate demand line rows with the current optional chapter semantics", () => {
|
||||
expect(buildEstimateDemandLineRows({
|
||||
estimateVersionId: "ver_1",
|
||||
currency: "EUR",
|
||||
ruleSet: { id: "ers_1", name: "VFX Standard" },
|
||||
lines: [
|
||||
{
|
||||
scopeItemName: "Shot_001",
|
||||
scopeType: "shot",
|
||||
discipline: "Compositing",
|
||||
chapter: "",
|
||||
hours: 16,
|
||||
unitMode: "per_frame",
|
||||
unitCount: 200,
|
||||
hoursPerUnit: 0.08,
|
||||
},
|
||||
],
|
||||
})).toEqual([
|
||||
{
|
||||
estimateVersionId: "ver_1",
|
||||
lineType: "LABOR",
|
||||
name: "Compositing — Shot_001",
|
||||
hours: 16,
|
||||
costRateCents: 0,
|
||||
billRateCents: 0,
|
||||
currency: "EUR",
|
||||
costTotalCents: 0,
|
||||
priceTotalCents: 0,
|
||||
monthlySpread: {},
|
||||
staffingAttributes: {},
|
||||
metadata: {
|
||||
effortRule: {
|
||||
ruleSetId: "ers_1",
|
||||
ruleSetName: "VFX Standard",
|
||||
discipline: "Compositing",
|
||||
unitMode: "per_frame",
|
||||
unitCount: 200,
|
||||
hoursPerUnit: 0.08,
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user