VirtualPR/backend/src/utils/serialize.js

383 lines
13 KiB
JavaScript

import { readOnboardedPii } from '../services/cryptoPii.js';
import { toYmd, weekdayOf } from '../services/schedule.js';
export function userLanguages(user) {
const fromArray = (user?.languages || []).map((item) => String(item || '').trim()).filter(Boolean);
if (fromArray.length) return [...new Set(fromArray)];
if (user?.language) return [String(user.language).trim()].filter(Boolean);
return [];
}
export function toUserDto(user, extras = {}) {
if (!user) return null;
const role = user.role && typeof user.role === 'object' ? user.role : null;
const languages = userLanguages(user);
return {
id: String(user._id),
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
phone: user.phone || '',
languages,
language: languages[0] || '',
specializations: Array.isArray(user.specializations) ? user.specializations : [],
availableSlots: Array.isArray(user.availableSlots) ? user.availableSlots : [],
availableStartWeekdays: Array.isArray(user.availableStartWeekdays) ? user.availableStartWeekdays : [],
maxCohorts: user.maxCohorts ?? null,
isActive: user.isActive,
lastLoginAt: user.lastLoginAt,
createdAt: user.createdAt,
updatedAt: user.updatedAt,
role: role
? {
id: String(role._id),
name: role.name,
systemKey: role.systemKey,
isSystem: role.isSystem,
}
: user.role
? { id: String(user.role) }
: null,
...extras,
};
}
export function toGoogleCalendarDto(user) {
const google = user?.google || {};
return {
connected: Boolean(google.refreshToken || google.accessToken),
email: google.email || '',
};
}
export function toAuthPayload(user) {
return toUserDto(user, { googleCalendar: toGoogleCalendarDto(user) });
}
export function toRoleDto(role, userCount = 0) {
return {
id: String(role._id),
name: role.name,
description: role.description || '',
systemKey: role.systemKey,
isSystem: role.isSystem,
permissions: (role.permissions || []).map((p) => ({
module: p.module,
actions: [...(p.actions || [])],
scope: p.scope || 'all',
})),
userCount,
createdAt: role.createdAt,
updatedAt: role.updatedAt,
};
}
export function toPatientDto(patient) {
const educator = patient.assignedEducator && typeof patient.assignedEducator === 'object'
? patient.assignedEducator
: null;
return {
id: String(patient._id),
sourcePatientId: patient.sourcePatientId,
name: patient.name,
mobile: patient.mobile || '',
age: patient.age,
gender: patient.gender || '',
lungCondition: patient.lungCondition || '',
otherHealthCondition: patient.otherHealthCondition || '',
sessionLanguage: patient.sessionLanguage || patient.language || '',
consentType: patient.consentType || '',
isNewOrOld: patient.isNewOrOld || '',
doctor: patient.doctor || {},
lastVisitDate: patient.lastVisitDate,
assignedEducator: educator
? {
id: String(educator._id),
firstName: educator.firstName,
lastName: educator.lastName,
email: educator.email,
}
: patient.assignedEducator
? { id: String(patient.assignedEducator) }
: null,
createdAt: patient.createdAt,
updatedAt: patient.updatedAt,
};
}
export function toSessionDto(session) {
if (!session) return null;
const s = typeof session.toObject === 'function' ? session.toObject() : session;
const patientId = s.patient && typeof s.patient === 'object' ? s.patient._id : s.patient;
return {
id: String(s._id),
sourceSessionId: s.sourceSessionId,
patientId: patientId ? String(patientId) : null,
visitDate: s.visitDate || null,
slot: s.slot || '',
sessionType: s.sessionType || '',
sessionReporting: s.sessionReporting || '',
zoomNotJoiningReason: s.zoomNotJoiningReason || '',
exercises: {
exercise: s.exercises?.exercise || '',
warmUp: s.exercises?.warmUp || '',
breathing: s.exercises?.breathing || '',
aerobic: s.exercises?.aerobic || '',
strengthening: s.exercises?.strengthening || '',
coolDown: s.exercises?.coolDown || '',
other: s.exercises?.other || '',
},
vitals: {
spo2Pre: s.vitals?.spo2Pre ?? null,
heartRatePre: s.vitals?.heartRatePre ?? null,
bpPre: s.vitals?.bpPre || '',
respPre: s.vitals?.respPre ?? null,
spo2Post: s.vitals?.spo2Post ?? null,
heartRatePost: s.vitals?.heartRatePost ?? null,
bpPost: s.vitals?.bpPost || '',
respPost: s.vitals?.respPost ?? null,
rpeRest: s.vitals?.rpeRest ?? null,
rpeActivity: s.vitals?.rpeActivity ?? null,
},
assessments: {
fev1: s.assessments?.fev1 ?? null,
fvc: s.assessments?.fvc ?? null,
sixMwt: s.assessments?.sixMwt ?? null,
eq5d3l: s.assessments?.eq5d3l ?? null,
sgrq: s.assessments?.sgrq ?? null,
sitToStand: s.assessments?.sitToStand ?? null,
o2Regular: s.assessments?.o2Regular ?? null,
o2WithExercise: s.assessments?.o2WithExercise ?? null,
},
employee: {
code: s.employee?.code || '',
uniqueId: s.employee?.uniqueId || '',
parentCode: s.employee?.parentCode || '',
name: s.employee?.name || '',
hq: s.employee?.hq || '',
region: s.employee?.region || '',
zone: s.employee?.zone || '',
},
sourceCreatedAt: s.sourceCreatedAt || null,
sourceModifiedAt: s.sourceModifiedAt || null,
createdAt: s.createdAt,
updatedAt: s.updatedAt,
};
}
export function toOnboardedPatientDto(item) {
if (!item) return null;
const pii = readOnboardedPii(item);
const by = item.onboardedBy && typeof item.onboardedBy === 'object'
? item.onboardedBy
: null;
return {
id: String(item._id),
sourcePatientId: item.sourcePatientId || '',
name: pii.name,
mobile: pii.mobile,
age: pii.age,
gender: pii.gender,
lungCondition: pii.lungCondition,
otherHealthCondition: pii.otherHealthCondition,
sessionLanguage: item.sessionLanguage || '',
diseaseType: item.diseaseType || '',
preferredWeekday: item.preferredWeekday ?? null,
sessionDate: item.sessionDate || null,
slot: item.slot || '',
matchingStatus: item.matchingStatus || 'unassigned',
rejectReason: item.rejectReason || '',
paymentStatus: item.paymentStatus || 'Unpaid',
hasScreenshot: Boolean(item.paymentScreenshot?.filename),
onboardedBy: by
? {
id: String(by._id),
firstName: by.firstName,
lastName: by.lastName,
email: by.email,
}
: item.onboardedBy
? { id: String(item.onboardedBy) }
: null,
assignedEducator: item.assignedEducator && typeof item.assignedEducator === 'object'
? {
id: String(item.assignedEducator._id),
firstName: item.assignedEducator.firstName,
lastName: item.assignedEducator.lastName,
}
: item.assignedEducator
? { id: String(item.assignedEducator) }
: null,
cohort: item.cohort && typeof item.cohort === 'object'
? { id: String(item.cohort._id), name: item.cohort.name, startDate: toYmd(item.cohort.startDate), slot: item.cohort.slot, language: item.cohort.language || '' }
: item.cohort
? { id: String(item.cohort) }
: null,
whatsappOptOut: Boolean(item.whatsappOptOut),
reviewStatus: item.reviewStatus || 'pending',
reviewedAt: item.reviewedAt || null,
reviewedBy: item.reviewedBy && typeof item.reviewedBy === 'object'
? {
id: String(item.reviewedBy._id),
firstName: item.reviewedBy.firstName,
lastName: item.reviewedBy.lastName,
}
: item.reviewedBy
? { id: String(item.reviewedBy) }
: null,
createdAt: item.createdAt,
updatedAt: item.updatedAt,
};
}
function userBrief(user) {
if (!user) return null;
if (typeof user === 'object') {
return {
id: String(user._id),
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
};
}
return { id: String(user) };
}
export function toCohortDto(cohort) {
if (!cohort) return null;
const patients = Array.isArray(cohort.patients) ? cohort.patients : [];
return {
id: String(cohort._id),
name: cohort.name,
startDate: toYmd(cohort.startDate),
weekday: cohort.startDate ? weekdayOf(toYmd(cohort.startDate)) : null,
slot: cohort.slot || '',
language: cohort.language || '',
scheduleId: cohort.scheduleId || '',
createdAs: cohort.createdAs || 'cohorts',
sixDayWeek: Boolean(cohort.sixDayWeek),
diseaseType: cohort.diseaseType || '',
status: cohort.status || 'active',
needsReassignment: Boolean(cohort.needsReassignment),
durationMinutes: cohort.durationMinutes || 60,
virtualPrt: userBrief(cohort.virtualPrt),
patients: patients.map((p) => (
p && typeof p === 'object'
? { id: String(p._id), name: readOnboardedPii(p).name, mobile: readOnboardedPii(p).mobile, whatsappOptOut: Boolean(p.whatsappOptOut) }
: { id: String(p) }
)),
patientCount: patients.length,
whatsapp: {
status: cohort.whatsappStatus || '',
error: cohort.whatsappError || '',
inviteUrl: cohort.whatsappInviteUrl || '',
members: (cohort.whatsappMembers || []).map((row) => ({
patientId: String(row.patient?._id || row.patient),
status: row.status || '',
error: row.error || '',
})),
},
createdAt: cohort.createdAt,
updatedAt: cohort.updatedAt,
};
}
export function toHolidayDto(holiday) {
if (!holiday) return null;
return {
id: String(holiday._id),
date: holiday.date,
name: holiday.name,
languages: holiday.languages || [],
createdAt: holiday.createdAt,
updatedAt: holiday.updatedAt,
};
}
export function toLeaveDto(leave) {
if (!leave) return null;
return {
id: String(leave._id),
user: userBrief(leave.user),
startDate: leave.startDate,
endDate: leave.endDate,
reason: leave.reason || '',
status: leave.status || 'pending',
reviewedAt: leave.reviewedAt || null,
reviewedBy: userBrief(leave.reviewedBy),
createdAt: leave.createdAt,
updatedAt: leave.updatedAt,
};
}
export function toCohortSessionDto(session) {
if (!session) return null;
const cohort = session.cohort && typeof session.cohort === 'object' ? session.cohort : null;
return {
id: String(session._id),
index: session.index,
date: session.date,
slot: session.slot || cohort?.slot || '',
status: session.status || 'scheduled',
cancelReason: session.cancelReason || '',
meetUrl: session.meetUrl || '',
htmlLink: session.htmlLink || '',
googleEventId: session.googleEventId || '',
reminderSentAt: session.reminderSentAt || null,
coverPrt: userBrief(session.coverPrt),
cohort: cohort
? {
id: String(cohort._id),
name: cohort.name,
slot: cohort.slot || '',
language: cohort.language || '',
diseaseType: cohort.diseaseType || '',
status: cohort.status || '',
virtualPrt: userBrief(cohort.virtualPrt),
}
: session.cohort
? { id: String(session.cohort) }
: null,
records: (session.records || []).map((record) => ({
patient: record.patient && typeof record.patient === 'object'
? { id: String(record.patient._id), name: readOnboardedPii(record.patient).name, mobile: readOnboardedPii(record.patient).mobile }
: { id: String(record.patient) },
attended: Boolean(record.attended),
pre: { bp: record.pre?.bp || '', spo2: record.pre?.spo2 ?? null, pulse: record.pre?.pulse ?? null },
post: { bp: record.post?.bp || '', spo2: record.post?.spo2 ?? null, pulse: record.post?.pulse ?? null },
assessment: {
fev1: record.assessment?.fev1 || '',
fvc: record.assessment?.fvc || '',
sixMwt: record.assessment?.sixMwt || '',
eq5d3l: record.assessment?.eq5d3l || '',
sgrq: record.assessment?.sgrq || '',
sitToStand: record.assessment?.sitToStand || '',
rpeRest: record.assessment?.rpeRest || '',
rpeActivity: record.assessment?.rpeActivity || '',
o2Regular: record.assessment?.o2Regular || '',
o2WithExercise: record.assessment?.o2WithExercise || '',
},
})),
createdAt: session.createdAt,
updatedAt: session.updatedAt,
};
}
export function toReassignmentDto(event) {
if (!event) return null;
return {
id: String(event._id),
reason: event.reason || '',
status: event.status || 'open',
cohort: event.cohort && typeof event.cohort === 'object'
? { id: String(event.cohort._id), name: event.cohort.name, slot: event.cohort.slot || '', language: event.cohort.language || '' }
: event.cohort
? { id: String(event.cohort) }
: null,
fromPrt: userBrief(event.fromPrt),
toPrt: userBrief(event.toPrt),
createdAt: event.createdAt,
updatedAt: event.updatedAt,
};
}