77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import { Member as CwMember } from "../../generated/prisma/client";
|
|
import { User as ApiUser } from "../../../api/generated/prisma/client";
|
|
import { Translation, skipRow } from "./types";
|
|
|
|
const isValidEmail = (value: string | null): boolean => {
|
|
const normalized = value?.trim().toLowerCase();
|
|
return !!normalized && normalized.includes("@");
|
|
};
|
|
|
|
const isFullMember = (row: CwMember): boolean =>
|
|
row.memberClass === "F" && isValidEmail(row.emailAddress);
|
|
|
|
/**
|
|
* For full members, use their real email.
|
|
* For hidden members (non-F or missing valid email), generate a stable
|
|
* placeholder that satisfies the unique non-null login/email constraints.
|
|
*/
|
|
const resolveEmail = (row: CwMember): string => {
|
|
if (isFullMember(row)) {
|
|
return row.emailAddress!.trim().toLowerCase();
|
|
}
|
|
return `${row.memberId}@cw.local`;
|
|
};
|
|
|
|
export const userTranslation: Translation<CwMember, ApiUser> = {
|
|
values: [
|
|
{
|
|
from: "memberId",
|
|
to: "login",
|
|
// Use memberId@cw.local as a stable, unique login for all synced members.
|
|
// The real email goes into `email`; Microsoft OAuth overwrites `login` with
|
|
// the UPN on first login so this value is only a placeholder.
|
|
process: (value) => `${value}@cw.local`,
|
|
},
|
|
{
|
|
from: "firstName",
|
|
to: "firstName",
|
|
process: (value) => (value && value.trim() ? value.trim() : "Unknown"),
|
|
},
|
|
{
|
|
from: "lastName",
|
|
to: "lastName",
|
|
process: (value) => (value && value.trim() ? value.trim() : "Unknown"),
|
|
},
|
|
{
|
|
from: "emailAddress",
|
|
to: "email",
|
|
process: (_value, _context, row) => resolveEmail(row),
|
|
},
|
|
{ from: "memberRecId", to: "cwMemberId" },
|
|
{
|
|
from: "memberId",
|
|
to: "cwIdentifier",
|
|
process: (value) => {
|
|
const normalized = value?.trim();
|
|
return normalized ? normalized : null;
|
|
},
|
|
},
|
|
{
|
|
from: "inactiveFlag",
|
|
to: "active",
|
|
process: (value) => !value,
|
|
},
|
|
{
|
|
from: "memberClass",
|
|
to: "hidden",
|
|
process: (_value, _context, row) => !isFullMember(row),
|
|
},
|
|
{
|
|
from: "dateHire",
|
|
to: "createdAt",
|
|
process: (value, _context, row) => value ?? row.lastUpdatedUtc,
|
|
},
|
|
{ from: "lastUpdatedUtc", to: "updatedAt" },
|
|
],
|
|
};
|