mirror of
https://github.com/Sea-Haven-Industries/seahaven-door-unlock-api.git
synced 2026-09-30 08:13:13 +00:00
Some checks failed
Deploy / deploy (push) Has been cancelled
* feat(3cx): sync office department BLFs via XAPI Keep unlock and lockdown keys in the templates and write colleague plus shared-parking BLFs per extension so phones skip their own line. * fix(3cx): preserve parking BLF IDs and fail the job on PATCH errors
102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
import {
|
|
type BlfEntry,
|
|
parseBlfs,
|
|
serializeBlfs,
|
|
} from "./blf-xml";
|
|
import {
|
|
type SlotContract,
|
|
isManagedSlot,
|
|
isReservedSlot,
|
|
isSharedParkingSlot,
|
|
managedSlotCount,
|
|
} from "./slot-contract";
|
|
|
|
export interface Colleague {
|
|
id: number;
|
|
number: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
}
|
|
|
|
export interface MergeResult {
|
|
xml: string;
|
|
changed: boolean;
|
|
overflow: number;
|
|
placed: number;
|
|
}
|
|
|
|
export function sortColleagues(colleagues: Colleague[]): Colleague[] {
|
|
return [...colleagues].sort((a, b) => a.number.localeCompare(b.number, "en", { numeric: true }));
|
|
}
|
|
|
|
export function mergeDepartmentBlfs(input: {
|
|
currentXml: string | undefined | null;
|
|
selfExtension: string;
|
|
colleagues: Colleague[];
|
|
contract: SlotContract;
|
|
}): MergeResult {
|
|
const current = parseBlfs(input.currentXml);
|
|
const others = sortColleagues(
|
|
input.colleagues.filter((c) => c.number !== input.selfExtension)
|
|
);
|
|
const slotCount = managedSlotCount(input.contract);
|
|
const placedColleagues = others.slice(0, slotCount);
|
|
const overflow = Math.max(0, others.length - slotCount);
|
|
|
|
const preserved = current.filter((entry) => {
|
|
if (entry.blfNo === input.contract.ownLine) {
|
|
return false;
|
|
}
|
|
if (isReservedSlot(input.contract, entry.blfNo)) {
|
|
return false;
|
|
}
|
|
if (isSharedParkingSlot(input.contract, entry.blfNo)) {
|
|
return false;
|
|
}
|
|
if (isManagedSlot(input.contract, entry.blfNo)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
const existingOwnLine = current.find((entry) => entry.blfNo === input.contract.ownLine);
|
|
const ownLine: BlfEntry = {
|
|
id: existingOwnLine?.blfType === "Line" ? existingOwnLine.id : "-1",
|
|
blfNo: input.contract.ownLine,
|
|
blfType: "Line",
|
|
blfTypeId: "6",
|
|
value: "",
|
|
};
|
|
|
|
const parking: BlfEntry[] = input.contract.sharedParking.map((slot) => {
|
|
const existing = current.find(
|
|
(entry) =>
|
|
entry.blfNo === slot.blfNo &&
|
|
entry.blfType === "SharedParking" &&
|
|
entry.value === slot.value
|
|
);
|
|
return {
|
|
id: existing?.id ?? "-1",
|
|
blfNo: slot.blfNo,
|
|
blfType: "SharedParking",
|
|
blfTypeId: existing?.blfTypeId ?? "3",
|
|
value: slot.value,
|
|
};
|
|
});
|
|
|
|
const managed: BlfEntry[] = placedColleagues.map((colleague, index) => ({
|
|
id: String(colleague.id),
|
|
blfNo: input.contract.managedStart + index,
|
|
blfType: "BLF",
|
|
blfTypeId: "0",
|
|
value: colleague.number,
|
|
}));
|
|
|
|
const nextXml = serializeBlfs([...preserved, ownLine, ...parking, ...managed]);
|
|
return {
|
|
xml: nextXml,
|
|
changed: serializeBlfs(current) !== nextXml,
|
|
overflow,
|
|
placed: placedColleagues.length,
|
|
};
|
|
}
|