metis-desk/modules/companies/src/api/application/process-review-access.ts
2026-10-10 12:01:58 +02:00

85 lines
2.2 KiB
TypeScript

import type { AccessDefinition } from "../domain/access/access-definition";
import type { ProcessReviewSources } from "./process-review.builder";
type Item = { id: string; values: AccessDefinition };
type Relationship = ProcessReviewSources["relationships"][number];
function memberships(
link: Extract<AccessDefinition, { kind: "account_person" }>,
login: string,
items: readonly Item[]
): Relationship[] {
return items.flatMap((item) => {
const m = item.values;
if (m.kind !== "membership" || m.accountId !== link.accountId) {
return [];
}
const group = items.find((i) => i.id === m.groupId)?.values;
if (group?.kind !== "group") {
throw new Error("Grupo de revisión inconsistente.");
}
const ends = [link.endDate, m.endDate].filter((date): date is string => Boolean(date)).sort();
return [
{
id: item.id,
kind: "membership",
personId: link.personId,
label: `${login} · ${group.name}`,
endDate: ends[0] ?? null,
configuration: m.configuration,
},
];
});
}
export function accessReviewRelationships(items: readonly Item[]): Relationship[] {
return items.flatMap((item) => {
const v = item.values;
if (v.kind === "account_person") {
const account = items.find((i) => i.id === v.accountId)?.values;
if (account?.kind !== "account") {
throw new Error("Cuenta de revisión inconsistente.");
}
return [
{
id: item.id,
kind: "account",
personId: v.personId,
label: account.login,
endDate: v.endDate,
configuration: v.configuration,
},
...memberships(v, account.login, items),
];
}
if (v.kind === "need") {
const resource = items.find((i) => i.id === v.resourceId)?.values;
if (resource?.kind !== "resource") {
throw new Error("Recurso de revisión inconsistente.");
}
return [
{
id: item.id,
kind: "need",
personId: v.personId,
label: resource.name,
endDate: v.endDate,
configuration: null,
},
];
}
return [];
});
}