This commit is contained in:
wangxiaoxian 2026-03-03 23:36:48 +08:00
parent f912a0373d
commit 79160aae9b
22 changed files with 516 additions and 99 deletions

53
add_fields.js Normal file
View File

@ -0,0 +1,53 @@
const mysql = require('mysql2/promise');
async function addFields() {
try {
// 连接到数据库
const connection = await mysql.createConnection({
host: '8.152.207.41',
user: 'rentease',
password: 'Wxx@123!',
database: 'rentease'
});
console.log('成功连接到数据库');
// 检查 subStatus 字段是否存在
const [subStatusResult] = await connection.query(`
SHOW COLUMNS FROM rooms LIKE 'subStatus'
`);
// 如果 subStatus 字段不存在,则添加
if (subStatusResult.length === 0) {
await connection.query(`
ALTER TABLE rooms ADD COLUMN subStatus ENUM('normal', 'soon_expire', 'expired') NOT NULL DEFAULT 'normal'
`);
console.log('添加 subStatus 字段成功');
} else {
console.log('subStatus 字段已存在');
}
// 检查 otherStatus 字段是否存在
const [otherStatusResult] = await connection.query(`
SHOW COLUMNS FROM rooms LIKE 'otherStatus'
`);
// 如果 otherStatus 字段不存在,则添加
if (otherStatusResult.length === 0) {
await connection.query(`
ALTER TABLE rooms ADD COLUMN otherStatus ENUM('', 'cleaning', 'maintenance') NOT NULL DEFAULT ''
`);
console.log('添加 otherStatus 字段成功');
} else {
console.log('otherStatus 字段已存在');
}
// 关闭连接
await connection.end();
console.log('数据库连接已关闭');
} catch (error) {
console.error('添加字段时出错:', error);
}
}
addFields();

31
add_fields.sql Normal file
View File

@ -0,0 +1,31 @@
-- 为 rooms 表添加字段
ALTER TABLE rooms ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE rooms ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 tenants 表添加字段
ALTER TABLE tenants ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE tenants ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 regions 表添加字段
ALTER TABLE regions ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE regions ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 apartments 表添加字段
ALTER TABLE apartments ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE apartments ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 contracts 表添加字段
ALTER TABLE contracts ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE contracts ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 rentals 表添加字段
ALTER TABLE rentals ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE rentals ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 water_bills 表添加字段
ALTER TABLE water_bills ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE water_bills ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;
-- 为 electricity_bills 表添加字段
ALTER TABLE electricity_bills ADD COLUMN updateTime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE electricity_bills ADD COLUMN isDeleted INT NOT NULL DEFAULT 0;

View File

