seahaven-door-unlock-api/lambda/blf-sync/merge.ts

103 lines
2.6 KiB
TypeScript
Raw Normal View History

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