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 }; }