1.0.0:first commit

This commit is contained in:
2026-03-26 01:23:19 +08:00
commit f8d5b11567
23562 changed files with 2853775 additions and 0 deletions

67
server/utils/accounting.js Executable file
View File

@@ -0,0 +1,67 @@
function roundCurrency(value) {
const amount = Number(value ?? 0);
if (!Number.isFinite(amount)) {
return 0;
}
return Number(amount.toFixed(2));
}
function normalizeAmount(value) {
const amount = Number(value);
if (!Number.isFinite(amount)) {
return null;
}
return roundCurrency(amount);
}
function normalizeUserKey(name) {
return String(name ?? '').replace(/\s+/g, '');
}
function createUserNameResolver(users = []) {
const exactNames = new Set();
const normalizedNameMap = new Map();
for (const user of users) {
const userName = String(user?.name ?? '').trim();
if (!userName) {
continue;
}
exactNames.add(userName);
const userKey = normalizeUserKey(userName);
if (!normalizedNameMap.has(userKey)) {
normalizedNameMap.set(userKey, new Set());
}
normalizedNameMap.get(userKey).add(userName);
}
return (inputName, fallbackName = '') => {
const rawName = String(inputName ?? '').trim();
if (!rawName) {
return fallbackName;
}
if (exactNames.has(rawName)) {
return rawName;
}
const matches = [...(normalizedNameMap.get(normalizeUserKey(rawName)) || [])];
if (matches.length === 1) {
return matches[0];
}
return rawName;
};
}
module.exports = {
createUserNameResolver,
normalizeAmount,
normalizeUserKey,
roundCurrency,
};

56
server/utils/date.js Executable file
View File

@@ -0,0 +1,56 @@
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
function parseDateInput(dateString) {
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(dateString ?? ''));
if (!match) {
return null;
}
const [, yearText, monthText, dayText] = match;
const year = Number(yearText);
const month = Number(monthText);
const day = Number(dayText);
const date = new Date(year, month - 1, day);
if (
date.getFullYear() !== year ||
date.getMonth() !== month - 1 ||
date.getDate() !== day
) {
return null;
}
return date;
}
function getWeekRange(dateString) {
const baseDate = parseDateInput(dateString);
if (!baseDate) {
return null;
}
const day = baseDate.getDay();
const diffToMonday = day === 0 ? -6 : 1 - day;
const start = new Date(baseDate);
start.setDate(baseDate.getDate() + diffToMonday);
const end = new Date(start);
end.setDate(start.getDate() + 6);
return {
startDate: formatDate(start),
endDate: formatDate(end),
};
}
module.exports = {
formatDate,
getWeekRange,
parseDateInput,
};