225 lines
6.3 KiB
JavaScript
225 lines
6.3 KiB
JavaScript
|
|
const { Room, Rental, Apartment, Region } = require('../models');
|
||
|
|
const { Op } = require('sequelize');
|
||
|
|
|
||
|
|
// 租金统计
|
||
|
|
const getRentStatistics = async (req, res) => {
|
||
|
|
try {
|
||
|
|
// 获取当前年份
|
||
|
|
const currentYear = new Date().getFullYear();
|
||
|
|
|
||
|
|
// 从数据库查询所有租房记录(包括活跃和已到期的)
|
||
|
|
const rentals = await Rental.findAll({
|
||
|
|
include: [Room]
|
||
|
|
});
|
||
|
|
|
||
|
|
// 按月份统计租金
|
||
|
|
const monthlyRent = {};
|
||
|
|
|
||
|
|
// 初始化12个月的数据
|
||
|
|
for (let i = 1; i <= 12; i++) {
|
||
|
|
const monthKey = `${currentYear}-${i.toString().padStart(2, '0')}`;
|
||
|
|
monthlyRent[monthKey] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 计算每个月的租金收入
|
||
|
|
rentals.forEach(rental => {
|
||
|
|
if (rental.Room) {
|
||
|
|
// 检查租金是否有效
|
||
|
|
const rentAmount = parseFloat(rental.rent) || 0;
|
||
|
|
if (rentAmount > 0 && rental.startDate && rental.endDate) {
|
||
|
|
// 解析开始和结束日期
|
||
|
|
const startDate = new Date(rental.startDate);
|
||
|
|
const endDate = new Date(rental.endDate);
|
||
|
|
|
||
|
|
// 计算当前年份的开始和结束日期
|
||
|
|
const yearStart = new Date(currentYear, 0, 1); // 1月1日
|
||
|
|
const yearEnd = new Date(currentYear, 11, 31); // 12月31日
|
||
|
|
|
||
|
|
// 确定实际的开始和结束日期(考虑年份范围)
|
||
|
|
const actualStart = startDate > yearStart ? startDate : yearStart;
|
||
|
|
const actualEnd = endDate < yearEnd ? endDate : yearEnd;
|
||
|
|
|
||
|
|
// 如果实际开始日期晚于实际结束日期,跳过
|
||
|
|
if (actualStart > actualEnd) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 遍历当前年份的每个月
|
||
|
|
for (let i = 1; i <= 12; i++) {
|
||
|
|
const monthKey = `${currentYear}-${i.toString().padStart(2, '0')}`;
|
||
|
|
const monthStart = new Date(currentYear, i - 1, 1); // 当月1日
|
||
|
|
const monthEnd = new Date(currentYear, i, 0); // 当月最后一天
|
||
|
|
|
||
|
|
// 检查租赁期是否与当前月份重叠
|
||
|
|
if (actualStart <= monthEnd && actualEnd >= monthStart) {
|
||
|
|
// 如果重叠,添加当月租金
|
||
|
|
monthlyRent[monthKey] += rentAmount;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// 转换为数组格式
|
||
|
|
const rentStatistics = Object.entries(monthlyRent).map(([month, amount]) => ({
|
||
|
|
month,
|
||
|
|
amount: Math.round(amount * 100) / 100 // 保留两位小数
|
||
|
|
}));
|
||
|
|
|
||
|
|
res.status(200).json(rentStatistics);
|
||
|
|
} catch (error) {
|
||
|
|
console.error('获取租金统计数据时出错:', error);
|
||
|
|
res.status(500).json({ error: error.message });
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 房间状态统计
|
||
|
|
const getRoomStatusStatistics = async (req, res) => {
|
||
|
|
try {
|
||
|
|
const statusCounts = await Room.count({
|
||
|
|
group: ['status']
|
||
|
|
});
|
||
|
|
|
||
|
|
const statusMap = {
|
||
|
|
empty: '空房',
|
||
|
|
rented: '在租',
|
||
|
|
soon_expire: '即将到期',
|
||
|
|
expired: '到期',
|
||
|
|
cleaning: '打扫中',
|
||
|
|
maintenance: '维修中'
|
||
|
|
};
|
||
|
|
|
||
|
|
const roomStatusStatistics = Object.entries(statusMap).map(([status, label]) => {
|
||
|
|
const count = statusCounts.find(item => item.status === status)?.count || 0;
|
||
|
|
return { status: label, count };
|
||
|
|
});
|
||
|
|
|
||
|
|
res.status(200).json(roomStatusStatistics);
|
||
|
|
} catch (error) {
|
||
|
|
res.status(500).json({ error: error.message });
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 区域房屋统计
|
||
|
|
const getRegionHouseStatistics = async (req, res) => {
|
||
|
|
try {
|
||
|
|
const regions = await Region.findAll({
|
||
|
|
include: [
|
||
|
|
{
|
||
|
|
model: Apartment,
|
||
|
|
include: [Room]
|
||
|
|
}
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
const regionHouseStatistics = regions.map(region => {
|
||
|
|
let empty = 0;
|
||
|
|
let rented = 0;
|
||
|
|
let soon_expire = 0;
|
||
|
|
let expired = 0;
|
||
|
|
let cleaning = 0;
|
||
|
|
let maintenance = 0;
|
||
|
|
|
||
|
|
region.Apartments.forEach(apartment => {
|
||
|
|
apartment.Rooms.forEach(room => {
|
||
|
|
switch (room.status) {
|
||
|
|
case 'empty': empty++;
|
||
|
|
break;
|
||
|
|
case 'rented': rented++;
|
||
|
|
break;
|
||
|
|
case 'soon_expire': soon_expire++;
|
||
|
|
break;
|
||
|
|
case 'expired': expired++;
|
||
|
|
break;
|
||
|
|
case 'cleaning': cleaning++;
|
||
|
|
break;
|
||
|
|
case 'maintenance': maintenance++;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return {
|
||
|
|
region: region.name,
|
||
|
|
empty,
|
||
|
|
rented,
|
||
|
|
soon_expire,
|
||
|
|
expired,
|
||
|
|
cleaning,
|
||
|
|
maintenance,
|
||
|
|
total: empty + rented + soon_expire + expired + cleaning + maintenance
|
||
|
|
};
|
||
|
|
});
|
||
|
|
|
||
|
|
res.status(200).json(regionHouseStatistics);
|
||
|
|
} catch (error) {
|
||
|
|
res.status(500).json({ error: error.message });
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 区域公寓房间状态分布
|
||
|
|
const getRegionApartmentHouseStatistics = async (req, res) => {
|
||
|
|
try {
|
||
|
|
const regions = await Region.findAll({
|
||
|
|
include: [
|
||
|
|
{
|
||
|
|
model: Apartment,
|
||
|
|
include: [Room]
|
||
|
|
}
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
const apartmentHouseStatistics = [];
|
||
|
|
|
||
|
|
regions.forEach(region => {
|
||
|
|
region.Apartments.forEach(apartment => {
|
||
|
|
let empty = 0;
|
||
|
|
let rented = 0;
|
||
|
|
let soon_expire = 0;
|
||
|
|
let expired = 0;
|
||
|
|
let cleaning = 0;
|
||
|
|
let maintenance = 0;
|
||
|
|
|
||
|
|
apartment.Rooms.forEach(room => {
|
||
|
|
switch (room.status) {
|
||
|
|
case 'empty': empty++;
|
||
|
|
break;
|
||
|
|
case 'rented': rented++;
|
||
|
|
break;
|
||
|
|
case 'soon_expire': soon_expire++;
|
||
|
|
break;
|
||
|
|
case 'expired': expired++;
|
||
|
|
break;
|
||
|
|
case 'cleaning': cleaning++;
|
||
|
|
break;
|
||
|
|
case 'maintenance': maintenance++;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
apartmentHouseStatistics.push({
|
||
|
|
region: region.name,
|
||
|
|
apartment: apartment.name,
|
||
|
|
empty,
|
||
|
|
rented,
|
||
|
|
soon_expire,
|
||
|
|
expired,
|
||
|
|
cleaning,
|
||
|
|
maintenance,
|
||
|
|
total: empty + rented + soon_expire + expired + cleaning + maintenance
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
res.status(200).json(apartmentHouseStatistics);
|
||
|
|
} catch (error) {
|
||
|
|
res.status(500).json({ error: error.message });
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
module.exports = {
|
||
|
|
getRentStatistics,
|
||
|
|
getRoomStatusStatistics,
|
||
|
|
getRegionHouseStatistics,
|
||
|
|
getRegionApartmentHouseStatistics
|
||
|
|
};
|