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