leistungsbilanz-ts/src/server/controllers/distribution-board.controller.ts

223 lines
7.1 KiB
TypeScript

import type { Request, Response } from "express";
import { createDistributionBoardUpdateProjectCommand } from "../../domain/models/distribution-board-project-command.model.js";
import {
createDistributionBoardInsertProjectCommand,
createDistributionBoardStructureSnapshot,
} from "../../domain/models/distribution-board-structure-project-command.model.js";
import {
createDistributionBoardDeleteSubtreeProjectCommand,
createDistributionBoardInsertSubtreeProjectCommand,
} from "../../domain/models/distribution-board-subtree-project-command.model.js";
import { cloneDistributionBoardSubtree } from "../../domain/models/distribution-board-subtree-snapshot.model.js";
import { distributionBoardInfoFields } from "../../shared/constants/distribution-board.js";
import {
copyDistributionBoardSchema,
createDistributionBoardSchema,
deleteDistributionBoardSchema,
updateDistributionBoardSchema,
} from "../../shared/validation/project-structure.schemas.js";
import {
distributionBoardSubtreeProjectCommandStore,
projectCommandService,
} from "../composition/project-command-stores.js";
import { distributionBoardRepository } from "../composition/application-repositories.js";
import { respondWithProjectCommandError } from "./project-command.controller.js";
export async function listDistributionBoardsByProject(req: Request, res: Response) {
const { projectId } = req.params;
if (typeof projectId !== "string") {
return res.status(400).json({ error: "Invalid projectId" });
}
const result = await distributionBoardRepository.listByProject(projectId);
return res.json(result);
}
export async function createDistributionBoard(req: Request, res: Response) {
const { projectId } = req.params;
if (typeof projectId !== "string") {
return res.status(400).json({ error: "Invalid projectId" });
}
const parsed = createDistributionBoardSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ error: parsed.error.flatten() });
}
const structure = createDistributionBoardStructureSnapshot(
projectId,
parsed.data.name,
{
floorId: parsed.data.floorId,
supplyType: parsed.data.supplyType,
}
);
try {
const result = projectCommandService.executeUser({
projectId,
expectedRevision: parsed.data.expectedRevision,
description: "Verteilung anlegen",
command:
createDistributionBoardInsertProjectCommand(structure),
});
return res.status(201).json({
...result,
distributionBoard: {
...structure.distributionBoard,
simultaneityFactor: 1,
boardNumber: null,
location: null,
fedFrom: null,
remark: null,
feedingDistributionBoardId: null,
feedingCircuitId: null,
},
});
} catch (error) {
return respondWithProjectCommandError(error, res);
}
}
export async function updateDistributionBoard(
req: Request,
res: Response
) {
const { projectId, distributionBoardId } = req.params;
if (
typeof projectId !== "string" ||
typeof distributionBoardId !== "string"
) {
return res.status(400).json({ error: "Invalid distribution board id" });
}
const parsed = updateDistributionBoardSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ error: parsed.error.flatten() });
}
// Info fields are optional in the request; only submitted fields become
// part of the command and therefore of its inverse.
const infoPatch = Object.fromEntries(
distributionBoardInfoFields
.filter((field) => parsed.data[field] !== undefined)
.map((field) => [field, parsed.data[field]])
);
const feedingPatch = {
...(parsed.data.feedingDistributionBoardId === undefined
? {}
: {
feedingDistributionBoardId:
parsed.data.feedingDistributionBoardId,
}),
...(parsed.data.feedingCircuitId === undefined
? {}
: { feedingCircuitId: parsed.data.feedingCircuitId }),
};
try {
const result = projectCommandService.executeUser({
projectId,
expectedRevision: parsed.data.expectedRevision,
description: "Verteilung bearbeiten",
command: createDistributionBoardUpdateProjectCommand(
distributionBoardId,
{
floorId: parsed.data.floorId,
supplyType: parsed.data.supplyType,
simultaneityFactor: parsed.data.simultaneityFactor,
...infoPatch,
...feedingPatch,
}
),
});
const distributionBoard = (
await distributionBoardRepository.listByProject(projectId)
).find((board) => board.id === distributionBoardId);
if (!distributionBoard) {
return res.status(404).json({ error: "Distribution board not found" });
}
return res.json({ ...result, distributionBoard });
} catch (error) {
return respondWithProjectCommandError(error, res);
}
}
export async function copyDistributionBoard(
req: Request,
res: Response
) {
const ids = getDistributionBoardIds(req, res);
if (!ids) {
return;
}
const parsed = copyDistributionBoardSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ error: parsed.error.flatten() });
}
try {
const source = distributionBoardSubtreeProjectCommandStore.capture(
ids.projectId,
ids.distributionBoardId
);
const copy = cloneDistributionBoardSubtree(source, parsed.data.name);
const result = projectCommandService.executeUser({
projectId: ids.projectId,
expectedRevision: parsed.data.expectedRevision,
description: "Verteilung kopieren",
command:
createDistributionBoardInsertSubtreeProjectCommand(copy),
});
return res.status(201).json({
...result,
distributionBoard: copy.distributionBoard,
circuitList: copy.circuitList,
});
} catch (error) {
return respondWithProjectCommandError(error, res);
}
}
export async function deleteDistributionBoard(
req: Request,
res: Response
) {
const ids = getDistributionBoardIds(req, res);
if (!ids) {
return;
}
const parsed = deleteDistributionBoardSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({ error: parsed.error.flatten() });
}
try {
const snapshot =
distributionBoardSubtreeProjectCommandStore.capture(
ids.projectId,
ids.distributionBoardId
);
const result = projectCommandService.executeUser({
projectId: ids.projectId,
expectedRevision: parsed.data.expectedRevision,
description: "Verteilung löschen",
command:
createDistributionBoardDeleteSubtreeProjectCommand(snapshot),
});
return res.json({
...result,
distributionBoardId: ids.distributionBoardId,
});
} catch (error) {
return respondWithProjectCommandError(error, res);
}
}
function getDistributionBoardIds(req: Request, res: Response) {
const { projectId, distributionBoardId } = req.params;
if (
typeof projectId !== "string" ||
typeof distributionBoardId !== "string" ||
!projectId.trim() ||
!distributionBoardId.trim()
) {
res.status(400).json({ error: "Invalid distribution board id" });
return null;
}
return { projectId, distributionBoardId };
}