@ -6,7 +6,7 @@ const createDatabase = async () => {
try {
// 连接到MySQL服务器
const connection = await mysql.createConnection({
host: 'localhost',
host: '8.152.207.41',
user: 'rentease',
password: 'Wxx@123!'
});
@ -28,7 +28,7 @@ const sequelize = new Sequelize(
'rentease', // 用户名
'Wxx@123!', // 密码
{
host: 'localhost',
host: '8.152.207.41',
dialect: 'mysql',
logging: false,
timezone: '+08:00'
@ -45,7 +45,7 @@ const testConnection = async () => {
'rentease', // 用户名
'Wxx@123!', // 密码
{
host: 'localhost',
host: '8.152.207.41',
dialect: 'mysql',
logging: false,
timezone: '+08:00'

View File

@ -13,14 +13,16 @@ const formatDate = (date) => {
const formatApartmentData = (apartment) => {
const formattedApartment = {
...apartment.toJSON(),
createTime: formatDate(apartment.createTime)
createTime: formatDate(apartment.createTime),
updateTime: formatDate(apartment.updateTime)
};
// 格式化关联数据
if (formattedApartment.Region) {
formattedApartment.Region = {
...formattedApartment.Region,
createTime: formatDate(formattedApartment.Region.createTime)
createTime: formatDate(formattedApartment.Region.createTime),
updateTime: formatDate(formattedApartment.Region.updateTime)
};
}
@ -33,7 +35,7 @@ const getAllApartments = async (req, res) => {
const { regionId, name, page = 1, pageSize = 10 } = req.query;
// 构建查询条件
const where = {};
const where = { isDeleted: 0 };
if (regionId) {
where.regionId = regionId;
}
@ -73,7 +75,8 @@ const getAllApartments = async (req, res) => {
const getApartmentById = async (req, res) => {
try {
const { id } = req.params;
const apartment = await Apartment.findByPk(id, {
const apartment = await Apartment.findOne({
where: { id, isDeleted: 0 },
include: [Region]
});
if (!apartment) {
@ -102,7 +105,9 @@ const updateApartment = async (req, res) => {
try {
const { id } = req.params;
const { regionId, name, address } = req.body;
const apartment = await Apartment.findByPk(id);
const apartment = await Apartment.findOne({
where: { id, isDeleted: 0 }
});
if (!apartment) {
return res.status(404).json({ error: '公寓不存在' });
}
@ -113,15 +118,17 @@ const updateApartment = async (req, res) => {
}
};
// 删除公寓
// 删除公寓(软删除)
const deleteApartment = async (req, res) => {
try {
const { id } = req.params;
const apartment = await Apartment.findByPk(id);
const apartment = await Apartment.findOne({
where: { id, isDeleted: 0 }
});
if (!apartment) {
return res.status(404).json({ error: '公寓不存在' });
}
await apartment.destroy();
await apartment.update({ isDeleted: 1 });
res.status(200).json({ message: '公寓删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -14,26 +14,30 @@ const formatContractData = (contract) => {
...contract.toJSON(),
startDate: formatDate(contract.startDate),
endDate: formatDate(contract.endDate),
createTime: formatDate(contract.createTime)
createTime: formatDate(contract.createTime),
updateTime: formatDate(contract.updateTime)
};
// 格式化关联数据
if (formattedContract.Room) {
formattedContract.Room = {
...formattedContract.Room,
createTime: formatDate(formattedContract.Room.createTime)
createTime: formatDate(formattedContract.Room.createTime),
updateTime: formatDate(formattedContract.Room.updateTime)
};
if (formattedContract.Room.Apartment) {
formattedContract.Room.Apartment = {
...formattedContract.Room.Apartment,
createTime: formatDate(formattedContract.Room.Apartment.createTime)
createTime: formatDate(formattedContract.Room.Apartment.createTime),
updateTime: formatDate(formattedContract.Room.Apartment.updateTime)
};
if (formattedContract.Room.Apartment.Region) {
formattedContract.Room.Apartment.Region = {
...formattedContract.Room.Apartment.Region,
createTime: formatDate(formattedContract.Room.Apartment.Region.createTime)
createTime: formatDate(formattedContract.Room.Apartment.Region.createTime),
updateTime: formatDate(formattedContract.Room.Apartment.Region.updateTime)
};
}
}
@ -42,7 +46,8 @@ const formatContractData = (contract) => {
if (formattedContract.Tenant) {
formattedContract.Tenant = {
...formattedContract.Tenant,
createTime: formatDate(formattedContract.Tenant.createTime)
createTime: formatDate(formattedContract.Tenant.createTime),
updateTime: formatDate(formattedContract.Tenant.updateTime)
};
}
@ -53,17 +58,28 @@ const formatContractData = (contract) => {
const getAllContracts = async (req, res) => {
try {
const contracts = await Contract.findAll({
where: { isDeleted: 0 },
include: [
{
model: Room,
where: { isDeleted: 0 },
include: [
{
model: Apartment,
include: [Region]
where: { isDeleted: 0 },
include: [
{
model: Region,
where: { isDeleted: 0 }
}
]
}
]
},
Tenant
{
model: Tenant,
where: { isDeleted: 0 }
}
]
});
const formattedContracts = contracts.map(formatContractData);
@ -77,18 +93,29 @@ const getAllContracts = async (req, res) => {
const getContractById = async (req, res) => {
try {
const { id } = req.params;
const contract = await Contract.findByPk(id, {
const contract = await Contract.findOne({
where: { id, isDeleted: 0 },
include: [
{
model: Room,
where: { isDeleted: 0 },
include: [
{
model: Apartment,
include: [Region]
where: { isDeleted: 0 },
include: [
{
model: Region,
where: { isDeleted: 0 }
}
]
}
]
},
Tenant
{
model: Tenant,
where: { isDeleted: 0 }
}
]
});
if (!contract) {
@ -117,7 +144,9 @@ const updateContract = async (req, res) => {
try {
const { id } = req.params;
const { roomId, tenantId, startDate, endDate, rent, deposit, status } = req.body;
const contract = await Contract.findByPk(id);
const contract = await Contract.findOne({
where: { id, isDeleted: 0 }
});
if (!contract) {
return res.status(404).json({ error: '合同不存在' });
}
@ -128,15 +157,17 @@ const updateContract = async (req, res) => {
}
};
// 删除合同
// 删除合同(软删除)
const deleteContract = async (req, res) => {
try {
const { id } = req.params;
const contract = await Contract.findByPk(id);
const contract = await Contract.findOne({
where: { id, isDeleted: 0 }
});
if (!contract) {
return res.status(404).json({ error: '合同不存在' });
}
await contract.destroy();
await contract.update({ isDeleted: 1 });
res.status(200).json({ message: '合同删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -15,14 +15,16 @@ const formatElectricityBillData = (bill) => {
...bill.toJSON(),
startDate: formatDate(bill.startDate),
endDate: formatDate(bill.endDate),
createTime: formatDate(bill.createTime)
createTime: formatDate(bill.createTime),
updateTime: formatDate(bill.updateTime)
};
// 格式化关联数据
if (formattedBill.Room) {
formattedBill.Room = {
...formattedBill.Room,
createTime: formatDate(formattedBill.Room.createTime)
createTime: formatDate(formattedBill.Room.createTime),
updateTime: formatDate(formattedBill.Room.updateTime)
};
}
@ -35,7 +37,7 @@ const getAllElectricityBills = async (req, res) => {
const { roomId, status, startDate, endDate, page = 1, pageSize = 10 } = req.query;
// 构建查询条件
const where = {};
const where = { isDeleted: 0 };
if (roomId) {
where.roomId = roomId;
}
@ -55,7 +57,12 @@ const getAllElectricityBills = async (req, res) => {
// 查询电费数据
const { count, rows } = await ElectricityBill.findAndCountAll({
where,
include: [Room],
include: [
{
model: Room,
where: { isDeleted: 0 }
}
],
limit: parseInt(pageSize),
offset: parseInt(offset)
});
@ -79,8 +86,14 @@ const getAllElectricityBills = async (req, res) => {
const getElectricityBillById = async (req, res) => {
try {
const { id } = req.params;
const bill = await ElectricityBill.findByPk(id, {
include: [Room]
const bill = await ElectricityBill.findOne({
where: { id, isDeleted: 0 },
include: [
{
model: Room,
where: { isDeleted: 0 }
}
]
});
if (!bill) {
return res.status(404).json({ error: '电费记录不存在' });
@ -125,7 +138,9 @@ const updateElectricityBill = async (req, res) => {
const { id } = req.params;
const { startDate, endDate, startReading, endReading, unitPrice, status } = req.body;
const bill = await ElectricityBill.findByPk(id);
const bill = await ElectricityBill.findOne({
where: { id, isDeleted: 0 }
});
if (!bill) {
return res.status(404).json({ error: '电费记录不存在' });
}
@ -156,15 +171,17 @@ const updateElectricityBill = async (req, res) => {
}
};
// 删除电费记录
// 删除电费记录(软删除)
const deleteElectricityBill = async (req, res) => {
try {
const { id } = req.params;
const bill = await ElectricityBill.findByPk(id);
const bill = await ElectricityBill.findOne({
where: { id, isDeleted: 0 }
});
if (!bill) {
return res.status(404).json({ error: '电费记录不存在' });
}
await bill.destroy();
await bill.update({ isDeleted: 1 });
res.status(200).json({ message: '电费记录删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -12,14 +12,17 @@ const formatDate = (date) => {
const formatRegionData = (region) => {
return {
...region.toJSON(),
createTime: formatDate(region.createTime)
createTime: formatDate(region.createTime),
updateTime: formatDate(region.updateTime)
};
};
// 获取所有区域
const getAllRegions = async (req, res) => {
try {
const regions = await Region.findAll();
const regions = await Region.findAll({
where: { isDeleted: 0 }
});
const formattedRegions = regions.map(formatRegionData);
res.status(200).json(formattedRegions);
} catch (error) {
@ -31,7 +34,9 @@ const getAllRegions = async (req, res) => {
const getRegionById = async (req, res) => {
try {
const { id } = req.params;
const region = await Region.findByPk(id);
const region = await Region.findOne({
where: { id, isDeleted: 0 }
});
if (!region) {
return res.status(404).json({ error: '区域不存在' });
}
@ -58,7 +63,9 @@ const updateRegion = async (req, res) => {
try {
const { id } = req.params;
const { name, description } = req.body;
const region = await Region.findByPk(id);
const region = await Region.findOne({
where: { id, isDeleted: 0 }
});
if (!region) {
return res.status(404).json({ error: '区域不存在' });
}
@ -69,15 +76,17 @@ const updateRegion = async (req, res) => {
}
};
// 删除区域
// 删除区域(软删除)
const deleteRegion = async (req, res) => {
try {
const { id } = req.params;
const region = await Region.findByPk(id);
const region = await Region.findOne({
where: { id, isDeleted: 0 }
});
if (!region) {
return res.status(404).json({ error: '区域不存在' });
}
await region.destroy();
await region.update({ isDeleted: 1 });
res.status(200).json({ message: '区域删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -15,7 +15,8 @@ const formatRentalData = (rental) => {
...rental.toJSON(),
startDate: formatDate(rental.startDate),
endDate: formatDate(rental.endDate),
createTime: formatDate(rental.createTime)
createTime: formatDate(rental.createTime),
updateTime: formatDate(rental.updateTime)
};
// 格式化关联数据
@ -24,7 +25,8 @@ const formatRentalData = (rental) => {
...formattedRental.Contract,
startDate: formatDate(formattedRental.Contract.startDate),
endDate: formatDate(formattedRental.Contract.endDate),
createTime: formatDate(formattedRental.Contract.createTime)
createTime: formatDate(formattedRental.Contract.createTime),
updateTime: formatDate(formattedRental.Contract.updateTime)
};
}
@ -42,8 +44,13 @@ const checkAndUpdateRentalStatus = async () => {
// 查找所有活跃的租房记录
const rentals = await Rental.findAll({
where: { status: 'active' },
include: [Room]
where: { status: 'active', isDeleted: 0 },
include: [
{
model: Room,
where: { isDeleted: 0 }
}
]
});
// 检查每个租房记录的状态
@ -81,7 +88,7 @@ const getAllRentals = async (req, res) => {
const { roomNumber, tenantName, status, page = 1, pageSize = 10 } = req.query;
// 构建查询条件
const where = {};
const where = { isDeleted: 0 };
if (status) {
where.status = status;
}
@ -90,19 +97,28 @@ const getAllRentals = async (req, res) => {
const include = [
{
model: Room,
where: roomNumber ? { roomNumber: { [Op.like]: `%${roomNumber}%` }, isDeleted: 0 } : { isDeleted: 0 },
include: [
{
model: Apartment,
include: [Region]
where: { isDeleted: 0 },
include: [
{
model: Region,
where: { isDeleted: 0 }
}
]
}
],
where: roomNumber ? { roomNumber: { [Op.like]: `%${roomNumber}%` } } : {}
]
},
{
model: Tenant,
where: tenantName ? { name: { [Op.like]: `%${tenantName}%` } } : {}
where: tenantName ? { name: { [Op.like]: `%${tenantName}%` }, isDeleted: 0 } : { isDeleted: 0 }
},
Contract
{
model: Contract,
where: { isDeleted: 0 }
}
];
// 计算偏移量
@ -135,19 +151,33 @@ const getAllRentals = async (req, res) => {
const getRentalById = async (req, res) => {
try {
const { id } = req.params;
const rental = await Rental.findByPk(id, {
const rental = await Rental.findOne({
where: { id, isDeleted: 0 },
include: [
{
model: Room,
where: { isDeleted: 0 },
include: [
{
model: Apartment,
include: [Region]
where: { isDeleted: 0 },
include: [
{
model: Region,
where: { isDeleted: 0 }
}
]
}
]
},
Tenant,
Contract
{
model: Tenant,
where: { isDeleted: 0 }
},
{
model: Contract,
where: { isDeleted: 0 }
}
]
});
if (!rental) {
@ -286,7 +316,9 @@ const updateRental = async (req, res) => {
try {
const { id } = req.params;
const { roomId, tenantId, contractId, startDate, endDate, rent, deposit, status } = req.body;
const rental = await Rental.findByPk(id);
const rental = await Rental.findOne({
where: { id, isDeleted: 0 }
});
if (!rental) {
return res.status(404).json({ error: '租房记录不存在' });
}
@ -297,15 +329,17 @@ const updateRental = async (req, res) => {
}
};
// 删除租房
// 删除租房(软删除)
const deleteRental = async (req, res) => {
try {
const { id } = req.params;
const rental = await Rental.findByPk(id);
const rental = await Rental.findOne({
where: { id, isDeleted: 0 }
});
if (!rental) {
return res.status(404).json({ error: '租房记录不存在' });
}
await rental.destroy();
await rental.update({ isDeleted: 1 });
res.status(200).json({ message: '租房记录删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -13,14 +13,16 @@ const formatDate = (date) => {
const formatRoomData = (room) => {
const formattedRoom = {
...room.toJSON(),
createTime: formatDate(room.createTime)
createTime: formatDate(room.createTime),
updateTime: formatDate(room.updateTime)
};
// 格式化关联数据
if (formattedRoom.Apartment) {
formattedRoom.Apartment = {
...formattedRoom.Apartment,
createTime: formatDate(formattedRoom.Apartment.createTime)
createTime: formatDate(formattedRoom.Apartment.createTime),
updateTime: formatDate(formattedRoom.Apartment.updateTime)
};
}
@ -31,14 +33,16 @@ const formatRoomData = (room) => {
...rental,
startDate: formatDate(rental.startDate),
endDate: formatDate(rental.endDate),
createTime: formatDate(rental.createTime)
createTime: formatDate(rental.createTime),
updateTime: formatDate(rental.updateTime)
};
// 格式化租客信息
if (formattedRental.Tenant) {
formattedRental.Tenant = {
...formattedRental.Tenant,
createTime: formatDate(formattedRental.Tenant.createTime)
createTime: formatDate(formattedRental.Tenant.createTime),
updateTime: formatDate(formattedRental.Tenant.updateTime)
};
}
@ -60,7 +64,7 @@ const checkAndUpdateRentalStatus = async () => {
// 查找所有活跃的租房记录
const rentals = await Rental.findAll({
where: { status: 'active' }
where: { status: 'active', isDeleted: 0 }
});
// 检查每个租房记录的状态
@ -73,14 +77,20 @@ const checkAndUpdateRentalStatus = async () => {
await rental.update({ status: 'expired' });
// 更新房间状态为空房
const room = await Room.findByPk(rental.roomId);
if (room) {
await room.update({ status: 'empty' });
if (room && room.status === 'rented') {
await room.update({ status: 'empty', subStatus: 'normal' });
}
} else if (endDate <= tenDaysLater) {
// 更新房间状态为即将到期
// 更新房间附属状态为即将到期
const room = await Room.findByPk(rental.roomId);
if (room && room.status === 'rented') {
await room.update({ status: 'soon_expire' });
await room.update({ subStatus: 'soon_expire' });
}
} else {
// 更新房间附属状态为正常
const room = await Room.findByPk(rental.roomId);
if (room && room.status === 'rented') {
await room.update({ subStatus: 'normal' });
}
}
}
@ -97,10 +107,10 @@ const getAllRooms = async (req, res) => {
// 先检查并更新租房状态
await checkAndUpdateRentalStatus();
const { apartmentId, roomNumber, status, page = 1, pageSize = 10 } = req.query;
const { apartmentId, roomNumber, status, otherStatus, subStatus, page = 1, pageSize = 10 } = req.query;
// 构建查询条件
const where = {};
const where = { isDeleted: 0 };
if (apartmentId) {
where.apartmentId = apartmentId;
}
@ -112,6 +122,12 @@ const getAllRooms = async (req, res) => {
if (status) {
where.status = status;
}
if (otherStatus) {
where.otherStatus = otherStatus;
}
if (subStatus) {
where.subStatus = subStatus;
}
// 计算偏移量
const offset = (page - 1) * pageSize;
@ -187,7 +203,8 @@ const getRoomById = async (req, res) => {
await checkAndUpdateRentalStatus();
const { id } = req.params;
const room = await Room.findByPk(id, {
const room = await Room.findOne({
where: { id, isDeleted: 0 },
include: [Apartment]
});
if (!room) {
@ -238,8 +255,8 @@ const getRoomById = async (req, res) => {
// 创建房间
const createRoom = async (req, res) => {
try {
const { apartmentId, roomNumber, area, price, status } = req.body;
const room = await Room.create({ apartmentId, roomNumber, area, price, status });
const { apartmentId, roomNumber, area, monthlyPrice, yearlyPrice, status, subStatus, otherStatus } = req.body;
const room = await Room.create({ apartmentId, roomNumber, area, monthlyPrice, yearlyPrice, status, subStatus, otherStatus });
res.status(201).json(room);
} catch (error) {
res.status(500).json({ error: error.message });
@ -250,27 +267,31 @@ const createRoom = async (req, res) => {
const updateRoom = async (req, res) => {
try {
const { id } = req.params;
const { apartmentId, roomNumber, area, price, status } = req.body;
const room = await Room.findByPk(id);
const { apartmentId, roomNumber, area, monthlyPrice, yearlyPrice, status, subStatus, otherStatus } = req.body;
const room = await Room.findOne({
where: { id, isDeleted: 0 }
});
if (!room) {
return res.status(404).json({ error: '房间不存在' });
}
await room.update({ apartmentId, roomNumber, area, price, status });
await room.update({ apartmentId, roomNumber, area, monthlyPrice, yearlyPrice, status, subStatus, otherStatus });
res.status(200).json(room);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
// 删除房间
// 删除房间(软删除)
const deleteRoom = async (req, res) => {
try {
const { id } = req.params;
const room = await Room.findByPk(id);
const room = await Room.findOne({
where: { id, isDeleted: 0 }
});
if (!room) {
return res.status(404).json({ error: '房间不存在' });
}
await room.destroy();
await room.update({ isDeleted: 1 });
res.status(200).json({ message: '房间删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -12,14 +12,17 @@ const formatDate = (date) => {
const formatTenantData = (tenant) => {
return {
...tenant.toJSON(),
createTime: formatDate(tenant.createTime)
createTime: formatDate(tenant.createTime),
updateTime: formatDate(tenant.updateTime)
};
};
// 获取所有租客
const getAllTenants = async (req, res) => {
try {
const tenants = await Tenant.findAll();
const tenants = await Tenant.findAll({
where: { isDeleted: 0 }
});
const formattedTenants = tenants.map(formatTenantData);
res.status(200).json(formattedTenants);
} catch (error) {
@ -31,7 +34,9 @@ const getAllTenants = async (req, res) => {
const getTenantById = async (req, res) => {
try {
const { id } = req.params;
const tenant = await Tenant.findByPk(id);
const tenant = await Tenant.findOne({
where: { id, isDeleted: 0 }
});
if (!tenant) {
return res.status(404).json({ error: '租客不存在' });
}
@ -58,7 +63,9 @@ const updateTenant = async (req, res) => {
try {
const { id } = req.params;
const { name, phone, idCard } = req.body;
const tenant = await Tenant.findByPk(id);
const tenant = await Tenant.findOne({
where: { id, isDeleted: 0 }
});
if (!tenant) {
return res.status(404).json({ error: '租客不存在' });
}
@ -69,15 +76,17 @@ const updateTenant = async (req, res) => {
}
};
// 删除租客
// 删除租客(软删除)
const deleteTenant = async (req, res) => {
try {
const { id } = req.params;
const tenant = await Tenant.findByPk(id);
const tenant = await Tenant.findOne({
where: { id, isDeleted: 0 }
});
if (!tenant) {
return res.status(404).json({ error: '租客不存在' });
}
await tenant.destroy();
await tenant.update({ isDeleted: 1 });
res.status(200).json({ message: '租客删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -15,14 +15,16 @@ const formatWaterBillData = (bill) => {
...bill.toJSON(),
startDate: formatDate(bill.startDate),
endDate: formatDate(bill.endDate),
createTime: formatDate(bill.createTime)
createTime: formatDate(bill.createTime),
updateTime: formatDate(bill.updateTime)
};
// 格式化关联数据
if (formattedBill.Room) {
formattedBill.Room = {
...formattedBill.Room,
createTime: formatDate(formattedBill.Room.createTime)
createTime: formatDate(formattedBill.Room.createTime),
updateTime: formatDate(formattedBill.Room.updateTime)
};
}
@ -35,7 +37,7 @@ const getAllWaterBills = async (req, res) => {
const { roomId, status, startDate, endDate, page = 1, pageSize = 10 } = req.query;
// 构建查询条件
const where = {};
const where = { isDeleted: 0 };
if (roomId) {
where.roomId = roomId;
}
@ -55,7 +57,12 @@ const getAllWaterBills = async (req, res) => {
// 查询水费数据
const { count, rows } = await WaterBill.findAndCountAll({
where,
include: [Room],
include: [
{
model: Room,
where: { isDeleted: 0 }
}
],
limit: parseInt(pageSize),
offset: parseInt(offset)
});
@ -79,8 +86,14 @@ const getAllWaterBills = async (req, res) => {
const getWaterBillById = async (req, res) => {
try {
const { id } = req.params;
const bill = await WaterBill.findByPk(id, {
include: [Room]
const bill = await WaterBill.findOne({
where: { id, isDeleted: 0 },
include: [
{
model: Room,
where: { isDeleted: 0 }
}
]
});
if (!bill) {
return res.status(404).json({ error: '水费记录不存在' });
@ -125,7 +138,9 @@ const updateWaterBill = async (req, res) => {
const { id } = req.params;
const { startDate, endDate, startReading, endReading, unitPrice, status } = req.body;
const bill = await WaterBill.findByPk(id);
const bill = await WaterBill.findOne({
where: { id, isDeleted: 0 }
});
if (!bill) {
return res.status(404).json({ error: '水费记录不存在' });
}
@ -156,15 +171,17 @@ const updateWaterBill = async (req, res) => {
}
};
// 删除水费记录
// 删除水费记录(软删除)
const deleteWaterBill = async (req, res) => {
try {
const { id } = req.params;
const bill = await WaterBill.findByPk(id);
const bill = await WaterBill.findOne({
where: { id, isDeleted: 0 }
});
if (!bill) {
return res.status(404).json({ error: '水费记录不存在' });
}
await bill.destroy();
await bill.update({ isDeleted: 1 });
res.status(200).json({ message: '水费记录删除成功' });
} catch (error) {
res.status(500).json({ error: error.message });

View File

@ -27,6 +27,16 @@ const Apartment = sequelize.define('Apartment', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'apartments',

View File

@ -49,6 +49,16 @@ const Contract = sequelize.define('Contract', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'contracts',

View File

@ -52,6 +52,16 @@ const ElectricityBill = sequelize.define('ElectricityBill', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'electricity_bills',

View File

@ -19,6 +19,16 @@ const Region = sequelize.define('Region', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'regions',

View File

@ -62,6 +62,16 @@ const Rental = sequelize.define('Rental', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'rentals',

View File

@ -24,18 +24,42 @@ const Room = sequelize.define('Room', {
type: DataTypes.DECIMAL(10, 2),
allowNull: false
},
price: {
monthlyPrice: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false
},
yearlyPrice: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false
},
status: {
type: DataTypes.ENUM('empty', 'rented', 'soon_expire', 'expired', 'cleaning', 'maintenance'),
type: DataTypes.ENUM('empty', 'rented'),
allowNull: false,
defaultValue: 'empty'
},
subStatus: {
type: DataTypes.ENUM('normal', 'soon_expire', 'expired'),
allowNull: false,
defaultValue: 'normal'
},
otherStatus: {
type: DataTypes.ENUM('', 'cleaning', 'maintenance'),
allowNull: false,
defaultValue: ''
},
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'rooms',

View File

@ -23,6 +23,16 @@ const Tenant = sequelize.define('Tenant', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'tenants',

View File

@ -52,6 +52,16 @@ const WaterBill = sequelize.define('WaterBill', {
createTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updateTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
onUpdate: DataTypes.NOW
},
isDeleted: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 0
}
}, {
tableName: 'water_bills',

37
update_db.js Normal file
View File

@ -0,0 +1,37 @@
const mysql = require('mysql2/promise');
const fs = require('fs');
async function updateDatabase() {
try {
// 连接到数据库
const connection = await mysql.createConnection({
host: '8.152.207.41',
user: 'rentease',
password: 'Wxx@123!',
database: 'rentease'
});
console.log('成功连接到数据库');
// 读取 SQL 文件
const sqlContent = fs.readFileSync('add_fields.sql', 'utf8');
// 执行 SQL 语句
const statements = sqlContent.split(';').filter(statement => statement.trim());
for (const statement of statements) {
await connection.query(statement);
console.log(`执行 SQL: ${statement.substring(0, 50)}...`);
}
console.log('数据库表结构更新完成');
// 关闭连接
await connection.end();
console.log('数据库连接已关闭');
} catch (error) {
console.error('更新数据库表结构时出错:', error);
}
}
updateDatabase();

41
update_room_price.js Normal file
View File

@ -0,0 +1,41 @@
const mysql = require('mysql2/promise');
const fs = require('fs');
// 数据库连接配置
const dbConfig = {
host: '8.152.207.41',
user: 'root',
password: '123456',
database: 'rentease',
port: 3306
};
// 读取 SQL 文件
const sqlFilePath = './update_room_price_fields.sql';
const sqlContent = fs.readFileSync(sqlFilePath, 'utf8');
// 执行 SQL 语句
const executeSql = async () => {
let connection;
try {
// 连接数据库
connection = await mysql.createConnection(dbConfig);
console.log('成功连接到数据库');
// 执行 SQL 语句
const [results] = await connection.execute(sqlContent);
console.log('数据库表结构更新成功');
} catch (error) {
console.error('更新数据库表结构时出错:', error);
} finally {
// 关闭数据库连接
if (connection) {
await connection.end();
console.log('数据库连接已关闭');
}
}
};
// 执行脚本
executeSql();

View File

@ -0,0 +1,16 @@
-- 更新房间表结构,将原来的 price 字段改为 monthlyPrice 和 yearlyPrice 两个字段
-- 添加 monthlyPrice 字段
ALTER TABLE rooms ADD COLUMN monthlyPrice DECIMAL(10, 2) NOT NULL DEFAULT 0 AFTER area;
-- 添加 yearlyPrice 字段
ALTER TABLE rooms ADD COLUMN yearlyPrice DECIMAL(10, 2) NOT NULL DEFAULT 0 AFTER monthlyPrice;
-- 将原来的 price 字段值复制到 monthlyPrice 字段
UPDATE rooms SET monthlyPrice = price;
-- 计算年租金并更新 yearlyPrice 字段(月租金 * 12
UPDATE rooms SET yearlyPrice = monthlyPrice * 12;
-- 删除原来的 price 字段
ALTER TABLE rooms DROP COLUMN price;