Files
accounting/server/routes/users.js
2026-03-26 01:23:19 +08:00

110 lines
3.5 KiB
JavaScript
Executable File

const express = require('express');
const { getDb } = require('../db');
const { createUserNameResolver, normalizeUserKey } = require('../utils/accounting');
const router = express.Router();
function getUsers(db) {
return db.all('SELECT * FROM users ORDER BY sort_order, id');
}
function findNormalizedUserConflict(users, targetName, excludedId = null) {
const normalizedTarget = normalizeUserKey(targetName);
return users.find(
(user) => user.id !== excludedId && normalizeUserKey(user.name) === normalizedTarget
);
}
function getRelatedRecordAliases(db, userName) {
const users = getUsers(db).map((user) => ({ name: user.name }));
const resolveUserName = createUserNameResolver(users);
const aliases = db.all('SELECT DISTINCT user FROM records WHERE user IS NOT NULL AND user != ""');
return aliases
.map((row) => row.user)
.filter((name) => resolveUserName(name, '') === userName);
}
router.get('/', (req, res) => {
res.json(getUsers(getDb()));
});
router.post('/', (req, res) => {
const db = getDb();
const name = String(req.body.name ?? '').trim();
if (!name) {
return res.status(400).json({ error: '用户名为必填项' });
}
const users = getUsers(db);
const conflict = findNormalizedUserConflict(users, name);
if (conflict) {
return res.status(400).json({ error: '用户名已存在,或与现有用户名仅空格不同' });
}
const maxOrder = db.get('SELECT MAX(sort_order) AS max_order FROM users')?.max_order || 0;
const result = db.run('INSERT INTO users (name, sort_order) VALUES (?, ?)', name, maxOrder + 1);
db.run('INSERT INTO user_balance_settings (user_name, initial_balance) VALUES (?, 0)', name);
res.status(201).json(db.get('SELECT * FROM users WHERE id = ?', result.lastInsertRowid));
});
router.put('/:id', (req, res) => {
const db = getDb();
const id = Number.parseInt(req.params.id, 10);
const name = String(req.body.name ?? '').trim();
if (!name) {
return res.status(400).json({ error: '用户名为必填项' });
}
const user = db.get('SELECT * FROM users WHERE id = ?', id);
if (!user) {
return res.status(404).json({ error: '用户不存在' });
}
const users = getUsers(db);
const conflict = findNormalizedUserConflict(users, name, id);
if (conflict) {
return res.status(400).json({ error: '用户名已存在,或与现有用户名仅空格不同' });
}
const aliases = getRelatedRecordAliases(db, user.name);
db.run('UPDATE users SET name = ? WHERE id = ?', name, id);
db.run('UPDATE user_balance_settings SET user_name = ? WHERE user_name = ?', name, user.name);
aliases.forEach((alias) => {
db.run('UPDATE records SET user = ? WHERE user = ?', name, alias);
});
res.json(db.get('SELECT * FROM users WHERE id = ?', id));
});
router.delete('/:id', (req, res) => {
const db = getDb();
const id = Number.parseInt(req.params.id, 10);
const user = db.get('SELECT * FROM users WHERE id = ?', id);
if (!user) {
return res.status(404).json({ error: '用户不存在' });
}
const aliases = getRelatedRecordAliases(db, user.name);
const recordCount = aliases.reduce((total, alias) => {
const count = db.get('SELECT COUNT(*) AS count FROM records WHERE user = ?', alias)?.count || 0;
return total + count;
}, 0);
if (recordCount > 0) {
return res.status(400).json({ error: `该用户还有 ${recordCount} 条记录,无法删除` });
}
db.run('DELETE FROM users WHERE id = ?', id);
db.run('DELETE FROM user_balance_settings WHERE user_name = ?', user.name);
res.json({ message: '删除成功' });
});
module.exports = router;