Introduces per-class payout configuration (percentage or hourly rate, plus an optional per-session expense allowance), pure calculation utilities for professor payout/net profit/receivables, and a new financial-reports API surface with per-class, per-session, and date-range/monthly reports. Also adds full CRUD for institutional expenses used in the range report, and wires up the new permissions and roles. Fixes a pre-existing ReferenceError (missing parseImportDate import) in paymentService that blocked creating payments with dated transactions.
54 lines
1.5 KiB
JavaScript
54 lines
1.5 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Resolves a reporting date range from either an explicit start/end pair or a
|
|
* `month` + `year` shorthand (both 1-indexed month). Falls back to "all time"
|
|
* when nothing is provided so the same helper can power both the lifetime and
|
|
* the date-range/monthly reports.
|
|
*/
|
|
const resolveDateRange = ({ startDate, endDate, month, year } = {}) => {
|
|
let start = startDate ? new Date(startDate) : null;
|
|
let end = endDate ? new Date(endDate) : null;
|
|
|
|
if ((!start || Number.isNaN(start.getTime())) && month != null && year != null) {
|
|
const monthIndex = Number(month) - 1;
|
|
const yearNumber = Number(year);
|
|
if (Number.isInteger(monthIndex) && Number.isInteger(yearNumber)) {
|
|
start = new Date(yearNumber, monthIndex, 1, 0, 0, 0, 0);
|
|
end = new Date(yearNumber, monthIndex + 1, 0, 23, 59, 59, 999);
|
|
}
|
|
}
|
|
|
|
if (!start || Number.isNaN(start.getTime())) {
|
|
start = new Date(0);
|
|
} else {
|
|
start.setHours(0, 0, 0, 0);
|
|
}
|
|
|
|
if (!end || Number.isNaN(end.getTime())) {
|
|
end = new Date();
|
|
} else {
|
|
end.setHours(23, 59, 59, 999);
|
|
}
|
|
|
|
if (start.getTime() > end.getTime()) {
|
|
const swap = start;
|
|
start = end;
|
|
end = swap;
|
|
}
|
|
|
|
return { start, end };
|
|
};
|
|
|
|
const isWithinRange = (value, start, end) => {
|
|
if (!value) return false;
|
|
const date = value instanceof Date ? value : new Date(value);
|
|
if (Number.isNaN(date.getTime())) return false;
|
|
return date.getTime() >= start.getTime() && date.getTime() <= end.getTime();
|
|
};
|
|
|
|
module.exports = {
|
|
resolveDateRange,
|
|
isWithinRange
|
|
};
|