// /src/utils/professorShare.js // Mirrors gameno-api/utils/professorShare.js so the dashboard can preview payout // calculations client-side before saving a class. const toNonNegativeNumber = (value) => { const n = Number(value); if (!Number.isFinite(n) || n < 0) return 0; return n; }; const toPercentage = (value) => Math.min(100, toNonNegativeNumber(value)); const parseClockTime = (value) => { const raw = String(value || '').trim(); const match = raw.match(/^(\d{1,2}):(\d{2})$/); if (!match) return null; const hours = Number(match[1]); const minutes = Number(match[2]); if (hours > 23 || minutes > 59) return null; return hours * 60 + minutes; }; export function calculateSessionDurationHours(startTime, endTime) { const start = parseClockTime(startTime); const end = parseClockTime(endTime); if (start == null || end == null) return 0; let diffMinutes = end - start; if (diffMinutes <= 0) diffMinutes += 24 * 60; return diffMinutes / 60; } export function resolveSessionDurationHours({ hoursPerSection, startTime, endTime } = {}) { const hours = toNonNegativeNumber(hoursPerSection); if (hours > 0) return hours; return calculateSessionDurationHours(startTime, endTime); } export function calculatePercentageShare({ payoutPercentage = 0, revenue = 0, serviceFeePerPerson = 0, studentsCount = 0 } = {}) { const totalServiceFee = toNonNegativeNumber(serviceFeePerPerson) * toNonNegativeNumber(studentsCount); const netRevenue = Math.max(0, toNonNegativeNumber(revenue) - totalServiceFee); return (toPercentage(payoutPercentage) / 100) * netRevenue; } export function calculateHourlyShare({ payoutHourlyRate = 0, sessionDurationHours = 0, sessionsCount = 0 } = {}) { return toNonNegativeNumber(payoutHourlyRate) * toNonNegativeNumber(sessionDurationHours) * toNonNegativeNumber(sessionsCount); } export function calculateExtraExpenses({ extraExpensePerSession = 0, sessionsCount = 0 } = {}) { return toNonNegativeNumber(extraExpensePerSession) * toNonNegativeNumber(sessionsCount); } export function calculateProfessorPayout(params = {}) { const baseShare = params.payoutType === 'hourly' ? calculateHourlyShare(params) : calculatePercentageShare(params); const extraExpenses = calculateExtraExpenses(params); return { baseShare, extraExpenses, totalPayout: baseShare + extraExpenses }; } export function calculateNetProfit({ totalIncome = 0, professorTotalPayout = 0 } = {}) { return toNonNegativeNumber(totalIncome) - toNonNegativeNumber(professorTotalPayout); } export function calculatePendingReceivables(expectedRevenue = 0, actualReceivedRevenue = 0) { return Math.max(0, toNonNegativeNumber(expectedRevenue) - toNonNegativeNumber(actualReceivedRevenue)); } export function calculateOverpaidAmount(expectedRevenue = 0, actualReceivedRevenue = 0) { return Math.max(0, toNonNegativeNumber(actualReceivedRevenue) - toNonNegativeNumber(expectedRevenue)); }