75 lines
2.9 KiB
JavaScript
75 lines
2.9 KiB
JavaScript
// /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));
|
|
}
|