304 lines
8.9 KiB
JavaScript
304 lines
8.9 KiB
JavaScript
const { Room, Rental, Apartment, Region } = require('../models');
|
||
const { Op } = require('sequelize');
|
||
|
||
// 租金统计
|
||
const getRentStatistics = async (req, res) => {
|
||
try {
|
||
// 计算过去12个月的开始日期
|
||
const now = new Date();
|
||
const startDate = new Date(now.getFullYear(), now.getMonth() - 11, 1); // 12个月前的第一天
|
||
|
||
// 初始化过去12个月的数据
|
||
const monthlyRent = {};
|
||
for (let i = 0; i < 12; i++) {
|
||
const date = new Date(now.getFullYear(), now.getMonth() - i, 1);
|
||
const monthKey = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`;
|
||
monthlyRent[monthKey] = 0;
|
||
}
|
||
|
||
// 从数据库查询过去12个月的租赁记录(排除已删除的)
|
||
const rentals = await Rental.findAll({
|
||
where: {
|
||
createTime: {
|
||
[Op.gte]: startDate
|
||
},
|
||
isDeleted: 0
|
||
}
|
||
});
|
||
|
||
// 按月份统计已收租金
|
||
rentals.forEach(rental => {
|
||
// 检查租金是否有效
|
||
const rentAmount = parseFloat(rental.rent) || 0;
|
||
if (rentAmount > 0 && rental.createTime) {
|
||
// 解析创建时间
|
||
const createDate = new Date(rental.createTime);
|
||
const monthKey = `${createDate.getFullYear()}-${(createDate.getMonth() + 1).toString().padStart(2, '0')}`;
|
||
|
||
// 如果该月份在我们的统计范围内,添加租金
|
||
if (monthlyRent.hasOwnProperty(monthKey)) {
|
||
monthlyRent[monthKey] += rentAmount;
|
||
}
|
||
}
|
||
});
|
||
|
||
// 转换为数组格式并按月份倒序排序
|
||
const rentStatistics = Object.entries(monthlyRent)
|
||
.map(([month, amount]) => ({
|
||
month,
|
||
amount: Math.round(amount * 100) / 100 // 保留两位小数
|
||
}))
|
||
.sort((a, b) => b.month.localeCompare(a.month));
|
||
|
||
res.status(200).json(rentStatistics);
|
||
} catch (error) {
|
||
console.error('获取租金统计数据时出错:', error);
|
||
res.status(500).json({ error: error.message });
|
||
}
|
||
};
|
||
|
||
// 房间状态统计
|
||
const getRoomStatusStatistics = async (req, res) => {
|
||
try {
|
||
// 获取所有房间(排除已删除的)
|
||
const rooms = await Room.findAll({ where: { isDeleted: 0 } });
|
||
|
||
// 初始化统计数据
|
||
let empty = 0;
|
||
let reserved = 0;
|
||
let rented = 0;
|
||
let soon_expire = 0;
|
||
let expired = 0;
|
||
let cleaning = 0;
|
||
let maintenance = 0;
|
||
|
||
// 统计各状态房间数量
|
||
rooms.forEach(room => {
|
||
if (room.status === 'empty') {
|
||
empty++;
|
||
} else if (room.status === 'reserved') {
|
||
reserved++;
|
||
} else if (room.status === 'rented') {
|
||
rented++;
|
||
// 统计附属状态
|
||
if (room.subStatus === 'soon_expire') {
|
||
soon_expire++;
|
||
} else if (room.subStatus === 'expired') {
|
||
expired++;
|
||
}
|
||
// 统计其他状态
|
||
if (room.otherStatus === 'cleaning') {
|
||
cleaning++;
|
||
} else if (room.otherStatus === 'maintenance') {
|
||
maintenance++;
|
||
}
|
||
}
|
||
});
|
||
|
||
const roomStatusStatistics = [
|
||
{ status: '空房', count: empty },
|
||
{ status: '预订', count: reserved },
|
||
{ status: '在租', count: rented },
|
||
{ status: '即将到期', count: soon_expire },
|
||
{ status: '到期', count: expired },
|
||
{ status: '打扫中', count: cleaning },
|
||
{ status: '维修中', count: maintenance }
|
||
];
|
||
|
||
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({
|
||
where: { isDeleted: 0 },
|
||
include: [
|
||
{
|
||
model: Apartment,
|
||
where: { isDeleted: 0 },
|
||
include: [{
|
||
model: Room,
|
||
where: { isDeleted: 0 }
|
||
}]
|
||
}
|
||
]
|
||
});
|
||
|
||
const regionHouseStatistics = regions.map(region => {
|
||
let empty = 0;
|
||
let reserved = 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 => {
|
||
if (room.status === 'empty') {
|
||
empty++;
|
||
} else if (room.status === 'reserved') {
|
||
reserved++;
|
||
} else if (room.status === 'rented') {
|
||
rented++;
|
||
// 统计附属状态
|
||
if (room.subStatus === 'soon_expire') {
|
||
soon_expire++;
|
||
} else if (room.subStatus === 'expired') {
|
||
expired++;
|
||
}
|
||
// 统计其他状态
|
||
if (room.otherStatus === 'cleaning') {
|
||
cleaning++;
|
||
} else if (room.otherStatus === 'maintenance') {
|
||
maintenance++;
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
return {
|
||
region: region.name,
|
||
empty,
|
||
reserved,
|
||
rented,
|
||
soon_expire,
|
||
expired,
|
||
cleaning,
|
||
maintenance,
|
||
total: empty + reserved + rented
|
||
};
|
||
});
|
||
|
||
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({
|
||
where: { isDeleted: 0 },
|
||
include: [
|
||
{
|
||
model: Apartment,
|
||
where: { isDeleted: 0 },
|
||
include: [{
|
||
model: Room,
|
||
where: { isDeleted: 0 }
|
||
}]
|
||
}
|
||
]
|
||
});
|
||
|
||
const apartmentHouseStatistics = [];
|
||
|
||
regions.forEach(region => {
|
||
region.Apartments.forEach(apartment => {
|
||
let empty = 0;
|
||
let reserved = 0;
|
||
let rented = 0;
|
||
let soon_expire = 0;
|
||
let expired = 0;
|
||
let cleaning = 0;
|
||
let maintenance = 0;
|
||
|
||
apartment.Rooms.forEach(room => {
|
||
if (room.status === 'empty') {
|
||
empty++;
|
||
} else if (room.status === 'reserved') {
|
||
reserved++;
|
||
} else if (room.status === 'rented') {
|
||
rented++;
|
||
// 统计附属状态
|
||
if (room.subStatus === 'soon_expire') {
|
||
soon_expire++;
|
||
} else if (room.subStatus === 'expired') {
|
||
expired++;
|
||
}
|
||
// 统计其他状态
|
||
if (room.otherStatus === 'cleaning') {
|
||
cleaning++;
|
||
} else if (room.otherStatus === 'maintenance') {
|
||
maintenance++;
|
||
}
|
||
}
|
||
});
|
||
|
||
apartmentHouseStatistics.push({
|
||
region: region.name,
|
||
apartment: apartment.name,
|
||
empty,
|
||
reserved,
|
||
rented,
|
||
soon_expire,
|
||
expired,
|
||
cleaning,
|
||
maintenance,
|
||
total: empty + reserved + rented
|
||
});
|
||
});
|
||
});
|
||
|
||
res.status(200).json(apartmentHouseStatistics);
|
||
} catch (error) {
|
||
res.status(500).json({ error: error.message });
|
||
}
|
||
};
|
||
|
||
// Dashboard统计数据
|
||
const getDashboardStatistics = async (req, res) => {
|
||
try {
|
||
// 导入所有需要的模型
|
||
const { Region, Apartment, Room, WaterBill, Rental } = require('../models');
|
||
|
||
// 并行查询所有统计数据
|
||
const [regionCount, apartmentCount, roomCount, emptyRoomCount, reservedRoomCount, rentedRoomCount, soonExpireRoomCount, expiredRoomCount, collectedRentAmount, collectedWaterAmount] = await Promise.all([
|
||
Region.count({ where: { isDeleted: 0 } }),
|
||
Apartment.count({ where: { isDeleted: 0 } }),
|
||
Room.count({ where: { isDeleted: 0 } }),
|
||
Room.count({ where: { status: 'empty', isDeleted: 0 } }),
|
||
Room.count({ where: { status: 'reserved', isDeleted: 0 } }),
|
||
Room.count({ where: { status: 'rented', isDeleted: 0 } }),
|
||
Room.count({ where: { status: 'rented', subStatus: 'soon_expire', isDeleted: 0 } }),
|
||
Room.count({ where: { status: 'rented', subStatus: 'expired', isDeleted: 0 } }),
|
||
// 统计已收租金(排除已删除的)
|
||
Rental.sum('rent', { where: { isDeleted: 0 } }),
|
||
// 统计已收水费(排除已删除的)
|
||
WaterBill.sum('amount', { where: { status: 'paid', isDeleted: 0 } })
|
||
]);
|
||
|
||
// 构造响应数据
|
||
const dashboardStatistics = {
|
||
regionCount,
|
||
apartmentCount,
|
||
roomCount,
|
||
emptyRoomCount,
|
||
reservedRoomCount,
|
||
rentedRoomCount,
|
||
soonExpireRoomCount,
|
||
expiredRoomCount,
|
||
collectedRentAmount: parseFloat(collectedRentAmount) || 0,
|
||
collectedWaterAmount: parseFloat(collectedWaterAmount) || 0
|
||
};
|
||
|
||
res.status(200).json(dashboardStatistics);
|
||
} catch (error) {
|
||
console.error('获取Dashboard统计数据时出错:', error);
|
||
res.status(500).json({ error: error.message });
|
||
}
|
||
};
|
||
|
||
module.exports = {
|
||
getRentStatistics,
|
||
getRoomStatusStatistics,
|
||
getRegionHouseStatistics,
|
||
getRegionApartmentHouseStatistics,
|
||
getDashboardStatistics
|
||
}; |