统一api返回
This commit is contained in:
parent
5faf92593f
commit
ed4ff56082
|
|
@ -2,7 +2,7 @@ const { Sequelize } = require('sequelize');
|
|||
const mysql = require('mysql2/promise');
|
||||
|
||||
// 环境配置
|
||||
const NODE_ENV = process.env.NODE_ENV || 'development';
|
||||
const NODE_ENV = process.env.NODE_ENV || 'local';
|
||||
|
||||
// 数据库配置
|
||||
const dbConfig = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { Apartment, Tenant } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const { logOperation } = require('../utils/logger');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 格式化时间(考虑时区,转换为北京时间)
|
||||
const formatDate = (date) => {
|
||||
|
|
@ -51,14 +52,14 @@ const getAllApartments = async (req, res) => {
|
|||
const formattedApartments = rows.map(formatApartmentData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
data: formattedApartments,
|
||||
response.success(res, '获取成功', {
|
||||
list: formattedApartments,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
response.serverError(res, '获取公寓列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -70,16 +71,12 @@ const getApartmentById = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!apartment) {
|
||||
return res.status(404).json({ error: '公寓不存在' });
|
||||
return response.notFound(res, '公寓不存在');
|
||||
}
|
||||
const formattedApartment = formatApartmentData(apartment);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedApartment,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedApartment);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取公寓详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -90,9 +87,10 @@ const createApartment = async (req, res) => {
|
|||
|
||||
// 检查租户资源使用情况(仅记录日志,不阻止创建)
|
||||
const tenant = await Tenant.findByPk(req.user.tenantId);
|
||||
let currentApartmentCount = 0;
|
||||
if (tenant) {
|
||||
// 获取当前公寓数量
|
||||
const currentApartmentCount = await Apartment.count({
|
||||
currentApartmentCount = await Apartment.count({
|
||||
where: { tenantId: req.user.tenantId, isDeleted: 0 }
|
||||
});
|
||||
|
||||
|
|
@ -122,14 +120,12 @@ const createApartment = async (req, res) => {
|
|||
createBy: req.user.id,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: apartment,
|
||||
message: '创建成功',
|
||||
response.created(res, '创建成功', {
|
||||
apartment,
|
||||
warning: tenant && currentApartmentCount >= tenant.maxApartments ? `当前已超出套餐限制(${tenant.maxApartments}栋),续费时将收取超额费用` : null
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建公寓失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -142,7 +138,7 @@ const updateApartment = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!apartment) {
|
||||
return res.status(404).json({ error: '公寓不存在' });
|
||||
return response.notFound(res, '公寓不存在');
|
||||
}
|
||||
await apartment.update({
|
||||
name,
|
||||
|
|
@ -150,13 +146,9 @@ const updateApartment = async (req, res) => {
|
|||
description,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: apartment,
|
||||
message: '更新成功'
|
||||
});
|
||||
response.success(res, '更新成功', apartment);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '更新公寓失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -168,18 +160,15 @@ const deleteApartment = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!apartment) {
|
||||
return res.status(404).json({ error: '公寓不存在' });
|
||||
return response.notFound(res, '公寓不存在');
|
||||
}
|
||||
await apartment.update({
|
||||
isDeleted: 1,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '公寓删除成功'
|
||||
});
|
||||
response.success(res, '公寓删除成功');
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '删除公寓失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -208,13 +197,9 @@ const listApartments = async (req, res) => {
|
|||
const formattedApartments = apartments.map(formatApartmentData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedApartments,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedApartments);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取公寓列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -225,4 +210,4 @@ module.exports = {
|
|||
createApartment,
|
||||
updateApartment,
|
||||
deleteApartment
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const Setting = require('../models/Setting');
|
|||
const { SubscriptionPlan } = require('../models');
|
||||
const { generateToken } = require('../middleware/auth');
|
||||
const { logLogin, getClientIp } = require('../utils/logger');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 登录
|
||||
exports.login = async (req, res) => {
|
||||
|
|
@ -28,10 +29,7 @@ exports.login = async (req, res) => {
|
|||
status: 'fail',
|
||||
message: '用户名和密码不能为空'
|
||||
});
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '用户名和密码不能为空'
|
||||
});
|
||||
return response.badRequest(res, '用户名和密码不能为空');
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
|
|
@ -58,10 +56,7 @@ exports.login = async (req, res) => {
|
|||
status: 'fail',
|
||||
message: '用户名或密码错误'
|
||||
});
|
||||
return res.status(401).json({
|
||||
code: 401,
|
||||
message: '用户名或密码错误'
|
||||
});
|
||||
return response.unauthorized(res, '用户名或密码错误');
|
||||
}
|
||||
|
||||
// 检查用户状态
|
||||
|
|
@ -75,10 +70,7 @@ exports.login = async (req, res) => {
|
|||
status: 'fail',
|
||||
message: '账号已被禁用'
|
||||
});
|
||||
return res.status(401).json({
|
||||
code: 401,
|
||||
message: '账号已被禁用'
|
||||
});
|
||||
return response.unauthorized(res, '账号已被禁用');
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
|
|
@ -93,10 +85,7 @@ exports.login = async (req, res) => {
|
|||
status: 'fail',
|
||||
message: '用户名或密码错误'
|
||||
});
|
||||
return res.status(401).json({
|
||||
code: 401,
|
||||
message: '用户名或密码错误'
|
||||
});
|
||||
return response.unauthorized(res, '用户名或密码错误');
|
||||
}
|
||||
|
||||
// 检查租户计费状态(仅非系统管理员需要检查)
|
||||
|
|
@ -112,15 +101,11 @@ exports.login = async (req, res) => {
|
|||
status: 'fail',
|
||||
message: '账户已过期,请续费'
|
||||
});
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '您的账户已过期,请前往续费',
|
||||
data: {
|
||||
expired: true,
|
||||
billingStatus: billingStatus,
|
||||
trialEndDate: user.tenant.trialEndDate,
|
||||
paidEndDate: user.tenant.paidEndDate
|
||||
}
|
||||
return response.forbidden(res, '您的账户已过期,请前往续费', {
|
||||
expired: true,
|
||||
billingStatus: billingStatus,
|
||||
trialEndDate: user.tenant.trialEndDate,
|
||||
paidEndDate: user.tenant.paidEndDate
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -172,22 +157,18 @@ exports.login = async (req, res) => {
|
|||
});
|
||||
|
||||
// 返回用户信息和 Token
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '登录成功',
|
||||
data: {
|
||||
token,
|
||||
userInfo: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
role: user.role,
|
||||
tenantId: user.tenantId,
|
||||
userType: user.userType
|
||||
},
|
||||
tenant: user.tenant,
|
||||
menus
|
||||
}
|
||||
response.success(res, '登录成功', {
|
||||
token,
|
||||
userInfo: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
role: user.role,
|
||||
tenantId: user.tenantId,
|
||||
userType: user.userType
|
||||
},
|
||||
tenant: user.tenant,
|
||||
menus
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('登录错误:', error);
|
||||
|
|
@ -199,11 +180,7 @@ exports.login = async (req, res) => {
|
|||
status: 'fail',
|
||||
message: error.message
|
||||
});
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '登录失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '登录失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -222,16 +199,10 @@ exports.logout = async (req, res) => {
|
|||
message: '登出成功'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '登出成功'
|
||||
});
|
||||
response.success(res, '登出成功');
|
||||
} catch (error) {
|
||||
console.error('登出错误:', error);
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '登出成功'
|
||||
});
|
||||
response.success(res, '登出成功');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -264,18 +235,10 @@ function buildMenuTree(menus, parentId = null) {
|
|||
exports.getCurrentUser = async (req, res) => {
|
||||
try {
|
||||
// req.user 由 authMiddleware 附加
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: req.user
|
||||
});
|
||||
response.success(res, '获取成功', req.user);
|
||||
} catch (error) {
|
||||
console.error('获取用户信息错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取用户信息失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取用户信息失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -287,35 +250,23 @@ exports.changePassword = async (req, res) => {
|
|||
|
||||
// 参数验证
|
||||
if (!oldPassword || !newPassword) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '原密码和新密码不能为空'
|
||||
});
|
||||
return response.badRequest(res, '原密码和新密码不能为空');
|
||||
}
|
||||
|
||||
if (newPassword.length < 6) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '新密码长度不能少于6位'
|
||||
});
|
||||
return response.badRequest(res, '新密码长度不能少于6位');
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
const user = await User.findByPk(userId);
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
// 验证原密码
|
||||
const isPasswordValid = await bcrypt.compare(oldPassword, user.password);
|
||||
if (!isPasswordValid) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '原密码错误'
|
||||
});
|
||||
return response.badRequest(res, '原密码错误');
|
||||
}
|
||||
|
||||
// 加密新密码
|
||||
|
|
@ -324,17 +275,10 @@ exports.changePassword = async (req, res) => {
|
|||
// 更新密码
|
||||
await user.update({ password: hashedPassword });
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '密码修改成功'
|
||||
});
|
||||
response.success(res, '密码修改成功');
|
||||
} catch (error) {
|
||||
console.error('修改密码错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '修改密码失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '修改密码失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -351,19 +295,13 @@ exports.registerTenant = async (req, res) => {
|
|||
try {
|
||||
// 参数验证
|
||||
if (!contactName || !contactPhone || !contactEmail || !adminUsername || !adminPassword) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '请填写所有必填项'
|
||||
});
|
||||
return response.badRequest(res, '请填写所有必填项');
|
||||
}
|
||||
|
||||
// 检查管理员账号是否已存在
|
||||
const existingUser = await User.findOne({ where: { username: adminUsername } });
|
||||
if (existingUser) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '管理员账号已存在'
|
||||
});
|
||||
return response.badRequest(res, '管理员账号已存在');
|
||||
}
|
||||
|
||||
// 查询默认套餐
|
||||
|
|
@ -375,10 +313,7 @@ exports.registerTenant = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!defaultPlan) {
|
||||
return res.status(500).json({
|
||||
code: 500,
|
||||
message: '系统未配置默认套餐,请联系管理员'
|
||||
});
|
||||
return response.serverError(res, '系统未配置默认套餐,请联系管理员');
|
||||
}
|
||||
|
||||
// 生成租户编码:时间戳 + 随机数
|
||||
|
|
@ -489,21 +424,13 @@ exports.registerTenant = async (req, res) => {
|
|||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '注册成功,欢迎试用',
|
||||
data: {
|
||||
tenantId: tenant.id,
|
||||
code: tenant.code,
|
||||
status: tenant.status
|
||||
}
|
||||
response.success(res, '注册成功,欢迎试用', {
|
||||
tenantId: tenant.id,
|
||||
code: tenant.code,
|
||||
status: tenant.status
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('租户注册失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '注册失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '注册失败', error);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const { Bill, MeterReading, Room, Renter, Rental, BillPayment } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 生成账单编号
|
||||
const generateBillNo = () => {
|
||||
|
|
@ -141,16 +142,15 @@ const getAllBills = async (req, res) => {
|
|||
const formattedBills = rows.map(formatBillData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBills,
|
||||
response.success(res, '获取成功', {
|
||||
list: formattedBills,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取账单列表失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取账单列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -170,13 +170,10 @@ const getBillsList = async (req, res) => {
|
|||
const formattedBills = rows.map(formatBillData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBills
|
||||
});
|
||||
response.success(res, '获取成功', formattedBills);
|
||||
} catch (error) {
|
||||
console.error('获取账单列表失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取账单列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -211,19 +208,15 @@ const getBillById = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!bill) {
|
||||
return res.status(404).json({ code: 404, error: '账单不存在' });
|
||||
return response.notFound(res, '账单不存在');
|
||||
}
|
||||
|
||||
const formattedBill = formatBillData(bill);
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBill,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedBill);
|
||||
} catch (error) {
|
||||
console.error('获取账单详情失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取账单详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -261,14 +254,10 @@ const createBill = async (req, res) => {
|
|||
});
|
||||
|
||||
const formattedBill = formatBillData(bill);
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: formattedBill,
|
||||
message: '创建成功'
|
||||
});
|
||||
response.created(res, '创建成功', formattedBill);
|
||||
} catch (error) {
|
||||
console.error('创建账单失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建账单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -293,7 +282,7 @@ const updateBill = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!bill) {
|
||||
return res.status(404).json({ code: 404, error: '账单不存在' });
|
||||
return response.notFound(res, '账单不存在');
|
||||
}
|
||||
|
||||
await bill.update({
|
||||
|
|
@ -309,14 +298,10 @@ const updateBill = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formatBillData(bill),
|
||||
message: '更新成功'
|
||||
});
|
||||
response.success(res, '更新成功', formatBillData(bill));
|
||||
} catch (error) {
|
||||
console.error('更新账单失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '更新账单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -329,7 +314,7 @@ const deleteBill = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!bill) {
|
||||
return res.status(404).json({ code: 404, error: '账单不存在' });
|
||||
return response.notFound(res, '账单不存在');
|
||||
}
|
||||
|
||||
await bill.update({
|
||||
|
|
@ -337,13 +322,10 @@ const deleteBill = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '账单删除成功'
|
||||
});
|
||||
response.success(res, '账单删除成功');
|
||||
} catch (error) {
|
||||
console.error('删除账单失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '删除账单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -358,7 +340,7 @@ const receivePayment = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!bill) {
|
||||
return res.status(404).json({ code: 404, error: '账单不存在' });
|
||||
return response.notFound(res, '账单不存在');
|
||||
}
|
||||
|
||||
const newReceivedAmount = parseFloat(bill.receivedAmount) + parseFloat(amount);
|
||||
|
|
@ -378,14 +360,10 @@ const receivePayment = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formatBillData(bill),
|
||||
message: '收款成功'
|
||||
});
|
||||
response.success(res, '收款成功', formatBillData(bill));
|
||||
} catch (error) {
|
||||
console.error('账单收款失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '账单收款失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -443,22 +421,19 @@ const getBillStatistics = async (req, res) => {
|
|||
const totalReceivable = await Bill.sum('receivableAmount', { where });
|
||||
const totalReceived = await Bill.sum('receivedAmount', { where });
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: {
|
||||
summary: {
|
||||
totalReceivable: totalReceivable || 0,
|
||||
totalReceived: totalReceived || 0,
|
||||
totalUnreceived: (totalReceivable || 0) - (totalReceived || 0)
|
||||
},
|
||||
income: incomeStats,
|
||||
expense: expenseStats,
|
||||
status: statusStats
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
summary: {
|
||||
totalReceivable: totalReceivable || 0,
|
||||
totalReceived: totalReceived || 0,
|
||||
totalUnreceived: (totalReceivable || 0) - (totalReceived || 0)
|
||||
},
|
||||
income: incomeStats,
|
||||
expense: expenseStats,
|
||||
status: statusStats
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取账单统计失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取账单统计失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const { BillPayment, Bill } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取账单的所有支付流水
|
||||
const getPaymentsByBillId = async (req, res) => {
|
||||
|
|
@ -16,14 +17,10 @@ const getPaymentsByBillId = async (req, res) => {
|
|||
order: [['paymentTime', 'DESC']]
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: payments,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', payments);
|
||||
} catch (error) {
|
||||
console.error('获取支付流水失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取支付流水失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -41,15 +38,15 @@ const createPayment = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!bill) {
|
||||
return res.status(404).json({ code: 404, error: '账单不存在' });
|
||||
return response.notFound(res, '账单不存在');
|
||||
}
|
||||
|
||||
if (bill.status === 'paid') {
|
||||
return res.status(400).json({ code: 400, error: '该账单已收清,无法继续收款' });
|
||||
return response.badRequest(res, '该账单已收清,无法继续收款');
|
||||
}
|
||||
|
||||
if (bill.status === 'cancelled') {
|
||||
return res.status(400).json({ code: 400, error: '该账单已取消,无法收款' });
|
||||
return response.badRequest(res, '该账单已取消,无法收款');
|
||||
}
|
||||
|
||||
// 计算剩余应收金额
|
||||
|
|
@ -60,14 +57,11 @@ const createPayment = async (req, res) => {
|
|||
// 验证支付金额
|
||||
const paymentAmount = parseFloat(amount);
|
||||
if (paymentAmount <= 0) {
|
||||
return res.status(400).json({ code: 400, error: '支付金额必须大于0' });
|
||||
return response.badRequest(res, '支付金额必须大于0');
|
||||
}
|
||||
|
||||
if (paymentAmount > remainingAmount) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
error: `支付金额不能超过剩余应收金额 ¥${remainingAmount.toFixed(2)}`
|
||||
});
|
||||
return response.badRequest(res, `支付金额不能超过剩余应收金额 ¥${remainingAmount.toFixed(2)}`);
|
||||
}
|
||||
|
||||
// 创建支付流水
|
||||
|
|
@ -99,21 +93,17 @@ const createPayment = async (req, res) => {
|
|||
updateBy: createBy
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: {
|
||||
payment,
|
||||
bill: {
|
||||
id: bill.id,
|
||||
receivedAmount: newReceivedAmount,
|
||||
status: newStatus
|
||||
}
|
||||
},
|
||||
message: '收款成功'
|
||||
response.created(res, '收款成功', {
|
||||
payment,
|
||||
bill: {
|
||||
id: bill.id,
|
||||
receivedAmount: newReceivedAmount,
|
||||
status: newStatus
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建支付流水失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建支付流水失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -129,7 +119,7 @@ const deletePayment = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!payment) {
|
||||
return res.status(404).json({ code: 404, error: '支付流水不存在' });
|
||||
return response.notFound(res, '支付流水不存在');
|
||||
}
|
||||
|
||||
// 查找关联账单
|
||||
|
|
@ -138,7 +128,7 @@ const deletePayment = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!bill) {
|
||||
return res.status(404).json({ code: 404, error: '关联账单不存在' });
|
||||
return response.notFound(res, '关联账单不存在');
|
||||
}
|
||||
|
||||
// 软删除支付流水
|
||||
|
|
@ -170,20 +160,16 @@ const deletePayment = async (req, res) => {
|
|||
updateBy
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: {
|
||||
bill: {
|
||||
id: bill.id,
|
||||
receivedAmount: newReceivedAmount,
|
||||
status: newStatus
|
||||
}
|
||||
},
|
||||
message: '支付流水已删除,账单状态已更新'
|
||||
response.success(res, '支付流水已删除,账单状态已更新', {
|
||||
bill: {
|
||||
id: bill.id,
|
||||
receivedAmount: newReceivedAmount,
|
||||
status: newStatus
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('删除支付流水失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '删除支付流水失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -210,14 +196,10 @@ const getPaymentStatistics = async (req, res) => {
|
|||
group: ['paymentMethod']
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: payments,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', payments);
|
||||
} catch (error) {
|
||||
console.error('获取支付统计失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取支付统计失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { SubscriptionPlan, PricingConfig, Order, Payment, Tenant, User, Apartment, Room, PaymentSetting } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const billingService = require('../services/billingService');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取所有套餐列表
|
||||
const getAllPlans = async (req, res) => {
|
||||
|
|
@ -10,17 +11,9 @@ const getAllPlans = async (req, res) => {
|
|||
order: [['sort', 'ASC']]
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '获取套餐列表成功',
|
||||
data: plans
|
||||
});
|
||||
response.success(res, '获取套餐列表成功', plans);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取套餐列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取套餐列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -31,10 +24,7 @@ const createPlan = async (req, res) => {
|
|||
|
||||
// 验证必填字段
|
||||
if (!name) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐名称不能为空'
|
||||
});
|
||||
return response.badRequest(res, '套餐名称不能为空');
|
||||
}
|
||||
|
||||
// 检查是否是第一个套餐
|
||||
|
|
@ -52,17 +42,9 @@ const createPlan = async (req, res) => {
|
|||
isDefault
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
code: 200,
|
||||
message: '套餐创建成功',
|
||||
data: plan
|
||||
});
|
||||
response.created(res, '套餐创建成功', plan);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建套餐失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '创建套餐失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -78,10 +60,7 @@ const updatePlan = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!plan) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐不存在'
|
||||
});
|
||||
return response.badRequest(res, '套餐不存在');
|
||||
}
|
||||
|
||||
// 更新套餐信息
|
||||
|
|
@ -96,17 +75,9 @@ const updatePlan = async (req, res) => {
|
|||
sort: sort !== undefined ? sort : plan.sort
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '套餐更新成功',
|
||||
data: plan
|
||||
});
|
||||
response.success(res, '套餐更新成功', plan);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新套餐失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新套餐失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -121,33 +92,20 @@ const deletePlan = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!plan) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐不存在'
|
||||
});
|
||||
return response.badRequest(res, '套餐不存在');
|
||||
}
|
||||
|
||||
// 不能删除默认套餐
|
||||
if (plan.isDefault) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '不能删除默认套餐'
|
||||
});
|
||||
return response.badRequest(res, '不能删除默认套餐');
|
||||
}
|
||||
|
||||
// 软删除
|
||||
await plan.update({ isDeleted: 1 });
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '套餐删除成功'
|
||||
});
|
||||
response.success(res, '套餐删除成功');
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '删除套餐失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '删除套餐失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -162,10 +120,7 @@ const setDefaultPlan = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!plan) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐不存在'
|
||||
});
|
||||
return response.badRequest(res, '套餐不存在');
|
||||
}
|
||||
|
||||
// 将其他套餐 isDefault 设为 false
|
||||
|
|
@ -177,17 +132,9 @@ const setDefaultPlan = async (req, res) => {
|
|||
// 将指定套餐 isDefault 设为 true
|
||||
await plan.update({ isDefault: true });
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '设置默认套餐成功',
|
||||
data: plan
|
||||
});
|
||||
response.success(res, '设置默认套餐成功', plan);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '设置默认套餐失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '设置默认套餐失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -202,29 +149,17 @@ const getPricingConfig = async (req, res) => {
|
|||
|
||||
// 如果没有则返回默认配置
|
||||
if (!config) {
|
||||
return res.status(200).json({
|
||||
code: 200,
|
||||
message: '获取价格配置成功',
|
||||
data: {
|
||||
overageApartmentPrice: 10.00,
|
||||
overageRoomPrice: 2.00,
|
||||
overageUserPrice: 5.00,
|
||||
currency: 'CNY'
|
||||
}
|
||||
return response.success(res, '获取价格配置成功', {
|
||||
overageApartmentPrice: 10.00,
|
||||
overageRoomPrice: 2.00,
|
||||
overageUserPrice: 5.00,
|
||||
currency: 'CNY'
|
||||
});
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '获取价格配置成功',
|
||||
data: config
|
||||
});
|
||||
response.success(res, '获取价格配置成功', config);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取价格配置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取价格配置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -247,17 +182,9 @@ const updatePricingConfig = async (req, res) => {
|
|||
isActive: true
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '价格配置更新成功',
|
||||
data: config
|
||||
});
|
||||
response.success(res, '价格配置更新成功', config);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新价格配置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新价格配置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -267,10 +194,7 @@ const initDefaultPlans = async (req, res) => {
|
|||
// 检查是否已有套餐
|
||||
const existingCount = await SubscriptionPlan.count({ where: { isDeleted: 0 } });
|
||||
if (existingCount > 0) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐数据已存在,无需初始化'
|
||||
});
|
||||
return response.badRequest(res, '套餐数据已存在,无需初始化');
|
||||
}
|
||||
|
||||
// 默认套餐数据
|
||||
|
|
@ -320,17 +244,9 @@ const initDefaultPlans = async (req, res) => {
|
|||
// 批量创建套餐
|
||||
const plans = await SubscriptionPlan.bulkCreate(defaultPlans);
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '默认套餐初始化成功',
|
||||
data: plans
|
||||
});
|
||||
response.success(res, '默认套餐初始化成功', plans);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '初始化默认套餐失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '初始化默认套餐失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -343,10 +259,7 @@ const initDefaultPricing = async (req, res) => {
|
|||
});
|
||||
|
||||
if (existingConfig) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '价格配置已存在,无需初始化'
|
||||
});
|
||||
return response.badRequest(res, '价格配置已存在,无需初始化');
|
||||
}
|
||||
|
||||
// 创建默认价格配置
|
||||
|
|
@ -357,17 +270,9 @@ const initDefaultPricing = async (req, res) => {
|
|||
isActive: true
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '默认价格配置初始化成功',
|
||||
data: config
|
||||
});
|
||||
response.success(res, '默认价格配置初始化成功', config);
|
||||
} catch (error) {
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '初始化默认价格配置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '初始化默认价格配置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -412,23 +317,15 @@ const getOrders = async (req, res) => {
|
|||
]
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
},
|
||||
message: '获取订单列表成功'
|
||||
response.success(res, '获取订单列表成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取订单列表失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取订单列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取订单列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -440,17 +337,11 @@ const calculatePrice = async (req, res) => {
|
|||
|
||||
// 验证必填字段
|
||||
if (!planId || !months) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐ID和购买月数不能为空'
|
||||
});
|
||||
return response.badRequest(res, '套餐ID和购买月数不能为空');
|
||||
}
|
||||
|
||||
if (months < 1 || months > 36) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '购买月数必须在1-36之间'
|
||||
});
|
||||
return response.badRequest(res, '购买月数必须在1-36之间');
|
||||
}
|
||||
|
||||
// 获取套餐信息
|
||||
|
|
@ -459,27 +350,16 @@ const calculatePrice = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!plan) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐不存在'
|
||||
});
|
||||
return response.badRequest(res, '套餐不存在');
|
||||
}
|
||||
|
||||
// 计算订单金额(含超额费用)
|
||||
const amountInfo = await billingService.calculateRenewalAmount(tenantId, planId, months);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '计算成功',
|
||||
data: amountInfo
|
||||
});
|
||||
response.success(res, '计算成功', amountInfo);
|
||||
} catch (error) {
|
||||
console.error('计算价格失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '计算价格失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '计算价格失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -491,17 +371,11 @@ const createOrder = async (req, res) => {
|
|||
|
||||
// 验证必填字段
|
||||
if (!planId || !months) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐ID和购买月数不能为空'
|
||||
});
|
||||
return response.badRequest(res, '套餐ID和购买月数不能为空');
|
||||
}
|
||||
|
||||
if (months < 1 || months > 36) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '购买月数必须在1-36之间'
|
||||
});
|
||||
return response.badRequest(res, '购买月数必须在1-36之间');
|
||||
}
|
||||
|
||||
// 获取套餐信息
|
||||
|
|
@ -510,10 +384,7 @@ const createOrder = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!plan) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '套餐不存在'
|
||||
});
|
||||
return response.badRequest(res, '套餐不存在');
|
||||
}
|
||||
|
||||
// 计算订单金额
|
||||
|
|
@ -558,21 +429,13 @@ const createOrder = async (req, res) => {
|
|||
]
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
code: 200,
|
||||
message: '订单创建成功',
|
||||
data: {
|
||||
order: createdOrder.toJSON(),
|
||||
details: amountInfo.details
|
||||
}
|
||||
response.created(res, '订单创建成功', {
|
||||
order: createdOrder.toJSON(),
|
||||
details: amountInfo.details
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建订单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建订单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '创建订单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -605,32 +468,18 @@ const getOrderDetail = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!order) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '订单不存在'
|
||||
});
|
||||
return response.notFound(res, '订单不存在');
|
||||
}
|
||||
|
||||
// 权限检查:普通租户只能查看自己的订单
|
||||
if (!isSystemAdmin && order.tenantId !== currentTenantId) {
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '无权查看此订单'
|
||||
});
|
||||
return response.forbidden(res, '无权查看此订单');
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: order,
|
||||
message: '获取订单详情成功'
|
||||
});
|
||||
response.success(res, '获取订单详情成功', order);
|
||||
} catch (error) {
|
||||
console.error('获取订单详情失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取订单详情失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取订单详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -646,41 +495,25 @@ const cancelOrder = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!order) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '订单不存在'
|
||||
});
|
||||
return response.notFound(res, '订单不存在');
|
||||
}
|
||||
|
||||
// 权限检查:普通租户只能取消自己的订单
|
||||
if (!isSystemAdmin && order.tenantId !== currentTenantId) {
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '无权取消此订单'
|
||||
});
|
||||
return response.forbidden(res, '无权取消此订单');
|
||||
}
|
||||
|
||||
// 只能取消待支付的订单
|
||||
if (order.status !== 'pending') {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '只能取消待支付的订单'
|
||||
});
|
||||
return response.badRequest(res, '只能取消待支付的订单');
|
||||
}
|
||||
|
||||
await order.update({ status: 'cancelled' });
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '订单取消成功'
|
||||
});
|
||||
response.success(res, '订单取消成功');
|
||||
} catch (error) {
|
||||
console.error('取消订单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '取消订单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '取消订单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -690,21 +523,14 @@ const payOrder = async (req, res) => {
|
|||
const { id: orderId } = req.params;
|
||||
const { paymentMethod = 'other', amount, transactionId: customTransactionId, remark } = req.body || {};
|
||||
const isSystemAdmin = req.user.userType === 'super_admin';
|
||||
const currentTenantId = req.tenantId;
|
||||
|
||||
if (!orderId) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '订单ID不能为空'
|
||||
});
|
||||
return response.badRequest(res, '订单ID不能为空');
|
||||
}
|
||||
|
||||
// 只有管理员可以确认支付
|
||||
if (!isSystemAdmin) {
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '无权操作,请联系管理员'
|
||||
});
|
||||
return response.forbidden(res, '无权操作,请联系管理员');
|
||||
}
|
||||
|
||||
// 查询订单
|
||||
|
|
@ -713,27 +539,18 @@ const payOrder = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!order) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '订单不存在'
|
||||
});
|
||||
return response.notFound(res, '订单不存在');
|
||||
}
|
||||
|
||||
// 验证订单状态
|
||||
if (order.status !== 'pending') {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '订单状态异常,无法支付'
|
||||
});
|
||||
return response.badRequest(res, '订单状态异常,无法支付');
|
||||
}
|
||||
|
||||
// 验证金额
|
||||
const paymentAmount = parseFloat(amount) || order.actualAmount;
|
||||
if (paymentAmount <= 0) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '支付金额必须大于0'
|
||||
});
|
||||
return response.badRequest(res, '支付金额必须大于0');
|
||||
}
|
||||
|
||||
// 生成或使用自定义交易流水号
|
||||
|
|
@ -762,26 +579,18 @@ const payOrder = async (req, res) => {
|
|||
// 使用订单的months字段和planId更新资源配置
|
||||
const paymentResult = await billingService.processPaymentSuccess(order.tenantId, order.months, order.planId);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '支付成功',
|
||||
data: {
|
||||
payment,
|
||||
order: {
|
||||
...order.toJSON(),
|
||||
status: 'paid',
|
||||
paidTime: paidTime
|
||||
},
|
||||
tenant: paymentResult
|
||||
}
|
||||
response.success(res, '支付成功', {
|
||||
payment,
|
||||
order: {
|
||||
...order.toJSON(),
|
||||
status: 'paid',
|
||||
paidTime: paidTime
|
||||
},
|
||||
tenant: paymentResult
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('支付订单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '支付订单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '支付订单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -822,23 +631,15 @@ const getPayments = async (req, res) => {
|
|||
]
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
},
|
||||
message: '获取支付记录成功'
|
||||
response.success(res, '获取支付记录成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取支付记录失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取支付记录失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取支付记录失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -859,10 +660,7 @@ const getBillingInfo = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!tenant) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '租户不存在'
|
||||
});
|
||||
return response.notFound(res, '租户不存在');
|
||||
}
|
||||
|
||||
// 获取当前使用量
|
||||
|
|
@ -872,37 +670,29 @@ const getBillingInfo = async (req, res) => {
|
|||
User.count({ where: { tenantId, isDeleted: 0 } })
|
||||
]);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: {
|
||||
tenant: {
|
||||
id: tenant.id,
|
||||
name: tenant.name,
|
||||
code: tenant.code,
|
||||
billingStatus: tenant.billingStatus,
|
||||
trialStartDate: tenant.trialStartDate,
|
||||
trialEndDate: tenant.trialEndDate,
|
||||
paidStartDate: tenant.paidStartDate,
|
||||
paidEndDate: tenant.paidEndDate,
|
||||
currentPeriodStart: tenant.currentPeriodStart,
|
||||
currentPeriodEnd: tenant.currentPeriodEnd
|
||||
},
|
||||
plan: tenant.subscriptionPlan,
|
||||
usage: {
|
||||
apartments: apartmentCount,
|
||||
rooms: roomCount,
|
||||
users: userCount
|
||||
}
|
||||
response.success(res, '获取计费信息成功', {
|
||||
tenant: {
|
||||
id: tenant.id,
|
||||
name: tenant.name,
|
||||
code: tenant.code,
|
||||
billingStatus: tenant.billingStatus,
|
||||
trialStartDate: tenant.trialStartDate,
|
||||
trialEndDate: tenant.trialEndDate,
|
||||
paidStartDate: tenant.paidStartDate,
|
||||
paidEndDate: tenant.paidEndDate,
|
||||
currentPeriodStart: tenant.currentPeriodStart,
|
||||
currentPeriodEnd: tenant.currentPeriodEnd
|
||||
},
|
||||
message: '获取计费信息成功'
|
||||
plan: tenant.subscriptionPlan,
|
||||
usage: {
|
||||
apartments: apartmentCount,
|
||||
rooms: roomCount,
|
||||
users: userCount
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取计费信息失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取计费信息失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取计费信息失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -913,18 +703,10 @@ const getUsageStats = async (req, res) => {
|
|||
|
||||
const usageStats = await billingService.calculateOverage(tenantId);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: usageStats,
|
||||
message: '获取资源使用情况成功'
|
||||
});
|
||||
response.success(res, '获取资源使用情况成功', usageStats);
|
||||
} catch (error) {
|
||||
console.error('获取资源使用情况失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取资源使用情况失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取资源使用情况失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -934,10 +716,7 @@ const getBillingStats = async (req, res) => {
|
|||
const isSystemAdmin = req.user.userType === 'super_admin';
|
||||
|
||||
if (!isSystemAdmin) {
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '无权访问此接口'
|
||||
});
|
||||
return response.forbidden(res, '无权访问此接口');
|
||||
}
|
||||
|
||||
// 各计费状态租户数量
|
||||
|
|
@ -1009,28 +788,20 @@ const getBillingStats = async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: {
|
||||
billingStatusStats: billingStatusStats.reduce((acc, item) => {
|
||||
acc[item.billingStatus] = parseInt(item.get('count'));
|
||||
return acc;
|
||||
}, {}),
|
||||
totalRevenue: totalRevenue || 0,
|
||||
monthRevenue: monthRevenue || 0,
|
||||
upcomingExpiredCount,
|
||||
expiredCount,
|
||||
pendingOrdersCount
|
||||
},
|
||||
message: '获取计费统计成功'
|
||||
response.success(res, '获取计费统计成功', {
|
||||
billingStatusStats: billingStatusStats.reduce((acc, item) => {
|
||||
acc[item.billingStatus] = parseInt(item.get('count'));
|
||||
return acc;
|
||||
}, {}),
|
||||
totalRevenue: totalRevenue || 0,
|
||||
monthRevenue: monthRevenue || 0,
|
||||
upcomingExpiredCount,
|
||||
expiredCount,
|
||||
pendingOrdersCount
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取计费统计失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取计费统计失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取计费统计失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1044,25 +815,13 @@ const getPaymentSettings = async (req, res) => {
|
|||
|
||||
// 如果没有记录,返回空对象
|
||||
if (!settings) {
|
||||
return res.json({
|
||||
code: 200,
|
||||
message: '获取支付设置成功',
|
||||
data: {}
|
||||
});
|
||||
return response.success(res, '获取支付设置成功', {});
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取支付设置成功',
|
||||
data: settings
|
||||
});
|
||||
response.success(res, '获取支付设置成功', settings);
|
||||
} catch (error) {
|
||||
console.error('获取支付设置失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取支付设置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取支付设置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1073,10 +832,7 @@ const updatePaymentSettings = async (req, res) => {
|
|||
|
||||
// 只有超级管理员可以修改支付设置
|
||||
if (!isSystemAdmin) {
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '无权操作,请联系管理员'
|
||||
});
|
||||
return response.forbidden(res, '无权操作,请联系管理员');
|
||||
}
|
||||
|
||||
const {
|
||||
|
|
@ -1124,18 +880,10 @@ const updatePaymentSettings = async (req, res) => {
|
|||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '支付设置更新成功',
|
||||
data: settings
|
||||
});
|
||||
response.success(res, '支付设置更新成功', settings);
|
||||
} catch (error) {
|
||||
console.error('更新支付设置失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新支付设置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新支付设置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,214 +0,0 @@
|
|||
const { ElectricityBill, Room } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
|
||||
// 格式化时间(考虑时区,转换为北京时间)
|
||||
const formatDate = (date) => {
|
||||
if (!date) return null;
|
||||
// 确保date是Date对象
|
||||
const dateObj = date instanceof Date ? date : new Date(date);
|
||||
// 创建一个新的Date对象,加上8小时的时区偏移
|
||||
const beijingDate = new Date(dateObj.getTime() + 8 * 60 * 60 * 1000);
|
||||
return beijingDate.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
// 格式化电费数据
|
||||
const formatElectricityBillData = (bill) => {
|
||||
const formattedBill = {
|
||||
...bill.toJSON(),
|
||||
startDate: formatDate(bill.startDate),
|
||||
endDate: formatDate(bill.endDate),
|
||||
createTime: formatDate(bill.createTime),
|
||||
updateTime: formatDate(bill.updateTime)
|
||||
};
|
||||
|
||||
// 格式化关联数据
|
||||
if (formattedBill.Room) {
|
||||
formattedBill.Room = {
|
||||
...formattedBill.Room,
|
||||
createTime: formatDate(formattedBill.Room.createTime),
|
||||
updateTime: formatDate(formattedBill.Room.updateTime)
|
||||
};
|
||||
}
|
||||
|
||||
return formattedBill;
|
||||
};
|
||||
|
||||
// 获取所有电费记录(支持搜索和分页)
|
||||
const getAllElectricityBills = async (req, res) => {
|
||||
try {
|
||||
const { roomId, status, startDate, endDate, page = 1, pageSize = 10 } = req.query;
|
||||
|
||||
// 构建查询条件
|
||||
const where = { isDeleted: 0 };
|
||||
if (roomId) {
|
||||
where.roomId = roomId;
|
||||
}
|
||||
if (status) {
|
||||
where.status = status;
|
||||
}
|
||||
if (startDate) {
|
||||
where.startDate = { [Op.gte]: new Date(startDate) };
|
||||
}
|
||||
if (endDate) {
|
||||
where.endDate = { [Op.lte]: new Date(endDate) };
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
const offset = (page - 1) * pageSize;
|
||||
|
||||
// 查询电费数据
|
||||
const { count, rows } = await ElectricityBill.findAndCountAll({
|
||||
where,
|
||||
include: [
|
||||
{
|
||||
model: Room,
|
||||
where: { isDeleted: 0 }
|
||||
}
|
||||
],
|
||||
limit: parseInt(pageSize),
|
||||
offset: parseInt(offset)
|
||||
});
|
||||
|
||||
// 格式化数据
|
||||
const formattedBills = rows.map(formatElectricityBillData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
data: formattedBills,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 获取单个电费记录
|
||||
const getElectricityBillById = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const bill = await ElectricityBill.findOne({
|
||||
where: { id, isDeleted: 0 },
|
||||
include: [
|
||||
{
|
||||
model: Room,
|
||||
where: { isDeleted: 0 }
|
||||
}
|
||||
]
|
||||
});
|
||||
if (!bill) {
|
||||
return res.status(404).json({ error: '电费记录不存在' });
|
||||
}
|
||||
const formattedBill = formatElectricityBillData(bill);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBill,
|
||||
message: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 创建电费记录
|
||||
const createElectricityBill = async (req, res) => {
|
||||
try {
|
||||
const { roomId, startDate, endDate, startReading, endReading, unitPrice } = req.body;
|
||||
|
||||
// 计算用电量和费用
|
||||
const usage = parseFloat(endReading) - parseFloat(startReading);
|
||||
const amount = usage * parseFloat(unitPrice);
|
||||
|
||||
const bill = await ElectricityBill.create({
|
||||
roomId,
|
||||
startDate,
|
||||
endDate,
|
||||
startReading,
|
||||
endReading,
|
||||
usage,
|
||||
unitPrice,
|
||||
amount
|
||||
});
|
||||
|
||||
const formattedBill = formatElectricityBillData(bill);
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: formattedBill,
|
||||
message: '创建成功'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 更新电费记录
|
||||
const updateElectricityBill = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { startDate, endDate, startReading, endReading, unitPrice, status } = req.body;
|
||||
|
||||
const bill = await ElectricityBill.findOne({
|
||||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!bill) {
|
||||
return res.status(404).json({ error: '电费记录不存在' });
|
||||
}
|
||||
|
||||
// 计算用电量和费用
|
||||
let usage = bill.usage;
|
||||
let amount = bill.amount;
|
||||
if (startReading && endReading && unitPrice) {
|
||||
usage = parseFloat(endReading) - parseFloat(startReading);
|
||||
amount = usage * parseFloat(unitPrice);
|
||||
}
|
||||
|
||||
await bill.update({
|
||||
startDate,
|
||||
endDate,
|
||||
startReading,
|
||||
endReading,
|
||||
usage,
|
||||
unitPrice,
|
||||
amount,
|
||||
status
|
||||
});
|
||||
|
||||
const formattedBill = formatElectricityBillData(bill);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBill,
|
||||
message: '更新成功'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 删除电费记录(软删除)
|
||||
const deleteElectricityBill = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const bill = await ElectricityBill.findOne({
|
||||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!bill) {
|
||||
return res.status(404).json({ error: '电费记录不存在' });
|
||||
}
|
||||
await bill.update({ isDeleted: 1 });
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '电费记录删除成功'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAllElectricityBills,
|
||||
getElectricityBillById,
|
||||
createElectricityBill,
|
||||
updateElectricityBill,
|
||||
deleteElectricityBill
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
const { Op } = require('sequelize');
|
||||
const OperationLog = require('../models/OperationLog');
|
||||
const LoginLog = require('../models/LoginLog');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取操作日志列表
|
||||
exports.getOperationLogs = async (req, res) => {
|
||||
|
|
@ -35,23 +36,15 @@ exports.getOperationLogs = async (req, res) => {
|
|||
limit: parseInt(pageSize)
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取操作日志错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取操作日志失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取操作日志失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -85,23 +78,15 @@ exports.getLoginLogs = async (req, res) => {
|
|||
limit: parseInt(pageSize)
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取登录日志错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取登录日志失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取登录日志失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -119,17 +104,10 @@ exports.clearOperationLogs = async (req, res) => {
|
|||
|
||||
await OperationLog.destroy({ where });
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '清空成功'
|
||||
});
|
||||
response.success(res, '清空成功');
|
||||
} catch (error) {
|
||||
console.error('清空操作日志错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '清空操作日志失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '清空操作日志失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -147,16 +125,9 @@ exports.clearLoginLogs = async (req, res) => {
|
|||
|
||||
await LoginLog.destroy({ where });
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '清空成功'
|
||||
});
|
||||
response.success(res, '清空成功');
|
||||
} catch (error) {
|
||||
console.error('清空登录日志错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '清空登录日志失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '清空登录日志失败', error);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const { Op } = require('sequelize');
|
|||
const Menu = require('../models/Menu');
|
||||
const RoleMenu = require('../models/RoleMenu');
|
||||
const { logOperation } = require('../utils/logger');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取菜单树
|
||||
exports.getMenuTree = async (req, res) => {
|
||||
|
|
@ -29,18 +30,10 @@ exports.getMenuTree = async (req, res) => {
|
|||
|
||||
const menuTree = buildTree(menus);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: menuTree
|
||||
});
|
||||
response.success(res, '获取成功', menuTree);
|
||||
} catch (error) {
|
||||
console.error('获取菜单树失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取菜单树失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取菜单树失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -67,23 +60,15 @@ exports.getMenuList = async (req, res) => {
|
|||
limit: parseInt(pageSize)
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取菜单列表失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取菜单列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取菜单列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -97,24 +82,13 @@ exports.getMenuById = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!menu) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '菜单不存在'
|
||||
});
|
||||
return response.notFound(res, '菜单不存在');
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: menu
|
||||
});
|
||||
response.success(res, '获取成功', menu);
|
||||
} catch (error) {
|
||||
console.error('获取菜单详情失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取菜单详情失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取菜单详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -124,17 +98,11 @@ exports.createMenu = async (req, res) => {
|
|||
const { parentId, name, code, type, path, component, icon, sort, visible, status } = req.body;
|
||||
|
||||
if (!name || !code || !type) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '菜单名称、编码和类型不能为空'
|
||||
});
|
||||
return response.badRequest(res, '菜单名称、编码和类型不能为空');
|
||||
}
|
||||
|
||||
if (type === 'menu' && !path) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '菜单类型必须填写路由路径'
|
||||
});
|
||||
return response.badRequest(res, '菜单类型必须填写路由路径');
|
||||
}
|
||||
|
||||
const existingMenu = await Menu.findOne({
|
||||
|
|
@ -142,10 +110,7 @@ exports.createMenu = async (req, res) => {
|
|||
});
|
||||
|
||||
if (existingMenu) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '菜单编码已存在'
|
||||
});
|
||||
return response.badRequest(res, '菜单编码已存在');
|
||||
}
|
||||
|
||||
if (parentId) {
|
||||
|
|
@ -153,10 +118,7 @@ exports.createMenu = async (req, res) => {
|
|||
where: { isDeleted: false }
|
||||
});
|
||||
if (!parentMenu) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '父菜单不存在'
|
||||
});
|
||||
return response.badRequest(res, '父菜单不存在');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,18 +149,10 @@ exports.createMenu = async (req, res) => {
|
|||
status: 'success'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '创建成功',
|
||||
data: menu
|
||||
});
|
||||
response.success(res, '创建成功', menu);
|
||||
} catch (error) {
|
||||
console.error('创建菜单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建菜单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '创建菜单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -213,10 +167,7 @@ exports.updateMenu = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!menu) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '菜单不存在'
|
||||
});
|
||||
return response.notFound(res, '菜单不存在');
|
||||
}
|
||||
|
||||
if (code && code !== menu.code) {
|
||||
|
|
@ -225,29 +176,20 @@ exports.updateMenu = async (req, res) => {
|
|||
});
|
||||
|
||||
if (existingMenu) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '菜单编码已存在'
|
||||
});
|
||||
return response.badRequest(res, '菜单编码已存在');
|
||||
}
|
||||
}
|
||||
|
||||
if (parentId) {
|
||||
if (parseInt(parentId) === parseInt(id)) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '不能将菜单设置为自己的子菜单'
|
||||
});
|
||||
return response.badRequest(res, '不能将菜单设置为自己的子菜单');
|
||||
}
|
||||
|
||||
const parentMenu = await Menu.findByPk(parentId, {
|
||||
where: { isDeleted: false }
|
||||
});
|
||||
if (!parentMenu) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '父菜单不存在'
|
||||
});
|
||||
return response.badRequest(res, '父菜单不存在');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,18 +221,10 @@ exports.updateMenu = async (req, res) => {
|
|||
status: 'success'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '更新成功',
|
||||
data: menu
|
||||
});
|
||||
response.success(res, '更新成功', menu);
|
||||
} catch (error) {
|
||||
console.error('更新菜单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新菜单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新菜单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -304,10 +238,7 @@ exports.deleteMenu = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!menu) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '菜单不存在'
|
||||
});
|
||||
return response.notFound(res, '菜单不存在');
|
||||
}
|
||||
|
||||
const children = await Menu.findAll({
|
||||
|
|
@ -315,10 +246,7 @@ exports.deleteMenu = async (req, res) => {
|
|||
});
|
||||
|
||||
if (children.length > 0) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '该菜单下有子菜单,无法删除'
|
||||
});
|
||||
return response.badRequest(res, '该菜单下有子菜单,无法删除');
|
||||
}
|
||||
|
||||
await menu.update({
|
||||
|
|
@ -342,17 +270,10 @@ exports.deleteMenu = async (req, res) => {
|
|||
status: 'success'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '删除成功'
|
||||
});
|
||||
response.success(res, '删除成功');
|
||||
} catch (error) {
|
||||
console.error('删除菜单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '删除菜单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '删除菜单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -369,10 +290,7 @@ exports.getRoleMenus = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!role) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '角色不存在'
|
||||
});
|
||||
return response.notFound(res, '角色不存在');
|
||||
}
|
||||
|
||||
// 获取角色的菜单权限
|
||||
|
|
@ -388,18 +306,10 @@ exports.getRoleMenus = async (req, res) => {
|
|||
|
||||
const menus = roleData ? roleData.menus : [];
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: menus
|
||||
});
|
||||
response.success(res, '获取成功', menus);
|
||||
} catch (error) {
|
||||
console.error('获取角色菜单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取角色菜单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取角色菜单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -410,20 +320,14 @@ exports.assignMenusToRole = async (req, res) => {
|
|||
const { menuIds } = req.body;
|
||||
|
||||
if (!Array.isArray(menuIds)) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '菜单ID必须是数组'
|
||||
});
|
||||
return response.badRequest(res, '菜单ID必须是数组');
|
||||
}
|
||||
|
||||
const Role = require('../models/Role');
|
||||
const role = await Role.findByPk(roleId);
|
||||
|
||||
if (!role) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '角色不存在'
|
||||
});
|
||||
return response.notFound(res, '角色不存在');
|
||||
}
|
||||
|
||||
await RoleMenu.destroy({
|
||||
|
|
@ -450,17 +354,10 @@ exports.assignMenusToRole = async (req, res) => {
|
|||
status: 'success'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '分配成功'
|
||||
});
|
||||
response.success(res, '分配成功');
|
||||
} catch (error) {
|
||||
console.error('分配菜单权限失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '分配菜单权限失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '分配菜单权限失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -505,18 +402,11 @@ exports.getUserMenus = async (req, res) => {
|
|||
const allMenus = [...menuList, ...buttonList];
|
||||
const menuTree = buildTree(allMenus);
|
||||
|
||||
return res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: menuTree
|
||||
});
|
||||
return response.success(res, '获取成功', menuTree);
|
||||
}
|
||||
|
||||
if (!user.role) {
|
||||
return res.status(403).json({
|
||||
code: 403,
|
||||
message: '用户没有分配角色'
|
||||
});
|
||||
return response.forbidden(res, '用户没有分配角色');
|
||||
}
|
||||
|
||||
// 普通用户返回角色分配的菜单
|
||||
|
|
@ -534,11 +424,7 @@ exports.getUserMenus = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!roleData || !roleData.menus) {
|
||||
return res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: []
|
||||
});
|
||||
return response.success(res, '获取成功', []);
|
||||
}
|
||||
|
||||
// 按sort排序
|
||||
|
|
@ -547,18 +433,10 @@ exports.getUserMenus = async (req, res) => {
|
|||
// 构建菜单树
|
||||
const menuTree = buildTree(menus);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: menuTree
|
||||
});
|
||||
response.success(res, '获取成功', menuTree);
|
||||
} catch (error) {
|
||||
console.error('获取用户菜单失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取用户菜单失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取用户菜单失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const { MeterReading, Bill, Room, Renter, Rental } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 生成账单编号
|
||||
const generateBillNo = () => {
|
||||
|
|
@ -98,16 +99,15 @@ const getAllMeterReadings = async (req, res) => {
|
|||
|
||||
const formattedReadings = rows.map(formatMeterReadingData);
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedReadings,
|
||||
response.success(res, '获取成功', {
|
||||
list: formattedReadings,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取抄表记录列表失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取抄表记录列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -135,17 +135,13 @@ const getMeterReadingById = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!reading) {
|
||||
return res.status(404).json({ code: 404, error: '抄表记录不存在' });
|
||||
return response.notFound(res, '抄表记录不存在');
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formatMeterReadingData(reading),
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formatMeterReadingData(reading));
|
||||
} catch (error) {
|
||||
console.error('获取抄表记录详情失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取抄表记录详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -221,17 +217,13 @@ const createMeterReading = async (req, res) => {
|
|||
// 更新抄表记录的账单ID
|
||||
await meterReading.update({ billId: bill.id });
|
||||
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: {
|
||||
meterReading: formatMeterReadingData(meterReading),
|
||||
bill: {
|
||||
id: bill.id,
|
||||
billNo: bill.billNo,
|
||||
status: bill.status
|
||||
}
|
||||
},
|
||||
message: '抄表记录创建成功,已自动生成账单'
|
||||
response.created(res, '抄表记录创建成功,已自动生成账单', {
|
||||
meterReading: formatMeterReadingData(meterReading),
|
||||
bill: {
|
||||
id: bill.id,
|
||||
billNo: bill.billNo,
|
||||
status: bill.status
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('创建抄表记录失败:', error);
|
||||
|
|
@ -239,23 +231,17 @@ const createMeterReading = async (req, res) => {
|
|||
if (error.name === 'SequelizeUniqueConstraintError') {
|
||||
const field = error.errors[0]?.path || '未知字段';
|
||||
if (field === 'uk_room_type_month') {
|
||||
return res.status(409).json({
|
||||
code: 409,
|
||||
error: '该房间本月已存在此类型的抄表记录,请勿重复创建'
|
||||
});
|
||||
return response.error(res, '该房间本月已存在此类型的抄表记录,请勿重复创建', 409);
|
||||
}
|
||||
return res.status(409).json({
|
||||
code: 409,
|
||||
error: `数据重复: ${field} 必须唯一`
|
||||
});
|
||||
return response.error(res, `数据重复: ${field} 必须唯一`, 409);
|
||||
}
|
||||
// 输出详细的验证错误信息
|
||||
if (error.name === 'SequelizeValidationError') {
|
||||
const messages = error.errors.map(e => `${e.path}: ${e.message}`).join(', ');
|
||||
console.error('验证错误详情:', messages);
|
||||
return res.status(400).json({ code: 400, error: `Validation error: ${messages}` });
|
||||
return response.badRequest(res, `Validation error: ${messages}`);
|
||||
}
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建抄表记录失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -276,7 +262,7 @@ const updateMeterReading = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!meterReading) {
|
||||
return res.status(404).json({ code: 404, error: '抄表记录不存在' });
|
||||
return response.notFound(res, '抄表记录不存在');
|
||||
}
|
||||
|
||||
// 重新计算用量和金额
|
||||
|
|
@ -305,14 +291,10 @@ const updateMeterReading = async (req, res) => {
|
|||
}
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formatMeterReadingData(meterReading),
|
||||
message: '更新成功'
|
||||
});
|
||||
response.success(res, '更新成功', formatMeterReadingData(meterReading));
|
||||
} catch (error) {
|
||||
console.error('更新抄表记录失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '更新抄表记录失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -325,7 +307,7 @@ const deleteMeterReading = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!meterReading) {
|
||||
return res.status(404).json({ code: 404, error: '抄表记录不存在' });
|
||||
return response.notFound(res, '抄表记录不存在');
|
||||
}
|
||||
|
||||
// 软删除抄表记录
|
||||
|
|
@ -345,13 +327,10 @@ const deleteMeterReading = async (req, res) => {
|
|||
}
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '抄表记录及关联账单删除成功'
|
||||
});
|
||||
response.success(res, '抄表记录及关联账单删除成功');
|
||||
} catch (error) {
|
||||
console.error('删除抄表记录失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '删除抄表记录失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -390,16 +369,15 @@ const getRoomMeterReadings = async (req, res) => {
|
|||
|
||||
const formattedReadings = rows.map(formatMeterReadingData);
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedReadings,
|
||||
response.success(res, '获取成功', {
|
||||
list: formattedReadings,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取房间抄表记录失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取房间抄表记录失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -418,16 +396,13 @@ const getLatestReading = async (req, res) => {
|
|||
order: [['billMonth', 'DESC']]
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: latestReading ? {
|
||||
previousReading: latestReading.currentReading,
|
||||
billMonth: latestReading.billMonth
|
||||
} : null
|
||||
});
|
||||
response.success(res, '获取成功', latestReading ? {
|
||||
previousReading: latestReading.currentReading,
|
||||
billMonth: latestReading.billMonth
|
||||
} : null);
|
||||
} catch (error) {
|
||||
console.error('获取最新读数失败:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取最新读数失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const { Rental, Room, Apartment, Bill, Transaction, Renter, MeterReading } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 格式化时间(考虑时区,转换为北京时间)
|
||||
const formatDate = (date) => {
|
||||
|
|
@ -149,14 +150,14 @@ const getAllRentals = async (req, res) => {
|
|||
const formattedRentals = rows.map(formatRentalData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
data: formattedRentals,
|
||||
response.success(res, '获取成功', {
|
||||
list: formattedRentals,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
response.serverError(res, '获取租房列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -183,16 +184,12 @@ const getRentalById = async (req, res) => {
|
|||
]
|
||||
});
|
||||
if (!rental) {
|
||||
return res.status(404).json({ error: '租房记录不存在' });
|
||||
return response.notFound(res, '租房记录不存在');
|
||||
}
|
||||
const formattedRental = formatRentalData(rental);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedRental,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedRental);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取租房详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -206,34 +203,34 @@ const createRental = async (req, res) => {
|
|||
|
||||
// 检查请求体是否存在
|
||||
if (!body) {
|
||||
return res.status(400).json({ error: '请求体不能为空' });
|
||||
return response.badRequest(res, '请求体不能为空');
|
||||
}
|
||||
|
||||
// 检查所有必要参数
|
||||
if (!body.roomId) {
|
||||
return res.status(400).json({ error: '缺少房间ID' });
|
||||
return response.badRequest(res, '缺少房间ID');
|
||||
}
|
||||
if (!body.renterId) {
|
||||
return res.status(400).json({ error: '缺少租客ID' });
|
||||
return response.badRequest(res, '缺少租客ID');
|
||||
}
|
||||
if (!body.startDate) {
|
||||
return res.status(400).json({ error: '缺少开始日期' });
|
||||
return response.badRequest(res, '缺少开始日期');
|
||||
}
|
||||
if (!body.endDate) {
|
||||
return res.status(400).json({ error: '缺少结束日期' });
|
||||
return response.badRequest(res, '缺少结束日期');
|
||||
}
|
||||
if (!body.rent) {
|
||||
return res.status(400).json({ error: '缺少租金' });
|
||||
return response.badRequest(res, '缺少租金');
|
||||
}
|
||||
|
||||
// 转换roomId和renterId为整数类型
|
||||
const parsedRoomId = parseInt(body.roomId);
|
||||
const parsedRenterId = parseInt(body.renterId);
|
||||
if (isNaN(parsedRoomId)) {
|
||||
return res.status(400).json({ error: '无效的房间ID' });
|
||||
return response.badRequest(res, '无效的房间ID');
|
||||
}
|
||||
if (isNaN(parsedRenterId)) {
|
||||
return res.status(400).json({ error: '无效的租客ID' });
|
||||
return response.badRequest(res, '无效的租客ID');
|
||||
}
|
||||
|
||||
// 处理押金,为空时设置为0
|
||||
|
|
@ -317,14 +314,10 @@ const createRental = async (req, res) => {
|
|||
});
|
||||
}
|
||||
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: rental,
|
||||
message: '创建成功'
|
||||
});
|
||||
response.created(res, '创建成功', rental);
|
||||
} catch (error) {
|
||||
console.error('创建租房记录时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建租房失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -337,7 +330,7 @@ const updateRental = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!rental) {
|
||||
return res.status(404).json({ error: '租房记录不存在' });
|
||||
return response.notFound(res, '租房记录不存在');
|
||||
}
|
||||
// 处理押金,为空时设置为0
|
||||
const updateDeposit = deposit || 0;
|
||||
|
|
@ -358,13 +351,9 @@ const updateRental = async (req, res) => {
|
|||
remark,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: rental,
|
||||
message: '更新成功'
|
||||
});
|
||||
response.success(res, '更新成功', rental);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '更新租房失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -376,18 +365,15 @@ const deleteRental = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!rental) {
|
||||
return res.status(404).json({ error: '租房记录不存在' });
|
||||
return response.notFound(res, '租房记录不存在');
|
||||
}
|
||||
await rental.update({
|
||||
isDeleted: 1,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '租房记录删除成功'
|
||||
});
|
||||
response.success(res, '租房记录删除成功');
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '删除租房失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -417,11 +403,11 @@ const terminateRental = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!rental) {
|
||||
return res.status(404).json({ error: '租房记录不存在' });
|
||||
return response.notFound(res, '租房记录不存在');
|
||||
}
|
||||
|
||||
if (rental.status !== 'active') {
|
||||
return res.status(400).json({ error: '只有生效中的租约可以退租' });
|
||||
return response.badRequest(res, '只有生效中的租约可以退租');
|
||||
}
|
||||
|
||||
const room = rental.Room;
|
||||
|
|
@ -484,14 +470,10 @@ const terminateRental = async (req, res) => {
|
|||
{ where: { id: room.id } }
|
||||
);
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: rental,
|
||||
message: '退租处理成功'
|
||||
});
|
||||
response.success(res, '退租处理成功', rental);
|
||||
} catch (error) {
|
||||
console.error('退租处理时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '退租处理失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -560,13 +542,9 @@ const listRentals = async (req, res) => {
|
|||
const formattedRentals = rentals.map(formatRentalData);
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedRentals,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedRentals);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取租房列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -602,25 +580,25 @@ const createRentalWithRenter = async (req, res) => {
|
|||
// 参数验证
|
||||
if (!renterName) {
|
||||
await transaction.rollback();
|
||||
return res.status(400).json({ code: 400, error: '租客姓名不能为空' });
|
||||
return response.badRequest(res, '租客姓名不能为空');
|
||||
}
|
||||
if (!roomId) {
|
||||
await transaction.rollback();
|
||||
return res.status(400).json({ code: 400, error: '房间ID不能为空' });
|
||||
return response.badRequest(res, '房间ID不能为空');
|
||||
}
|
||||
if (!startDate || !endDate) {
|
||||
await transaction.rollback();
|
||||
return res.status(400).json({ code: 400, error: '开始日期和结束日期不能为空' });
|
||||
return response.badRequest(res, '开始日期和结束日期不能为空');
|
||||
}
|
||||
if (!rent) {
|
||||
await transaction.rollback();
|
||||
return res.status(400).json({ code: 400, error: '租金不能为空' });
|
||||
return response.badRequest(res, '租金不能为空');
|
||||
}
|
||||
|
||||
const parsedRoomId = parseInt(roomId);
|
||||
if (isNaN(parsedRoomId)) {
|
||||
await transaction.rollback();
|
||||
return res.status(400).json({ code: 400, error: '无效的房间ID' });
|
||||
return response.badRequest(res, '无效的房间ID');
|
||||
}
|
||||
|
||||
// 1. 创建租客
|
||||
|
|
@ -775,21 +753,17 @@ const createRentalWithRenter = async (req, res) => {
|
|||
// 提交事务
|
||||
await transaction.commit();
|
||||
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: {
|
||||
rentalId: rental.id,
|
||||
renterId: renter.id,
|
||||
roomId: parsedRoomId
|
||||
},
|
||||
message: '创建成功'
|
||||
response.created(res, '创建成功', {
|
||||
rentalId: rental.id,
|
||||
renterId: renter.id,
|
||||
roomId: parsedRoomId
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
// 回滚事务
|
||||
await transaction.rollback();
|
||||
console.error('创建租房(整合)时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建租房失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const { Renter, Rental, Room, Apartment } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取租客列表(分页)
|
||||
const getRenters = async (req, res) => {
|
||||
|
|
@ -28,23 +29,15 @@ const getRenters = async (req, res) => {
|
|||
limit: parseInt(pageSize)
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: {
|
||||
list: rows,
|
||||
pagination: {
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
}
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取租客列表失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取租客列表失败'
|
||||
});
|
||||
response.serverError(res, '获取租客列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -73,16 +66,10 @@ const getRenterList = async (req, res) => {
|
|||
order: [['createTime', 'DESC']]
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: rows
|
||||
});
|
||||
response.success(res, '获取成功', rows);
|
||||
} catch (error) {
|
||||
console.error('获取租客列表失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取租客列表失败'
|
||||
});
|
||||
response.serverError(res, '获取租客列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -97,10 +84,7 @@ const getRenterById = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!renter) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '租客不存在'
|
||||
});
|
||||
return response.notFound(res, '租客不存在');
|
||||
}
|
||||
|
||||
// 获取租客的租赁记录
|
||||
|
|
@ -121,20 +105,13 @@ const getRenterById = async (req, res) => {
|
|||
order: [['createTime', 'DESC']]
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: {
|
||||
...renter.toJSON(),
|
||||
rentals
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
...renter.toJSON(),
|
||||
rentals
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取租客详情失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取租客详情失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取租客详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -160,10 +137,7 @@ const createRenter = async (req, res) => {
|
|||
|
||||
// 验证必填字段
|
||||
if (!name) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '租客姓名不能为空'
|
||||
});
|
||||
return response.badRequest(res, '租客姓名不能为空');
|
||||
}
|
||||
|
||||
// 检查手机号是否已存在
|
||||
|
|
@ -172,10 +146,7 @@ const createRenter = async (req, res) => {
|
|||
where: { phone, tenantId, isDeleted: 0 }
|
||||
});
|
||||
if (existingRenter) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '该手机号已存在'
|
||||
});
|
||||
return response.badRequest(res, '该手机号已存在');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,17 +167,10 @@ const createRenter = async (req, res) => {
|
|||
status: 'active'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '创建成功',
|
||||
data: renter
|
||||
});
|
||||
response.created(res, '创建成功', renter);
|
||||
} catch (error) {
|
||||
console.error('创建租客失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建租客失败'
|
||||
});
|
||||
response.serverError(res, '创建租客失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -222,10 +186,7 @@ const updateRenter = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!renter) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '租客不存在'
|
||||
});
|
||||
return response.notFound(res, '租客不存在');
|
||||
}
|
||||
|
||||
const {
|
||||
|
|
@ -249,10 +210,7 @@ const updateRenter = async (req, res) => {
|
|||
where: { phone, tenantId, isDeleted: 0, id: { [Op.ne]: id } }
|
||||
});
|
||||
if (existingRenter) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '该手机号已被其他租客使用'
|
||||
});
|
||||
return response.badRequest(res, '该手机号已被其他租客使用');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,17 +230,10 @@ const updateRenter = async (req, res) => {
|
|||
updateBy
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '更新成功',
|
||||
data: renter
|
||||
});
|
||||
response.success(res, '更新成功', renter);
|
||||
} catch (error) {
|
||||
console.error('更新租客失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新租客失败'
|
||||
});
|
||||
response.serverError(res, '更新租客失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -297,10 +248,7 @@ const deleteRenter = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!renter) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '租客不存在'
|
||||
});
|
||||
return response.notFound(res, '租客不存在');
|
||||
}
|
||||
|
||||
// 检查是否有进行中的租赁
|
||||
|
|
@ -313,24 +261,15 @@ const deleteRenter = async (req, res) => {
|
|||
});
|
||||
|
||||
if (activeRentals > 0) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '该租客有进行中的租赁,无法删除'
|
||||
});
|
||||
return response.badRequest(res, '该租客有进行中的租赁,无法删除');
|
||||
}
|
||||
|
||||
await renter.update({ isDeleted: 1 });
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '删除成功'
|
||||
});
|
||||
response.success(res, '删除成功');
|
||||
} catch (error) {
|
||||
console.error('删除租客失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '删除租客失败'
|
||||
});
|
||||
response.serverError(res, '删除租客失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -356,19 +295,13 @@ const getRenterOptions = async (req, res) => {
|
|||
limit: 50
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
data: renters.map(r => ({
|
||||
value: r.id,
|
||||
label: `${r.name} ${r.phone ? '(' + r.phone + ')' : ''}`
|
||||
}))
|
||||
});
|
||||
response.success(res, '获取成功', renters.map(r => ({
|
||||
value: r.id,
|
||||
label: `${r.name} ${r.phone ? '(' + r.phone + ')' : ''}`
|
||||
})));
|
||||
} catch (error) {
|
||||
console.error('获取租客选项失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取租客选项失败'
|
||||
});
|
||||
response.serverError(res, '获取租客选项失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { Op } = require('sequelize');
|
||||
const Role = require('../models/Role');
|
||||
const { logOperation } = require('../utils/logger');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取角色列表
|
||||
exports.getRoles = async (req, res) => {
|
||||
|
|
@ -25,15 +26,11 @@ exports.getRoles = async (req, res) => {
|
|||
order: [['id', 'DESC']]
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取角色列表成功',
|
||||
data: {
|
||||
list: roles,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
}
|
||||
response.success(res, '获取角色列表成功', {
|
||||
list: roles,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
|
||||
// 记录操作日志
|
||||
|
|
@ -52,11 +49,7 @@ exports.getRoles = async (req, res) => {
|
|||
|
||||
} catch (error) {
|
||||
console.error('获取角色列表错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取角色列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取角色列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -78,17 +71,10 @@ exports.getRoleById = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!role) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '角色不存在'
|
||||
});
|
||||
return response.notFound(res, '角色不存在');
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取角色详情成功',
|
||||
data: role
|
||||
});
|
||||
response.success(res, '获取角色详情成功', role);
|
||||
|
||||
// 记录操作日志
|
||||
await logOperation({
|
||||
|
|
@ -106,11 +92,7 @@ exports.getRoleById = async (req, res) => {
|
|||
|
||||
} catch (error) {
|
||||
console.error('获取角色详情错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取角色详情失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取角色详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -122,10 +104,7 @@ exports.createRole = async (req, res) => {
|
|||
|
||||
// 参数验证
|
||||
if (!name || !code) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '角色名称和编码不能为空'
|
||||
});
|
||||
return response.badRequest(res, '角色名称和编码不能为空');
|
||||
}
|
||||
|
||||
// 检查角色编码是否已存在(限制在当前租户内)
|
||||
|
|
@ -138,10 +117,7 @@ exports.createRole = async (req, res) => {
|
|||
});
|
||||
|
||||
if (existingRole) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '角色编码已存在'
|
||||
});
|
||||
return response.badRequest(res, '角色编码已存在');
|
||||
}
|
||||
|
||||
const role = await Role.create({
|
||||
|
|
@ -155,11 +131,7 @@ exports.createRole = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '创建角色成功',
|
||||
data: role
|
||||
});
|
||||
response.success(res, '创建角色成功', role);
|
||||
|
||||
// 记录操作日志
|
||||
await logOperation({
|
||||
|
|
@ -177,11 +149,7 @@ exports.createRole = async (req, res) => {
|
|||
|
||||
} catch (error) {
|
||||
console.error('创建角色错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建角色失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '创建角色失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -202,10 +170,7 @@ exports.updateRole = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!role) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '角色不存在'
|
||||
});
|
||||
return response.notFound(res, '角色不存在');
|
||||
}
|
||||
|
||||
// 检查角色编码是否已存在(排除当前角色)
|
||||
|
|
@ -220,10 +185,7 @@ exports.updateRole = async (req, res) => {
|
|||
});
|
||||
|
||||
if (existingRole) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '角色编码已存在'
|
||||
});
|
||||
return response.badRequest(res, '角色编码已存在');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,11 +198,7 @@ exports.updateRole = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '更新角色成功',
|
||||
data: role
|
||||
});
|
||||
response.success(res, '更新角色成功', role);
|
||||
|
||||
// 记录操作日志
|
||||
await logOperation({
|
||||
|
|
@ -258,11 +216,7 @@ exports.updateRole = async (req, res) => {
|
|||
|
||||
} catch (error) {
|
||||
console.error('更新角色错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新角色失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新角色失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -282,10 +236,7 @@ exports.deleteRole = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!role) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '角色不存在'
|
||||
});
|
||||
return response.notFound(res, '角色不存在');
|
||||
}
|
||||
|
||||
// 检查是否有用户使用此角色
|
||||
|
|
@ -294,10 +245,7 @@ exports.deleteRole = async (req, res) => {
|
|||
});
|
||||
|
||||
if (userCount > 0) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '该角色下还有用户,无法删除'
|
||||
});
|
||||
return response.badRequest(res, '该角色下还有用户,无法删除');
|
||||
}
|
||||
|
||||
// 软删除
|
||||
|
|
@ -306,10 +254,7 @@ exports.deleteRole = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '删除角色成功'
|
||||
});
|
||||
response.success(res, '删除角色成功');
|
||||
|
||||
// 记录操作日志
|
||||
await logOperation({
|
||||
|
|
@ -327,11 +272,7 @@ exports.deleteRole = async (req, res) => {
|
|||
|
||||
} catch (error) {
|
||||
console.error('删除角色错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '删除角色失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '删除角色失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -352,18 +293,10 @@ exports.getAllRoles = async (req, res) => {
|
|||
attributes: ['id', 'name', 'code']
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取角色列表成功',
|
||||
data: roles
|
||||
});
|
||||
response.success(res, '获取角色列表成功', roles);
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取角色列表错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取角色列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取角色列表失败', error);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { Room, Apartment, Rental, Renter, Tenant } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const { logOperation } = require('../utils/logger');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 格式化时间(考虑时区,转换为北京时间)
|
||||
const formatDate = (date) => {
|
||||
|
|
@ -179,14 +180,14 @@ const getAllRooms = async (req, res) => {
|
|||
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
data: formattedRooms,
|
||||
response.success(res, '获取成功', {
|
||||
list: formattedRooms,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
response.serverError(res, '获取房间列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -202,7 +203,7 @@ const getRoomById = async (req, res) => {
|
|||
include: [Apartment]
|
||||
});
|
||||
if (!room) {
|
||||
return res.status(404).json({ error: '房间不存在' });
|
||||
return response.notFound(res, '房间不存在');
|
||||
}
|
||||
|
||||
// 格式化房间数据
|
||||
|
|
@ -242,13 +243,9 @@ const getRoomById = async (req, res) => {
|
|||
} else {
|
||||
formattedRoom.Rentals = [];
|
||||
}
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedRoom,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedRoom);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取房间详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -302,14 +299,12 @@ const createRoom = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
};
|
||||
const room = await Room.create(processedData);
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: room,
|
||||
message: '创建成功',
|
||||
response.created(res, '创建成功', {
|
||||
room,
|
||||
warning: tenant && currentRoomCount >= tenant.maxRooms ? `当前已超出套餐限制(${tenant.maxRooms}间),续费时将收取超额费用` : null
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '创建房间失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -322,7 +317,7 @@ const updateRoom = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!room) {
|
||||
return res.status(404).json({ error: '房间不存在' });
|
||||
return response.notFound(res, '房间不存在');
|
||||
}
|
||||
// 处理空值
|
||||
const processedData = {
|
||||
|
|
@ -340,13 +335,9 @@ const updateRoom = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
};
|
||||
await room.update(processedData);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: room,
|
||||
message: '更新成功'
|
||||
});
|
||||
response.success(res, '更新成功', room);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '更新房间失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -358,18 +349,15 @@ const deleteRoom = async (req, res) => {
|
|||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!room) {
|
||||
return res.status(404).json({ error: '房间不存在' });
|
||||
return response.notFound(res, '房间不存在');
|
||||
}
|
||||
await room.update({
|
||||
isDeleted: 1,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '房间删除成功'
|
||||
});
|
||||
response.success(res, '房间删除成功');
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '删除房间失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -446,13 +434,9 @@ const listRooms = async (req, res) => {
|
|||
}));
|
||||
|
||||
// 返回结果
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedRooms,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', formattedRooms);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取房间列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
const { Setting, Category } = require('../models');
|
||||
const response = require('../utils/response');
|
||||
|
||||
/**
|
||||
* 获取系统设置
|
||||
|
|
@ -24,18 +25,10 @@ const getSettings = async (req, res) => {
|
|||
...settingsMap
|
||||
};
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: defaultSettings
|
||||
});
|
||||
response.success(res, '获取成功', defaultSettings);
|
||||
} catch (error) {
|
||||
console.error('获取设置失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取设置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取设置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -71,17 +64,10 @@ const updateSettings = async (req, res) => {
|
|||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '设置保存成功'
|
||||
});
|
||||
response.success(res, '设置保存成功');
|
||||
} catch (error) {
|
||||
console.error('保存设置失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '保存设置失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '保存设置失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -108,18 +94,10 @@ const getCategories = async (req, res) => {
|
|||
order: [['sort', 'ASC'], ['id', 'ASC']]
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: categories
|
||||
});
|
||||
response.success(res, '获取成功', categories);
|
||||
} catch (error) {
|
||||
console.error('获取类目失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取类目失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取类目失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -138,10 +116,7 @@ const createCategory = async (req, res) => {
|
|||
});
|
||||
|
||||
if (existing) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '类目编码已存在'
|
||||
});
|
||||
return response.badRequest(res, '类目编码已存在');
|
||||
}
|
||||
|
||||
const category = await Category.create({
|
||||
|
|
@ -154,18 +129,10 @@ const createCategory = async (req, res) => {
|
|||
updateBy: userId
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '创建成功',
|
||||
data: category
|
||||
});
|
||||
response.success(res, '创建成功', category);
|
||||
} catch (error) {
|
||||
console.error('创建类目失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建类目失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '创建类目失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -184,23 +151,17 @@ const updateCategory = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!category) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '类目不存在'
|
||||
});
|
||||
return response.notFound(res, '类目不存在');
|
||||
}
|
||||
|
||||
// 检查编码是否与其他类目冲突
|
||||
if (code && code !== category.code) {
|
||||
const existing = await Category.findOne({
|
||||
where: { code, tenantId, isDeleted: 0, id: { $ne: id } }
|
||||
where: { code, tenantId, isDeleted: 0, id: { [Op.ne]: id } }
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '类目编码已存在'
|
||||
});
|
||||
return response.badRequest(res, '类目编码已存在');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,18 +174,10 @@ const updateCategory = async (req, res) => {
|
|||
updateBy: userId
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '更新成功',
|
||||
data: category
|
||||
});
|
||||
response.success(res, '更新成功', category);
|
||||
} catch (error) {
|
||||
console.error('更新类目失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新类目失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新类目失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -242,18 +195,12 @@ const deleteCategory = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!category) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '类目不存在'
|
||||
});
|
||||
return response.notFound(res, '类目不存在');
|
||||
}
|
||||
|
||||
// 默认类目不允许删除
|
||||
if (category.isDefault) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '默认类目不能删除'
|
||||
});
|
||||
return response.badRequest(res, '默认类目不能删除');
|
||||
}
|
||||
|
||||
await category.update({
|
||||
|
|
@ -261,17 +208,10 @@ const deleteCategory = async (req, res) => {
|
|||
updateBy: userId
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '删除成功'
|
||||
});
|
||||
response.success(res, '删除成功');
|
||||
} catch (error) {
|
||||
console.error('删除类目失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '删除类目失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '删除类目失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const { Room, Rental, Apartment, Bill } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 租金统计
|
||||
const getRentStatistics = async (req, res) => {
|
||||
|
|
@ -105,14 +106,10 @@ const getRentStatistics = async (req, res) => {
|
|||
}))
|
||||
.sort((a, b) => b.month.localeCompare(a.month));
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: rentStatistics,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', rentStatistics);
|
||||
} catch (error) {
|
||||
console.error('获取租金统计数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取租金统计数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -156,13 +153,9 @@ const getRoomStatusStatistics = async (req, res) => {
|
|||
expired: expired
|
||||
};
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: roomStatusStatistics,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', roomStatusStatistics);
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取房间状态统计失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -223,14 +216,10 @@ const getDashboardStatistics = async (req, res) => {
|
|||
collectedWaterAmount: parseFloat(collectedWaterAmount) || 0
|
||||
};
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: dashboardStatistics,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', dashboardStatistics);
|
||||
} catch (error) {
|
||||
console.error('获取Dashboard统计数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取Dashboard统计数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -280,14 +269,10 @@ const getApartmentRoomStatusStatistics = async (req, res) => {
|
|||
};
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: apartmentRoomStatusStatistics,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', apartmentRoomStatusStatistics);
|
||||
} catch (error) {
|
||||
console.error('获取公寓房间状态分布数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取公寓房间状态分布数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -323,14 +308,10 @@ const getEmptyRoomsByApartment = async (req, res) => {
|
|||
};
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: emptyRoomsByApartment,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', emptyRoomsByApartment);
|
||||
} catch (error) {
|
||||
console.error('获取空房分布数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取空房分布数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -366,14 +347,10 @@ const getRentedRoomsByApartment = async (req, res) => {
|
|||
};
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: rentedRoomsByApartment,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', rentedRoomsByApartment);
|
||||
} catch (error) {
|
||||
console.error('获取在租分布数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取在租分布数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -437,14 +414,10 @@ const getTenantRentalStats = async (req, res) => {
|
|||
// 转换为数组
|
||||
const tenantRentalStats = Array.from(tenantMap.values());
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: tenantRentalStats,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', tenantRentalStats);
|
||||
} catch (error) {
|
||||
console.error('获取租客在租统计数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取租客在租统计数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -481,14 +454,10 @@ const getSoonExpireRoomsByApartment = async (req, res) => {
|
|||
};
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: soonExpireRoomsByApartment,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', soonExpireRoomsByApartment);
|
||||
} catch (error) {
|
||||
console.error('获取即将到期分布数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取即将到期分布数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -525,14 +494,10 @@ const getExpiredRoomsByApartment = async (req, res) => {
|
|||
};
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: expiredRoomsByApartment,
|
||||
message: 'success'
|
||||
});
|
||||
response.success(res, '获取成功', expiredRoomsByApartment);
|
||||
} catch (error) {
|
||||
console.error('获取已到期分布数据时出错:', error);
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
response.serverError(res, '获取已到期分布数据失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -546,4 +511,4 @@ module.exports = {
|
|||
getSoonExpireRoomsByApartment,
|
||||
getExpiredRoomsByApartment,
|
||||
getTenantRentalStats
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const User = require('../models/User');
|
|||
const Role = require('../models/Role');
|
||||
const Tenant = require('../models/Tenant');
|
||||
const { logOperation } = require('../utils/logger');
|
||||
const response = require('../utils/response');
|
||||
|
||||
// 获取用户列表
|
||||
exports.getUserList = async (req, res) => {
|
||||
|
|
@ -36,23 +37,15 @@ exports.getUserList = async (req, res) => {
|
|||
limit: parseInt(pageSize)
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
}
|
||||
response.success(res, '获取成功', {
|
||||
list: rows,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取用户列表错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取用户列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取用户列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -72,17 +65,10 @@ exports.getUserById = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取成功',
|
||||
data: user
|
||||
});
|
||||
response.success(res, '获取成功', user);
|
||||
|
||||
// 记录操作日志
|
||||
await logOperation({
|
||||
|
|
@ -98,11 +84,7 @@ exports.getUserById = async (req, res) => {
|
|||
});
|
||||
} catch (error) {
|
||||
console.error('获取用户详情错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取用户详情失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取用户详情失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -113,31 +95,19 @@ exports.createUser = async (req, res) => {
|
|||
|
||||
// 参数验证
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '用户名和密码不能为空'
|
||||
});
|
||||
return response.badRequest(res, '用户名和密码不能为空');
|
||||
}
|
||||
|
||||
if (username.length < 3 || username.length > 20) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '用户名长度应在3-20个字符之间'
|
||||
});
|
||||
return response.badRequest(res, '用户名长度应在3-20个字符之间');
|
||||
}
|
||||
|
||||
if (password.length < 6 || password.length > 20) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '密码长度应在6-20个字符之间'
|
||||
});
|
||||
return response.badRequest(res, '密码长度应在6-20个字符之间');
|
||||
}
|
||||
|
||||
if (!roleId) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '角色不能为空'
|
||||
});
|
||||
return response.badRequest(res, '角色不能为空');
|
||||
}
|
||||
|
||||
// 检查租户资源使用情况(仅记录日志,不阻止创建)
|
||||
|
|
@ -174,19 +144,13 @@ exports.createUser = async (req, res) => {
|
|||
where: { isDeleted: 0, status: 'active' }
|
||||
});
|
||||
if (!role) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '角色不存在或已禁用'
|
||||
});
|
||||
return response.badRequest(res, '角色不存在或已禁用');
|
||||
}
|
||||
|
||||
// 检查用户名是否已存在
|
||||
const existingUser = await User.findOne({ where: { username, isDeleted: 0 } });
|
||||
if (existingUser) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '用户名已存在'
|
||||
});
|
||||
return response.badRequest(res, '用户名已存在');
|
||||
}
|
||||
|
||||
// 加密密码
|
||||
|
|
@ -203,16 +167,12 @@ exports.createUser = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '创建成功',
|
||||
data: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
roleId: user.roleId,
|
||||
createTime: user.createTime
|
||||
},
|
||||
response.success(res, '创建成功', {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
roleId: user.roleId,
|
||||
createTime: user.createTime,
|
||||
warning: isOverage && tenant ? `当前已超出套餐限制(${tenant.maxUsers}人),续费时将收取超额费用` : null
|
||||
});
|
||||
|
||||
|
|
@ -230,11 +190,7 @@ exports.createUser = async (req, res) => {
|
|||
});
|
||||
} catch (error) {
|
||||
console.error('创建用户错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '创建用户失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '创建用户失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -249,10 +205,7 @@ exports.updateUser = async (req, res) => {
|
|||
where: { isDeleted: 0 }
|
||||
});
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
// 检查角色是否存在
|
||||
|
|
@ -261,10 +214,7 @@ exports.updateUser = async (req, res) => {
|
|||
where: { isDeleted: 0, status: 'active' }
|
||||
});
|
||||
if (!role) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '角色不存在或已禁用'
|
||||
});
|
||||
return response.badRequest(res, '角色不存在或已禁用');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,17 +229,13 @@ exports.updateUser = async (req, res) => {
|
|||
// 更新用户
|
||||
await user.update(updateData);
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '更新成功',
|
||||
data: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
roleId: user.roleId,
|
||||
status: user.status,
|
||||
updateTime: user.updateTime
|
||||
}
|
||||
response.success(res, '更新成功', {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
roleId: user.roleId,
|
||||
status: user.status,
|
||||
updateTime: user.updateTime
|
||||
});
|
||||
|
||||
// 记录操作日志
|
||||
|
|
@ -306,11 +252,7 @@ exports.updateUser = async (req, res) => {
|
|||
});
|
||||
} catch (error) {
|
||||
console.error('更新用户错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新用户失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新用户失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -321,10 +263,7 @@ exports.deleteUser = async (req, res) => {
|
|||
|
||||
// 不能删除自己
|
||||
if (parseInt(id) === req.user.id) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '不能删除自己的账号'
|
||||
});
|
||||
return response.badRequest(res, '不能删除自己的账号');
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
|
|
@ -332,10 +271,7 @@ exports.deleteUser = async (req, res) => {
|
|||
where: { isDeleted: 0 }
|
||||
});
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
// 软删除
|
||||
|
|
@ -344,10 +280,7 @@ exports.deleteUser = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '删除成功'
|
||||
});
|
||||
response.success(res, '删除成功');
|
||||
|
||||
// 记录操作日志
|
||||
await logOperation({
|
||||
|
|
@ -363,11 +296,7 @@ exports.deleteUser = async (req, res) => {
|
|||
});
|
||||
} catch (error) {
|
||||
console.error('删除用户错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '删除用户失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '删除用户失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -382,10 +311,7 @@ exports.resetUserPassword = async (req, res) => {
|
|||
where: { isDeleted: 0 }
|
||||
});
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
// 加密默认密码
|
||||
|
|
@ -397,12 +323,8 @@ exports.resetUserPassword = async (req, res) => {
|
|||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '密码重置成功',
|
||||
data: {
|
||||
defaultPassword
|
||||
}
|
||||
response.success(res, '密码重置成功', {
|
||||
defaultPassword
|
||||
});
|
||||
|
||||
// 记录操作日志
|
||||
|
|
@ -419,11 +341,7 @@ exports.resetUserPassword = async (req, res) => {
|
|||
});
|
||||
} catch (error) {
|
||||
console.error('重置密码错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '重置密码失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '重置密码失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -435,19 +353,10 @@ exports.getAllUsers = async (req, res) => {
|
|||
attributes: ['id', 'username', 'nickname']
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取用户列表成功',
|
||||
data: users
|
||||
});
|
||||
|
||||
response.success(res, '获取用户列表成功', users);
|
||||
} catch (error) {
|
||||
console.error('获取用户列表错误:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取用户列表失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取用户列表失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -464,24 +373,13 @@ exports.getCurrentUserInfo = async (req, res) => {
|
|||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '获取用户信息成功',
|
||||
data: user
|
||||
});
|
||||
response.success(res, '获取用户信息成功', user);
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '获取用户信息失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '获取用户信息失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -492,19 +390,13 @@ exports.updateUserProfile = async (req, res) => {
|
|||
|
||||
// 验证昵称
|
||||
if (!nickname || nickname.trim().length === 0) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '昵称不能为空'
|
||||
});
|
||||
return response.badRequest(res, '昵称不能为空');
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
const user = await User.findByPk(req.user.id);
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
await user.update({
|
||||
|
|
@ -525,25 +417,17 @@ exports.updateUserProfile = async (req, res) => {
|
|||
status: 'success'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '个人资料更新成功',
|
||||
data: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
status: user.status,
|
||||
createTime: user.createTime,
|
||||
updateTime: user.updateTime
|
||||
}
|
||||
response.success(res, '个人资料更新成功', {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
status: user.status,
|
||||
createTime: user.createTime,
|
||||
updateTime: user.updateTime
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('更新个人资料失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '更新个人资料失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '更新个人资料失败', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -554,34 +438,22 @@ exports.changePassword = async (req, res) => {
|
|||
|
||||
// 验证参数
|
||||
if (!oldPassword || !newPassword) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '旧密码和新密码不能为空'
|
||||
});
|
||||
return response.badRequest(res, '旧密码和新密码不能为空');
|
||||
}
|
||||
|
||||
if (newPassword.length < 6) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '新密码长度至少6位'
|
||||
});
|
||||
return response.badRequest(res, '新密码长度至少6位');
|
||||
}
|
||||
|
||||
// 验证旧密码
|
||||
const user = await User.findByPk(req.user.id);
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
code: 404,
|
||||
message: '用户不存在'
|
||||
});
|
||||
return response.notFound(res, '用户不存在');
|
||||
}
|
||||
|
||||
const isPasswordValid = await bcrypt.compare(oldPassword, user.password);
|
||||
if (!isPasswordValid) {
|
||||
return res.status(400).json({
|
||||
code: 400,
|
||||
message: '旧密码错误'
|
||||
});
|
||||
return response.badRequest(res, '旧密码错误');
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
|
|
@ -604,16 +476,9 @@ exports.changePassword = async (req, res) => {
|
|||
status: 'success'
|
||||
});
|
||||
|
||||
res.json({
|
||||
code: 200,
|
||||
message: '密码修改成功'
|
||||
});
|
||||
response.success(res, '密码修改成功');
|
||||
} catch (error) {
|
||||
console.error('修改密码失败:', error);
|
||||
res.status(500).json({
|
||||
code: 500,
|
||||
message: '修改密码失败',
|
||||
error: error.message
|
||||
});
|
||||
response.serverError(res, '修改密码失败', error);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,283 +0,0 @@
|
|||
const { WaterBill, Room } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
|
||||
// 格式化时间(考虑时区,转换为北京时间)
|
||||
const formatDate = (date) => {
|
||||
if (!date) return null;
|
||||
// 确保date是Date对象
|
||||
const dateObj = date instanceof Date ? date : new Date(date);
|
||||
// 创建一个新的Date对象,加上8小时的时区偏移
|
||||
const beijingDate = new Date(dateObj.getTime() + 8 * 60 * 60 * 1000);
|
||||
return beijingDate.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
// 格式化水费数据
|
||||
const formatWaterBillData = (bill) => {
|
||||
const formattedBill = {
|
||||
...bill.toJSON(),
|
||||
startDate: formatDate(bill.startDate),
|
||||
endDate: formatDate(bill.endDate),
|
||||
createTime: formatDate(bill.createTime),
|
||||
updateTime: formatDate(bill.updateTime)
|
||||
};
|
||||
|
||||
// 格式化关联数据
|
||||
if (formattedBill.Room) {
|
||||
formattedBill.Room = {
|
||||
...formattedBill.Room,
|
||||
createTime: formatDate(formattedBill.Room.createTime),
|
||||
updateTime: formatDate(formattedBill.Room.updateTime)
|
||||
};
|
||||
}
|
||||
|
||||
return formattedBill;
|
||||
};
|
||||
|
||||
// 获取所有水费记录(支持搜索和分页)
|
||||
const getAllWaterBills = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
apartmentId,
|
||||
roomId,
|
||||
status,
|
||||
startDateFrom,
|
||||
endDateTo,
|
||||
page = 1,
|
||||
pageSize = 10
|
||||
} = req.query;
|
||||
|
||||
const where = { isDeleted: 0 };
|
||||
if (roomId) {
|
||||
where.roomId = roomId;
|
||||
}
|
||||
if (status) {
|
||||
where.status = status;
|
||||
}
|
||||
if (startDateFrom && endDateTo) {
|
||||
where.startDate = { [Op.gte]: new Date(startDateFrom) };
|
||||
where.endDate = { [Op.lte]: new Date(endDateTo) };
|
||||
}
|
||||
|
||||
const include = [
|
||||
{
|
||||
model: Room,
|
||||
where: {
|
||||
isDeleted: 0,
|
||||
...(apartmentId ? { apartmentId } : {})
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const offset = (page - 1) * pageSize;
|
||||
|
||||
const { count, rows } = await WaterBill.findAndCountAll({
|
||||
where,
|
||||
include,
|
||||
limit: parseInt(pageSize),
|
||||
offset: parseInt(offset),
|
||||
order: [['createTime', 'DESC']]
|
||||
});
|
||||
|
||||
const formattedBills = rows.map(formatWaterBillData);
|
||||
|
||||
res.status(200).json({
|
||||
data: formattedBills,
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
pageSize: parseInt(pageSize)
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 获取单个水费记录
|
||||
const getWaterBillById = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const bill = await WaterBill.findOne({
|
||||
where: { id, isDeleted: 0 },
|
||||
include: [
|
||||
{
|
||||
model: Room,
|
||||
where: { isDeleted: 0 }
|
||||
}
|
||||
]
|
||||
});
|
||||
if (!bill) {
|
||||
return res.status(404).json({ error: '水费记录不存在' });
|
||||
}
|
||||
const formattedBill = formatWaterBillData(bill);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBill,
|
||||
message: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 创建水费记录
|
||||
const createWaterBill = async (req, res) => {
|
||||
try {
|
||||
const { roomId, startDate, endDate, startReading, endReading, unitPrice, status } = req.body;
|
||||
|
||||
let usage = null;
|
||||
let amount = null;
|
||||
|
||||
if (startReading && endReading && unitPrice) {
|
||||
usage = parseFloat(endReading) - parseFloat(startReading);
|
||||
amount = usage * parseFloat(unitPrice);
|
||||
}
|
||||
|
||||
const bill = await WaterBill.create({
|
||||
roomId,
|
||||
startDate,
|
||||
endDate,
|
||||
startReading,
|
||||
endReading,
|
||||
usage,
|
||||
unitPrice,
|
||||
amount,
|
||||
status: status || 'unpaid',
|
||||
createBy: req.user.id,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
const formattedBill = formatWaterBillData(bill);
|
||||
res.status(201).json({
|
||||
code: 201,
|
||||
data: formattedBill,
|
||||
message: '创建成功'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 更新水费记录
|
||||
const updateWaterBill = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { startDate, endDate, startReading, endReading, unitPrice, status } = req.body;
|
||||
|
||||
const bill = await WaterBill.findOne({
|
||||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!bill) {
|
||||
return res.status(404).json({ error: '水费记录不存在' });
|
||||
}
|
||||
|
||||
let usage = bill.usage;
|
||||
let amount = bill.amount;
|
||||
if (startReading && endReading && unitPrice) {
|
||||
usage = parseFloat(endReading) - parseFloat(startReading);
|
||||
amount = usage * parseFloat(unitPrice);
|
||||
}
|
||||
|
||||
await bill.update({
|
||||
startDate,
|
||||
endDate,
|
||||
startReading,
|
||||
endReading,
|
||||
usage,
|
||||
unitPrice,
|
||||
amount,
|
||||
status: status !== undefined ? status : bill.status,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
|
||||
const formattedBill = formatWaterBillData(bill);
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBill,
|
||||
message: '更新成功'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 删除水费记录(软删除)
|
||||
const deleteWaterBill = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const bill = await WaterBill.findOne({
|
||||
where: { id, isDeleted: 0 }
|
||||
});
|
||||
if (!bill) {
|
||||
return res.status(404).json({ error: '水费记录不存在' });
|
||||
}
|
||||
await bill.update({
|
||||
isDeleted: 1,
|
||||
updateBy: req.user.id
|
||||
});
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
message: '水费记录删除成功'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// 获取所有水费记录(不分页)
|
||||
const listWaterBills = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
apartmentId,
|
||||
roomId,
|
||||
status,
|
||||
startDateFrom,
|
||||
endDateTo
|
||||
} = req.query;
|
||||
|
||||
const where = { isDeleted: 0 };
|
||||
if (roomId) {
|
||||
where.roomId = roomId;
|
||||
}
|
||||
if (status) {
|
||||
where.status = status;
|
||||
}
|
||||
if (startDateFrom && endDateTo) {
|
||||
where.startDate = { [Op.gte]: new Date(startDateFrom) };
|
||||
where.endDate = { [Op.lte]: new Date(endDateTo) };
|
||||
}
|
||||
|
||||
const include = [
|
||||
{
|
||||
model: Room,
|
||||
where: {
|
||||
isDeleted: 0,
|
||||
...(apartmentId ? { apartmentId } : {})
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const bills = await WaterBill.findAll({
|
||||
where,
|
||||
include,
|
||||
order: [['createTime', 'DESC']]
|
||||
});
|
||||
|
||||
const formattedBills = bills.map(formatWaterBillData);
|
||||
|
||||
res.status(200).json({
|
||||
code: 200,
|
||||
data: formattedBills,
|
||||
message: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ code: 500, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAllWaterBills,
|
||||
listWaterBills,
|
||||
getWaterBillById,
|
||||
createWaterBill,
|
||||
updateWaterBill,
|
||||
deleteWaterBill
|
||||
};
|
||||
|
|
@ -134,14 +134,6 @@ INSERT IGNORE INTO `menus` (`id`, `parentId`, `name`, `code`, `type`, `path`, `c
|
|||
INSERT IGNORE INTO `menus` (`id`, `name`, `code`, `type`, `path`, `component`, `icon`, `sort`, `visible`, `status`, `isBasic`, `isDeleted`, `createTime`, `updateTime`) VALUES
|
||||
(13, '计费中心', 'billing_center', 'menu', '/billing/center', 'views/billing/BillingCenter', 'el-icon-wallet', 6, 'show', 'active', 1, 0, NOW(), NOW());
|
||||
|
||||
-- 7. 数据统计(父菜单)
|
||||
INSERT IGNORE INTO `menus` (`id`, `name`, `code`, `type`, `path`, `component`, `icon`, `sort`, `visible`, `status`, `isBasic`, `isDeleted`, `createTime`, `updateTime`) VALUES
|
||||
(14, '数据统计', 'statistics', 'menu', '/statistics', NULL, 'el-icon-s-data', 7, 'show', 'active', 1, 0, NOW(), NOW());
|
||||
|
||||
-- 7.1 收支统计
|
||||
INSERT IGNORE INTO `menus` (`id`, `parentId`, `name`, `code`, `type`, `path`, `component`, `icon`, `sort`, `visible`, `status`, `isBasic`, `isDeleted`, `createTime`, `updateTime`) VALUES
|
||||
(15, 14, '收支统计', 'finance_stats', 'menu', '/statistics/finance', 'views/statistics/Finance', 'el-icon-s-data', 1, 'show', 'active', 1, 0, NOW(), NOW());
|
||||
|
||||
-- 8. 系统设置(父菜单)
|
||||
INSERT IGNORE INTO `menus` (`id`, `name`, `code`, `type`, `path`, `component`, `icon`, `sort`, `visible`, `status`, `isBasic`, `isDeleted`, `createTime`, `updateTime`) VALUES
|
||||
(17, '系统设置', 'settings', 'menu', '/settings', NULL, 'el-icon-setting', 8, 'show', 'active', 1, 0, NOW(), NOW());
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const electricityBillController = require('../controllers/electricityBillController');
|
||||
|
||||
// 获取所有电费记录
|
||||
router.get('/', electricityBillController.getAllElectricityBills);
|
||||
|
||||
// 获取单个电费记录
|
||||
router.get('/:id', electricityBillController.getElectricityBillById);
|
||||
|
||||
// 创建电费记录
|
||||
router.post('/', electricityBillController.createElectricityBill);
|
||||
|
||||
// 更新电费记录
|
||||
router.put('/:id', electricityBillController.updateElectricityBill);
|
||||
|
||||
// 删除电费记录
|
||||
router.delete('/:id', electricityBillController.deleteElectricityBill);
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const waterBillController = require('../controllers/waterBillController');
|
||||
|
||||
// 获取所有水费记录(分页)
|
||||
router.get('/', waterBillController.getAllWaterBills);
|
||||
|
||||
// 获取所有水费记录(不分页)
|
||||
router.get('/list', waterBillController.listWaterBills);
|
||||
|
||||
// 获取单个水费记录
|
||||
router.get('/:id', waterBillController.getWaterBillById);
|
||||
|
||||
// 创建水费记录
|
||||
router.post('/', waterBillController.createWaterBill);
|
||||
|
||||
// 更新水费记录
|
||||
router.put('/:id', waterBillController.updateWaterBill);
|
||||
|
||||
// 删除水费记录
|
||||
router.delete('/:id', waterBillController.deleteWaterBill);
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* 统一响应工具函数
|
||||
* 规范所有接口的返回数据格式
|
||||
*/
|
||||
|
||||
/**
|
||||
* 成功响应
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 成功消息
|
||||
* @param {any} data - 响应数据
|
||||
* @param {number} statusCode - HTTP状态码,默认200
|
||||
*/
|
||||
const success = (res, message = '操作成功', data = null, statusCode = 200) => {
|
||||
res.status(statusCode).json({
|
||||
code: 200,
|
||||
message,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 错误响应
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 错误消息
|
||||
* @param {number} code - 错误码,默认500
|
||||
* @param {number} statusCode - HTTP状态码,默认对应code
|
||||
*/
|
||||
const error = (res, message = '操作失败', code = 500, statusCode = null) => {
|
||||
const httpStatus = statusCode || code;
|
||||
res.status(httpStatus).json({
|
||||
code,
|
||||
message,
|
||||
data: null
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 参数错误响应 (400)
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 错误消息
|
||||
*/
|
||||
const badRequest = (res, message = '请求参数错误') => {
|
||||
error(res, message, 400);
|
||||
};
|
||||
|
||||
/**
|
||||
* 未授权响应 (401)
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 错误消息
|
||||
*/
|
||||
const unauthorized = (res, message = '未授权,请先登录') => {
|
||||
error(res, message, 401);
|
||||
};
|
||||
|
||||
/**
|
||||
* 禁止访问响应 (403)
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 错误消息
|
||||
*/
|
||||
const forbidden = (res, message = '没有权限执行此操作') => {
|
||||
error(res, message, 403);
|
||||
};
|
||||
|
||||
/**
|
||||
* 资源不存在响应 (404)
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 错误消息
|
||||
*/
|
||||
const notFound = (res, message = '资源不存在') => {
|
||||
error(res, message, 404);
|
||||
};
|
||||
|
||||
/**
|
||||
* 服务器错误响应 (500)
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 错误消息
|
||||
* @param {Error} err - 错误对象(仅在开发环境返回)
|
||||
*/
|
||||
const serverError = (res, message = '服务器内部错误', err = null) => {
|
||||
const response = {
|
||||
code: 500,
|
||||
message,
|
||||
data: null
|
||||
};
|
||||
|
||||
// 开发环境下返回错误详情
|
||||
if (process.env.NODE_ENV === 'development' && err) {
|
||||
response.error = err.message;
|
||||
response.stack = err.stack;
|
||||
}
|
||||
|
||||
res.status(500).json(response);
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建成功响应 (201)
|
||||
* @param {object} res - Express响应对象
|
||||
* @param {string} message - 成功消息
|
||||
* @param {any} data - 响应数据
|
||||
*/
|
||||
const created = (res, message = '创建成功', data = null) => {
|
||||
success(res, message, data, 201);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
success,
|
||||
error,
|
||||
badRequest,
|
||||
unauthorized,
|
||||
forbidden,
|
||||
notFound,
|
||||
serverError,
|
||||
created
|
||||
};
|
||||
Loading…
Reference in New Issue