Files
edr-platform/apps/edr-freight-api/src/modules/notification-inbox/notification-recipients.service.ts
2026-08-02 21:09:37 +00:00

101 lines
3.1 KiB
TypeScript

import { NotificationRecipients } from "@edr/types";
import { Injectable, Logger } from "@nestjs/common";
import { BackofficeService } from "../backoffice/backoffice.service";
import { CompanyProfileRepository } from "../companies/company-profile.repository";
import { ExternalProfileRepository } from "../companies/external-profile.repository";
/**
* Turns a {@link NotificationRecipients} selector into a de-duplicated set of
* IAM user ids.
*
* - `userIds` → honored as-is.
* - `companyId` → all portal users linked to the company (external_profiles).
* - `companyProfileId` → resolved to its company, then to that company's users.
* - `organizationId` → all current employees of the org (backoffice staff).
* - `permissionKeys` → current employees (any org) holding any of these
* permission keys (e.g. department/role-scoped targeting).
*/
@Injectable()
export class NotificationRecipientsService {
private readonly logger = new Logger(NotificationRecipientsService.name);
constructor(
private readonly externalProfiles: ExternalProfileRepository,
private readonly companyProfiles: CompanyProfileRepository,
private readonly backoffice: BackofficeService,
) {}
async resolve(recipients: NotificationRecipients): Promise<string[]> {
const ids = new Set<string>();
for (const id of recipients.userIds ?? []) {
if (id) ids.add(id);
}
let companyId = recipients.companyId;
if (!companyId && recipients.companyProfileId) {
const profile = await this.companyProfiles.findById(
recipients.companyProfileId,
);
companyId = profile?.companyId ?? undefined;
}
if (companyId) {
const profiles = await this.externalProfiles.findByCompanyId(companyId);
for (const p of profiles) {
if (p.userId) ids.add(p.userId);
}
}
if (recipients.organizationId) {
try {
const { items } = await this.backoffice.getOrganizationEmployees(
recipients.organizationId,
{},
);
for (const employee of items as Array<{
user?: { id?: string };
userId?: string;
}>) {
const uid = employee?.user?.id ?? employee?.userId;
if (uid) ids.add(uid);
}
} catch (err) {
this.logger.warn(
`Failed to resolve org recipients for ${recipients.organizationId}: ${
(err as Error).message
}`,
);
}
}
if (recipients.allBackoffice) {
try {
for (const uid of await this.backoffice.getAllCurrentEmployeeUserIds()) {
ids.add(uid);
}
} catch (err) {
this.logger.warn(
`Failed to resolve allBackoffice recipients: ${(err as Error).message}`,
);
}
}
if (recipients.permissionKeys?.length) {
try {
for (const uid of await this.backoffice.getEmployeeUserIdsByPermission(
recipients.permissionKeys,
)) {
ids.add(uid);
}
} catch (err) {
this.logger.warn(
`Failed to resolve permissionKeys recipients: ${(err as Error).message}`,
);
}
}
return [...ids];
}
}