Show logical feeder loads in project and circuit views

This commit is contained in:
Julian Appel 2026-09-27 22:37:04 +02:00
parent dfeb0e3cb6
commit 042a050876
12 changed files with 319 additions and 11 deletions

View file

@ -267,6 +267,15 @@ describe("cable sizing defaults from the circuit", () => {
sortOrder: 1,
isReserve: rows.length === 0,
circuitTotalPower: rows.reduce((sum, row) => sum + row.power, 0),
circuitApparentPower: rows.reduce(
(sum, row) => sum + row.power / (row.cosPhi ?? 1),
0
),
circuitCosPhi: rows.length
? rows.reduce((sum, row) => sum + row.power, 0) /
rows.reduce((sum, row) => sum + row.power / (row.cosPhi ?? 1), 0)
: 1,
downstreamBoardLoads: [],
deviceRows: rows.map((row, index) => ({
id: `row-${index}`,
sortOrder: index,
@ -288,6 +297,19 @@ describe("cable sizing defaults from the circuit", () => {
assert.equal(deriveCircuitCosPhi(circuit([])), 1);
});
it("uses the projected cos φ including downstream boards", () => {
const feeder = circuit([{ power: 1, cosPhi: 1 }]);
feeder.circuitCosPhi = 0.67;
feeder.downstreamBoardLoads = [{
distributionBoardId: "uv-2",
name: "UV 2",
activePowerKw: 3,
apparentPowerKva: 5,
cosPhi: 0.6,
}];
assert.equal(deriveCircuitCosPhi(feeder), 0.67);
});
it("derives the phase from the group category or three-phase rows", () => {
assert.equal(deriveCircuitPhase(circuit([{ power: 1, phaseType: "single_phase" }]), "single_phase"), 1);
assert.equal(deriveCircuitPhase(circuit([{ power: 1, phaseType: "three_phase" }]), "single_phase"), 3);

View file

@ -47,7 +47,10 @@ function makeCircuit(
sortOrder,
isReserve: deviceRows.length === 0,
circuitTotalPower: deviceRows.reduce((total, row) => total + row.rowTotalPower, 0),
circuitApparentPower: deviceRows.reduce((total, row) => total + row.rowTotalPower, 0),
circuitCosPhi: 1,
deviceRows,
downstreamBoardLoads: [],
};
}
@ -176,6 +179,44 @@ describe("circuit grid projection", () => {
);
});
it("renders linked downstream boards as separate read-only rows", () => {
const feeder = {
...reserveCircuit,
isReserve: false,
circuitTotalPower: 4,
circuitApparentPower: 5,
circuitCosPhi: 0.8,
downstreamBoardLoads: [{
distributionBoardId: "board-child",
name: "Unterverteilung",
boardNumber: "UV-02",
activePowerKw: 4,
apparentPowerKva: 5,
cosPhi: 0.8,
}],
};
const rows = buildVisibleGridRowsWithStructure(
[{ ...sections[0], circuits: [feeder] }],
{ headerComponents: [], footerComponents: [] }
);
assert.deepEqual(rows.map((row) => row.rowType), [
"section",
"circuitSummary",
"downstreamBoardLoad",
"placeholder",
]);
const loadRow = rows[2];
assert.equal(
loadRow.cells.find((cell) => cell.cellKey === "displayName")?.value,
"Unterverteilung UV-02"
);
assert.equal(
loadRow.cells.find((cell) => cell.cellKey === "rowTotalPower")?.value,
4
);
assert.equal(loadRow.cells.every((cell) => !cell.editable), true);
});
it("shows circuit protection once on each visible circuit row", () => {
const protectedSections = sections.map((section) => ({
...section,