feat: add all route modules (auth, records, stats, recurring, categories, export, search)
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
const express = require('express');
|
||||
const db = require('../config/database');
|
||||
const { authenticate } = require('../middleware/auth');
|
||||
const { asyncHandler, AppError } = require('../middleware/errorHandler');
|
||||
const { isValidMonth, VALID_STATS_PERIODS, VALID_STATS_TYPES } = require('../utils/validators');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// 获取月度统计
|
||||
router.get('/', authenticate, asyncHandler(async (req, res) => {
|
||||
const { month } = req.query;
|
||||
|
||||
if (!month) {
|
||||
throw new AppError('请指定月份', 400, 'MISSING_MONTH');
|
||||
}
|
||||
|
||||
const stmt = db.prepare(`
|
||||
SELECT
|
||||
SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as totalIncome,
|
||||
SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as totalExpense
|
||||
FROM records
|
||||
WHERE user_id = ? AND date LIKE ?
|
||||
`);
|
||||
|
||||
const result = stmt.get(req.userId, `${month}%`);
|
||||
|
||||
res.json({
|
||||
income: result.totalIncome || 0,
|
||||
expense: result.totalExpense || 0,
|
||||
balance: (result.totalIncome || 0) - (result.totalExpense || 0),
|
||||
});
|
||||
}));
|
||||
|
||||
// 收支趋势统计
|
||||
router.get('/trend', authenticate, asyncHandler(async (req, res) => {
|
||||
const { period = 'month', month } = req.query;
|
||||
|
||||
if (!VALID_STATS_PERIODS.includes(period)) {
|
||||
throw new AppError('统计周期错误', 400, 'INVALID_PERIOD');
|
||||
}
|
||||
|
||||
if (month && !isValidMonth(month)) {
|
||||
throw new AppError('月份格式错误', 400, 'INVALID_MONTH');
|
||||
}
|
||||
|
||||
let dateGroup;
|
||||
if (period === 'year') {
|
||||
dateGroup = "strftime('%Y', date)";
|
||||
} else if (period === 'week') {
|
||||
dateGroup = "strftime('%Y-%W', date)";
|
||||
} else {
|
||||
dateGroup = "strftime('%Y-%m', date)";
|
||||
}
|
||||
|
||||
let query = `
|
||||
SELECT
|
||||
${dateGroup} as period,
|
||||
SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as income,
|
||||
SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as expense
|
||||
FROM records
|
||||
WHERE user_id = ?
|
||||
`;
|
||||
const params = [req.userId];
|
||||
|
||||
if (month) {
|
||||
query += ' AND date LIKE ?';
|
||||
params.push(`${month}%`);
|
||||
}
|
||||
|
||||
query += `
|
||||
GROUP BY ${dateGroup}
|
||||
ORDER BY period DESC
|
||||
LIMIT 12
|
||||
`;
|
||||
|
||||
const stmt = db.prepare(query);
|
||||
const result = stmt.all(...params);
|
||||
res.json(result.reverse());
|
||||
}));
|
||||
|
||||
// 分类统计
|
||||
router.get('/category', authenticate, asyncHandler(async (req, res) => {
|
||||
const { month, type = 'all' } = req.query;
|
||||
|
||||
if (!VALID_STATS_TYPES.includes(type)) {
|
||||
throw new AppError('统计类型错误', 400, 'INVALID_TYPE');
|
||||
}
|
||||
|
||||
if (month && !isValidMonth(month)) {
|
||||
throw new AppError('月份格式错误', 400, 'INVALID_MONTH');
|
||||
}
|
||||
|
||||
let query = `
|
||||
SELECT
|
||||
category,
|
||||
SUM(amount) as total,
|
||||
type
|
||||
FROM records
|
||||
WHERE user_id = ?
|
||||
`;
|
||||
const params = [req.userId];
|
||||
|
||||
if (month) {
|
||||
query += ' AND date LIKE ?';
|
||||
params.push(`${month}%`);
|
||||
}
|
||||
|
||||
if (type !== 'all') {
|
||||
query += ' AND type = ?';
|
||||
params.push(type);
|
||||
}
|
||||
|
||||
query += `
|
||||
GROUP BY category, type
|
||||
ORDER BY total DESC
|
||||
`;
|
||||
|
||||
const stmt = db.prepare(query);
|
||||
const result = stmt.all(...params);
|
||||
res.json(result);
|
||||
}));
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user