const { Tenant, User, Apartment, Room, Category, Setting } = require('../models'); const bcrypt = require('bcryptjs'); // 格式化日期时间(年月日时分秒) const formatDateTime = (date) => { if (!date) return null; const dateObj = date instanceof Date ? date : new Date(date); if (isNaN(dateObj.getTime())) return null; const beijingDate = new Date(dateObj.getTime() + 8 * 60 * 60 * 1000); return beijingDate.toISOString().replace('T', ' ').slice(0, 19); }; // 格式化租户数据 const formatTenantData = (tenant) => { const data = tenant.toJSON ? tenant.toJSON() : tenant; return { ...data, createTime: formatDateTime(data.createTime), updateTime: formatDateTime(data.updateTime) }; }; // 获取租户列表(超级管理员) const getTenantList = async (req, res) => { try { const { page = 1, pageSize = 10, keyword, status } = req.query; const offset = (page - 1) * pageSize; const where = { isDeleted: 0 }; if (keyword) { where.code = { [require('sequelize').Op.like]: `%${keyword}%` }; } if (status) { where.status = status; } const { count, rows } = await Tenant.findAndCountAll({ where, limit: parseInt(pageSize), offset: parseInt(offset), order: [['createTime', 'DESC']] }); res.json({ code: 200, data: { list: rows, total: count, page: parseInt(page), pageSize: parseInt(pageSize) }, message: '获取成功' }); } catch (error) { console.error('获取租户列表失败:', error); res.status(500).json({ code: 500, message: '获取租户列表失败', error: error.message }); } }; // 获取租户详情 const getTenantDetail = async (req, res) => { try { const { id } = req.params; const tenant = await Tenant.findOne({ where: { id, isDeleted: 0 } }); if (!tenant) { return res.status(404).json({ code: 404, message: '租户不存在' }); } // 获取租户统计数据 const userCount = await User.count({ where: { tenantId: id, isDeleted: 0 } }); const apartmentCount = await Apartment.count({ where: { tenantId: id, isDeleted: 0 } }); const roomCount = await Room.count({ where: { tenantId: id, isDeleted: 0 } }); res.json({ code: 200, data: { ...formatTenantData(tenant), stats: { userCount, apartmentCount, roomCount } }, message: '获取成功' }); } catch (error) { console.error('获取租户详情失败:', error); res.status(500).json({ code: 500, message: '获取租户详情失败', error: error.message }); } }; // 创建租户 const createTenant = async (req, res) => { try { const { code, description, contactName, contactPhone, contactEmail, maxUsers, maxApartments, maxRooms, adminUsername, adminPassword } = req.body; // 检查租户编码是否已存在 const existingTenant = await Tenant.findOne({ where: { code } }); if (existingTenant) { return res.status(400).json({ code: 400, message: '租户编码已存在' }); } // 创建租户 const tenant = await Tenant.create({ code, description, contactName, contactPhone, contactEmail, maxUsers: maxUsers || 10, maxApartments: maxApartments || 5, maxRooms: maxRooms || 50, status: 'active', createBy: req.user.id }); // 创建租户管理员账号 if (adminUsername && adminPassword) { const hashedPassword = await bcrypt.hash(adminPassword, 10); await User.create({ username: adminUsername, password: hashedPassword, nickname: '管理员', tenantId: tenant.id, userType: 'tenant_admin', status: 'active', createBy: req.user.id }); } // 初始化默认收支类目 const defaultCategories = [ // 收入类目 { name: '租金', code: 'rent', type: 'income', sort: 1 }, { name: '水费', code: 'water', type: 'income', sort: 2 }, { name: '电费', code: 'electricity', type: 'income', sort: 3 }, { name: '燃气费', code: 'gas', type: 'income', sort: 4 }, { name: '押金', code: 'deposit', type: 'income', sort: 5 }, { name: '物业费', code: 'property_fee', type: 'income', sort: 6 }, { name: '违约金', code: 'penalty', type: 'income', sort: 7 }, { name: '其他收入', code: 'other_income', type: 'income', sort: 8 }, // 支出类目 { name: '维修费', code: 'maintenance', type: 'expense', sort: 1 }, { name: '中介费', code: 'agency_fee', type: 'expense', sort: 2 }, { name: '物业费', code: 'property_fee_expense', type: 'expense', sort: 3 }, { name: '水费', code: 'water_expense', type: 'expense', sort: 4 }, { name: '电费', code: 'electricity_expense', type: 'expense', sort: 5 }, { name: '燃气费', code: 'gas_expense', type: 'expense', sort: 6 }, { name: '装修费', code: 'renovation', type: 'expense', sort: 7 }, { name: '其他支出', code: 'other_expense', type: 'expense', sort: 8 } ]; for (const category of defaultCategories) { await Category.create({ ...category, tenantId: tenant.id, status: 'active', isDefault: 1, createBy: req.user.id }); } // 初始化默认系统设置 const defaultSettings = [ { key: 'expireReminderDays', value: '30', description: '房间到期提前提醒天数' } ]; for (const setting of defaultSettings) { await Setting.create({ ...setting, tenantId: tenant.id, createBy: req.user.id }); } res.json({ code: 200, data: tenant, message: '租户创建成功' }); } catch (error) { console.error('创建租户失败:', error); res.status(500).json({ code: 500, message: '创建租户失败', error: error.message }); } }; // 更新租户 const updateTenant = async (req, res) => { try { const { id } = req.params; const updateData = req.body; const tenant = await Tenant.findOne({ where: { id, isDeleted: 0 } }); if (!tenant) { return res.status(404).json({ code: 404, message: '租户不存在' }); } // 不允许修改租户编码 delete updateData.code; delete updateData.id; updateData.updateBy = req.user.id; await tenant.update(updateData); res.json({ code: 200, data: tenant, message: '租户更新成功' }); } catch (error) { console.error('更新租户失败:', error); res.status(500).json({ code: 500, message: '更新租户失败', error: error.message }); } }; // 删除租户 const deleteTenant = async (req, res) => { try { const { id } = req.params; const tenant = await Tenant.findOne({ where: { id, isDeleted: 0 } }); if (!tenant) { return res.status(404).json({ code: 404, message: '租户不存在' }); } await tenant.update({ isDeleted: 1, updateBy: req.user.id }); res.json({ code: 200, message: '租户删除成功' }); } catch (error) { console.error('删除租户失败:', error); res.status(500).json({ code: 500, message: '删除租户失败', error: error.message }); } }; // 获取当前租户信息 const getCurrentTenant = async (req, res) => { try { const tenantId = req.tenantId; const tenant = await Tenant.findOne({ where: { id: tenantId, isDeleted: 0 } }); if (!tenant) { return res.status(404).json({ code: 404, message: '租户不存在' }); } // 获取租户统计数据 const userCount = await User.count({ where: { tenantId, isDeleted: 0 } }); const apartmentCount = await Apartment.count({ where: { tenantId, isDeleted: 0 } }); const roomCount = await Room.count({ where: { tenantId, isDeleted: 0 } }); res.json({ code: 200, data: { ...formatTenantData(tenant), stats: { userCount, apartmentCount, roomCount } }, message: '获取成功' }); } catch (error) { console.error('获取当前租户信息失败:', error); res.status(500).json({ code: 500, message: '获取当前租户信息失败', error: error.message }); } }; // 更新当前租户信息 const updateCurrentTenant = async (req, res) => { try { const tenantId = req.tenantId; const updateData = req.body; const tenant = await Tenant.findOne({ where: { id: tenantId, isDeleted: 0 } }); if (!tenant) { return res.status(404).json({ code: 404, message: '租户不存在' }); } // 只允许修改特定字段 const allowedFields = ['description', 'contactName', 'contactPhone', 'contactEmail', 'logo']; const filteredData = {}; allowedFields.forEach(field => { if (updateData[field] !== undefined) { filteredData[field] = updateData[field]; } }); filteredData.updateBy = req.user.id; await tenant.update(filteredData); res.json({ code: 200, data: tenant, message: '租户信息更新成功' }); } catch (error) { console.error('更新当前租户信息失败:', error); res.status(500).json({ code: 500, message: '更新当前租户信息失败', error: error.message }); } }; module.exports = { getTenantList, getTenantDetail, createTenant, updateTenant, deleteTenant, getCurrentTenant, updateCurrentTenant };