import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { CircuitWriteService } from "../src/domain/services/circuit-write.service.js"; describe("circuit write service rules", () => { it("rejects duplicate equipment identifiers in same circuit list", async () => { const service = new CircuitWriteService({ circuitListRepository: { async findById() { return { id: "list1", projectId: "p1" } as never; }, } as never, circuitSectionRepository: { async findById() { return { id: "sec1", circuitListId: "list1" } as never; }, } as never, circuitRepository: { async existsByEquipmentIdentifier() { return true; }, } as never, }); await assert.rejects( () => service.createCircuit("p1", "list1", { sectionId: "sec1", equipmentIdentifier: "-2F1", sortOrder: 10, }), /Duplicate equipmentIdentifier/ ); }); it("rejects section and list mismatch", async () => { const service = new CircuitWriteService({ circuitListRepository: { async findById() { return { id: "list1", projectId: "p1" } as never; }, } as never, circuitSectionRepository: { async findById() { return { id: "sec1", circuitListId: "other" } as never; }, } as never, circuitRepository: { async existsByEquipmentIdentifier() { return false; }, } as never, }); await assert.rejects( () => service.createCircuit("p1", "list1", { sectionId: "sec1", equipmentIdentifier: "-2F1", sortOrder: 10, }), /Section does not belong to circuit list/ ); }); it("deleting last device row keeps circuit and sets reserve", async () => { let reserveFlag = false; const service = new CircuitWriteService({ deviceRowRepository: { async findById() { return { id: "r1", circuitId: "c1" } as never; }, async delete() { return; }, async countByCircuit() { return 0; }, } as never, circuitRepository: { async findById() { return { id: "c1", sectionId: "s1", circuitListId: "l1", equipmentIdentifier: "-2F1", sortOrder: 10, isReserve: 0, } as never; }, async update(_id: string, payload: { isReserve: boolean }) { reserveFlag = payload.isReserve; }, } as never, }); await service.deleteDeviceRow("r1"); assert.equal(reserveFlag, true); }); it("creating device row in reserve circuit clears reserve status", async () => { let reserveFlag = true; const service = new CircuitWriteService({ circuitRepository: { async findById() { return { id: "c1", sectionId: "s1", circuitListId: "l1", equipmentIdentifier: "-2F1", sortOrder: 10, isReserve: 1, } as never; }, async update(_id: string, payload: { isReserve: boolean }) { reserveFlag = payload.isReserve; }, } as never, deviceRowRepository: { async countByCircuit() { return 0; }, async create() { return "row1"; }, async findById() { return { id: "row1" } as never; }, } as never, circuitListRepository: {} as never, circuitSectionRepository: {} as never, projectDeviceRepository: { async findById() { return { id: "pd1" } as never; }, } as never, }); await service.createDeviceRow("c1", { name: "Load", displayName: "Load", quantity: 1, powerPerUnit: 1, simultaneityFactor: 1, }); assert.equal(reserveFlag, false); }); it("renumber affects only circuits in selected section and keeps row order untouched", async () => { const updatedIds: string[] = []; const service = new CircuitWriteService({ circuitSectionRepository: { async findById() { return { id: "s1", circuitListId: "l1", prefix: "-2F" } as never; }, } as never, circuitRepository: { async listBySection() { return [ { id: "c1", sectionId: "s1", equipmentIdentifier: "-2F7", sortOrder: 10, isReserve: 0 }, { id: "c2", sectionId: "s1", equipmentIdentifier: "-2F9", sortOrder: 20, isReserve: 1 }, ] as never[]; }, async listByCircuitList() { return [{ id: "x1", sectionId: "s2", equipmentIdentifier: "-3F1" }] as never[]; }, async update(circuitId: string) { updatedIds.push(circuitId); }, } as never, }); const result = await service.renumberSection("s1"); assert.deepEqual(updatedIds, ["c1", "c2"]); assert.equal(result.length, 2); }); it("moving a device row to another circuit preserves row and toggles reserve flags", async () => { const updatedReserve: Array<{ id: string; isReserve: boolean }> = []; const movedCalls: Array<{ rowId: string; targetCircuitId: string; sortOrder: number }> = []; const service = new CircuitWriteService({ deviceRowRepository: { async findById() { return { id: "r1", circuitId: "c1" } as never; }, async countByCircuit(circuitId: string) { if (circuitId === "c2") { return 2; } if (circuitId === "c1") { return 0; } return 0; }, async moveToCircuit(rowId: string, targetCircuitId: string, sortOrder: number) { movedCalls.push({ rowId, targetCircuitId, sortOrder }); }, } as never, circuitRepository: { async findById(circuitId: string) { if (circuitId === "c1") { return { id: "c1", sectionId: "s1", circuitListId: "l1", equipmentIdentifier: "-1F1", sortOrder: 10, isReserve: 0, } as never; } return { id: "c2", sectionId: "s1", circuitListId: "l1", equipmentIdentifier: "-1F2", sortOrder: 20, isReserve: 1, } as never; }, async update(id: string, payload: { isReserve: boolean }) { updatedReserve.push({ id, isReserve: payload.isReserve }); }, } as never, }); await service.moveDeviceRow("r1", { targetCircuitId: "c2" }); assert.deepEqual(movedCalls, [{ rowId: "r1", targetCircuitId: "c2", sortOrder: 30 }]); assert.deepEqual(updatedReserve, [ { id: "c1", isReserve: true }, { id: "c2", isReserve: false }, ]); }); it("moving a device row to placeholder creates a new circuit in target section", async () => { let createdCircuitPayload: { sectionId: string; equipmentIdentifier: string; isReserve?: boolean } | null = null; const service = new CircuitWriteService({ deviceRowRepository: { async findById() { return { id: "r1", circuitId: "c1" } as never; }, async countByCircuit(circuitId: string) { if (circuitId === "c-new") { return 0; } return 1; }, async moveToCircuit() { return; }, } as never, circuitRepository: { async findById(circuitId: string) { if (circuitId === "c1") { return { id: "c1", sectionId: "s1", circuitListId: "l1", equipmentIdentifier: "-1F1", sortOrder: 10, isReserve: 0, } as never; } if (circuitId === "c-new") { return { id: "c-new", sectionId: "s2", circuitListId: "l1", equipmentIdentifier: "-2F8", sortOrder: 50, isReserve: 0, } as never; } return null as never; }, async listBySection() { return [{ sortOrder: 40 }] as never[]; }, async create(payload: { sectionId: string; equipmentIdentifier: string; isReserve?: boolean }) { createdCircuitPayload = payload; return "c-new"; }, async update() { return; }, } as never, circuitSectionRepository: { async findById() { return { id: "s2", circuitListId: "l1", prefix: "-2F" } as never; }, } as never, numberingService: { async getNextIdentifier() { return "-2F8"; }, } as never, }); await service.moveDeviceRow("r1", { targetSectionId: "s2", createNewCircuit: true }); assert.equal(createdCircuitPayload?.sectionId, "s2"); assert.equal(createdCircuitPayload?.equipmentIdentifier, "-2F8"); assert.equal(createdCircuitPayload?.isReserve, false); }); it("reorders circuits inside one section without renumbering identifiers", async () => { const updates: Array<{ id: string; sortOrder: number; equipmentIdentifier: string }> = []; const service = new CircuitWriteService({ circuitSectionRepository: { async findById() { return { id: "s1", circuitListId: "l1" } as never; }, } as never, circuitRepository: { async listBySection() { return [ { id: "c1", sectionId: "s1", equipmentIdentifier: "-2F7", sortOrder: 10, isReserve: 0 }, { id: "c2", sectionId: "s1", equipmentIdentifier: "-2F9", sortOrder: 20, isReserve: 0 }, { id: "c3", sectionId: "s1", equipmentIdentifier: "-2F5", sortOrder: 30, isReserve: 1 }, ] as never[]; }, async update(id: string, payload: { sortOrder: number; equipmentIdentifier: string }) { updates.push({ id, sortOrder: payload.sortOrder, equipmentIdentifier: payload.equipmentIdentifier }); }, } as never, }); await service.reorderCircuitsInSection("s1", { orderedCircuitIds: ["c3", "c1", "c2"] }); assert.deepEqual(updates, [ { id: "c3", sortOrder: 10, equipmentIdentifier: "-2F5" }, { id: "c1", sortOrder: 20, equipmentIdentifier: "-2F7" }, { id: "c2", sortOrder: 30, equipmentIdentifier: "-2F9" }, ]); }); });