押金不是必填

This commit is contained in:
wangxiaoxian 2026-03-04 15:09:52 +08:00
parent 79deb628b4
commit 95063cad70
7 changed files with 552 additions and 328 deletions

View File

@ -18,7 +18,7 @@ const formatRentalData = (rental) => {
createTime: formatDate(rental.createTime), createTime: formatDate(rental.createTime),
updateTime: formatDate(rental.updateTime) updateTime: formatDate(rental.updateTime)
}; };
// 格式化关联数据 // 格式化关联数据
if (formattedRental.Contract) { if (formattedRental.Contract) {
formattedRental.Contract = { formattedRental.Contract = {
@ -29,7 +29,7 @@ const formatRentalData = (rental) => {
updateTime: formatDate(formattedRental.Contract.updateTime) updateTime: formatDate(formattedRental.Contract.updateTime)
}; };
} }
return formattedRental; return formattedRental;
}; };
@ -41,7 +41,7 @@ const checkAndUpdateRentalStatus = async () => {
// 计算10天后的日期 // 计算10天后的日期
const tenDaysLater = new Date(); const tenDaysLater = new Date();
tenDaysLater.setDate(currentDate.getDate() + 30); tenDaysLater.setDate(currentDate.getDate() + 30);
// 查找所有活跃的租房记录 // 查找所有活跃的租房记录
const rentals = await Rental.findAll({ const rentals = await Rental.findAll({
where: { status: 'active', isDeleted: 0 }, where: { status: 'active', isDeleted: 0 },
@ -52,11 +52,11 @@ const checkAndUpdateRentalStatus = async () => {
} }
] ]
}); });
// 检查每个租房记录的状态 // 检查每个租房记录的状态
for (const rental of rentals) { for (const rental of rentals) {
const endDate = new Date(rental.endDate); const endDate = new Date(rental.endDate);
// 检查是否已到期 // 检查是否已到期
if (endDate < currentDate) { if (endDate < currentDate) {
// 更新房间附属状态为已到期 // 更新房间附属状态为已到期
@ -78,7 +78,7 @@ const checkAndUpdateRentalStatus = async () => {
} }
} }
} }
console.log('租房状态检查和更新完成'); console.log('租房状态检查和更新完成');
} catch (error) { } catch (error) {
console.error('检查和更新租房状态时出错:', error); console.error('检查和更新租房状态时出错:', error);
@ -90,33 +90,20 @@ const getAllRentals = async (req, res) => {
try { try {
// 先检查并更新租房状态 // 先检查并更新租房状态
await checkAndUpdateRentalStatus(); await checkAndUpdateRentalStatus();
const { roomNumber, tenantName, status, page = 1, pageSize = 10 } = req.query; const { roomId, tenantName, status, page = 1, pageSize = 10 } = req.query;
// 构建查询条件 // 构建查询条件
const where = { isDeleted: 0 }; const where = { isDeleted: 0 };
if (status) { if (status) {
where.status = status; where.status = status;
} }
if (roomId) {
// 构建包含关系 where.roomId = roomId;
}
// 构建包含关系 - 关联租客信息和合同信息
const include = [ const include = [
{
model: Room,
where: roomNumber ? { roomNumber: { [Op.like]: `%${roomNumber}%` }, isDeleted: 0 } : { isDeleted: 0 },
include: [
{
model: Apartment,
where: { isDeleted: 0 },
include: [
{
model: Region,
where: { isDeleted: 0 }
}
]
}
]
},
{ {
model: Tenant, model: Tenant,
where: tenantName ? { name: { [Op.like]: `%${tenantName}%` }, isDeleted: 0 } : { isDeleted: 0 } where: tenantName ? { name: { [Op.like]: `%${tenantName}%` }, isDeleted: 0 } : { isDeleted: 0 }
@ -126,21 +113,22 @@ const getAllRentals = async (req, res) => {
where: { isDeleted: 0 } where: { isDeleted: 0 }
} }
]; ];
// 计算偏移量 // 计算偏移量
const offset = (page - 1) * pageSize; const offset = (page - 1) * pageSize;
// 查询租房数据 // 查询租房数据
const { count, rows } = await Rental.findAndCountAll({ const { count, rows } = await Rental.findAndCountAll({
where, where,
include, include,
limit: parseInt(pageSize), limit: parseInt(pageSize),
offset: parseInt(offset) offset: parseInt(offset),
order: [['createTime', 'DESC']] // 按创建时间倒序排序
}); });
// 格式化数据 // 格式化数据
const formattedRentals = rows.map(formatRentalData); const formattedRentals = rows.map(formatRentalData);
// 返回结果 // 返回结果
res.status(200).json({ res.status(200).json({
data: formattedRentals, data: formattedRentals,
@ -200,15 +188,15 @@ const getRentalById = async (req, res) => {
const createRental = async (req, res) => { const createRental = async (req, res) => {
try { try {
console.log('接收到的请求数据:', req.body); console.log('接收到的请求数据:', req.body);
// 直接使用req.body中的数据 // 直接使用req.body中的数据
const body = req.body; const body = req.body;
// 检查请求体是否存在 // 检查请求体是否存在
if (!body) { if (!body) {
return res.status(400).json({ error: '请求体不能为空' }); return res.status(400).json({ error: '请求体不能为空' });
} }
// 检查所有必要参数 // 检查所有必要参数
if (!body.roomId) { if (!body.roomId) {
return res.status(400).json({ error: '缺少房间ID' }); return res.status(400).json({ error: '缺少房间ID' });
@ -216,12 +204,6 @@ const createRental = async (req, res) => {
if (!body.tenantName) { if (!body.tenantName) {
return res.status(400).json({ error: '缺少租客姓名' }); return res.status(400).json({ error: '缺少租客姓名' });
} }
if (!body.tenantPhone) {
return res.status(400).json({ error: '缺少租客电话' });
}
if (!body.tenantIdCard) {
return res.status(400).json({ error: '缺少身份证号' });
}
if (!body.startDate) { if (!body.startDate) {
return res.status(400).json({ error: '缺少开始日期' }); return res.status(400).json({ error: '缺少开始日期' });
} }
@ -231,68 +213,74 @@ const createRental = async (req, res) => {
if (!body.rent) { if (!body.rent) {
return res.status(400).json({ error: '缺少租金' }); return res.status(400).json({ error: '缺少租金' });
} }
// 转换roomId为整数类型 // 转换roomId为整数类型
const parsedRoomId = parseInt(body.roomId); const parsedRoomId = parseInt(body.roomId);
if (isNaN(parsedRoomId)) { if (isNaN(parsedRoomId)) {
return res.status(400).json({ error: '无效的房间ID' }); return res.status(400).json({ error: '无效的房间ID' });
} }
// 先查找或创建租客 // 先查找或创建租客
let tenant = await Tenant.findOne({ where: { idCard: body.tenantIdCard } }); let tenant;
if (body.tenantIdCard) {
tenant = await Tenant.findOne({ where: { idCard: body.tenantIdCard } });
}
if (!tenant) { if (!tenant) {
console.log('创建新租客:', { name: body.tenantName, phone: body.tenantPhone, idCard: body.tenantIdCard }); console.log('创建新租客:', { name: body.tenantName, phone: body.tenantPhone, idCard: body.tenantIdCard });
tenant = await Tenant.create({ tenant = await Tenant.create({
name: body.tenantName, name: body.tenantName,
phone: body.tenantPhone, phone: body.tenantPhone,
idCard: body.tenantIdCard idCard: body.tenantIdCard
}); });
} }
console.log('租客信息:', tenant); console.log('租客信息:', tenant);
// 确保租客创建成功 // 确保租客创建成功
if (!tenant || !tenant.id) { if (!tenant || !tenant.id) {
return res.status(500).json({ error: '创建租客失败' }); return res.status(500).json({ error: '创建租客失败' });
} }
// 处理押金为空时设置为0
const deposit = body.deposit || 0;
// 创建合同 // 创建合同
console.log('创建合同:', { console.log('创建合同:', {
roomId: parsedRoomId, roomId: parsedRoomId,
tenantId: tenant.id, tenantId: tenant.id,
startDate: body.startDate, startDate: body.startDate,
endDate: body.endDate, endDate: body.endDate,
rent: body.rent, rent: body.rent,
deposit: body.deposit, deposit: deposit,
status: body.status || 'active' status: body.status || 'active'
}); });
const contract = await Contract.create({ const contract = await Contract.create({
roomId: parsedRoomId, roomId: parsedRoomId,
tenantId: tenant.id, tenantId: tenant.id,
startDate: body.startDate, startDate: body.startDate,
endDate: body.endDate, endDate: body.endDate,
rent: body.rent, rent: body.rent,
deposit: body.deposit, deposit: deposit,
status: body.status || 'active' status: body.status || 'active'
}); });
console.log('合同信息:', contract); console.log('合同信息:', contract);
// 确保合同创建成功 // 确保合同创建成功
if (!contract || !contract.id) { if (!contract || !contract.id) {
return res.status(500).json({ error: '创建合同失败' }); return res.status(500).json({ error: '创建合同失败' });
} }
// 创建租房记录 // 创建租房记录
console.log('创建租房记录:', { console.log('创建租房记录:', {
roomId: parsedRoomId, roomId: parsedRoomId,
tenantId: tenant.id, tenantId: tenant.id,
contractId: contract.id, contractId: contract.id,
startDate: body.startDate, startDate: body.startDate,
endDate: body.endDate, endDate: body.endDate,
rent: body.rent, rent: body.rent,
deposit: body.deposit, deposit: deposit,
status: body.status || 'active' status: body.status || 'active'
}); });
// 直接使用具体的数值创建租房记录 // 直接使用具体的数值创建租房记录
const rental = await Rental.create({ const rental = await Rental.create({
roomId: parsedRoomId, roomId: parsedRoomId,
@ -301,15 +289,15 @@ const createRental = async (req, res) => {
startDate: body.startDate, startDate: body.startDate,
endDate: body.endDate, endDate: body.endDate,
rent: body.rent, rent: body.rent,
deposit: body.deposit, deposit: deposit,
status: body.status || 'active' status: body.status || 'active'
}); });
console.log('租房记录:', rental); console.log('租房记录:', rental);
// 更新房间状态为已租 // 更新房间状态为已租
await Room.update({ status: 'rented' }, { where: { id: parsedRoomId } }); await Room.update({ status: 'rented' }, { where: { id: parsedRoomId } });
res.status(201).json(rental); res.status(201).json(rental);
} catch (error) { } catch (error) {
console.error('创建租房记录时出错:', error); console.error('创建租房记录时出错:', error);
@ -328,7 +316,9 @@ const updateRental = async (req, res) => {
if (!rental) { if (!rental) {
return res.status(404).json({ error: '租房记录不存在' }); return res.status(404).json({ error: '租房记录不存在' });
} }
await rental.update({ roomId, tenantId, contractId, startDate, endDate, rent, deposit, status }); // 处理押金为空时设置为0
const updateDeposit = deposit || 0;
await rental.update({ roomId, tenantId, contractId, startDate, endDate, rent, deposit: updateDeposit, status });
res.status(200).json(rental); res.status(200).json(rental);
} catch (error) { } catch (error) {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
@ -358,4 +348,4 @@ module.exports = {
createRental, createRental,
updateRental, updateRental,
deleteRental deleteRental
}; };

View File

@ -64,7 +64,8 @@ const getAllWaterBills = async (req, res) => {
} }
], ],
limit: parseInt(pageSize), limit: parseInt(pageSize),
offset: parseInt(offset) offset: parseInt(offset),
order: [['createTime', 'DESC']] // 按创建时间倒序排序
}); });
// 格式化数据 // 格式化数据

View File

@ -39,7 +39,7 @@ const Contract = sequelize.define('Contract', {
}, },
deposit: { deposit: {
type: DataTypes.DECIMAL(10, 2), type: DataTypes.DECIMAL(10, 2),
allowNull: false allowNull: true
}, },
status: { status: {
type: DataTypes.ENUM('active', 'expired'), type: DataTypes.ENUM('active', 'expired'),

View File

@ -48,7 +48,7 @@ const Rental = sequelize.define('Rental', {
}, },
deposit: { deposit: {
type: DataTypes.DECIMAL(10, 2), type: DataTypes.DECIMAL(10, 2),
allowNull: false allowNull: true
}, },
status: { status: {
type: DataTypes.ENUM('active', 'expired'), type: DataTypes.ENUM('active', 'expired'),

View File

@ -13,11 +13,11 @@ const Tenant = sequelize.define('Tenant', {
}, },
phone: { phone: {
type: DataTypes.STRING(20), type: DataTypes.STRING(20),
allowNull: false allowNull: true
}, },
idCard: { idCard: {
type: DataTypes.STRING(20), type: DataTypes.STRING(20),
allowNull: false, allowNull: true,
unique: true unique: true
}, },
createTime: { createTime: {

711
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
"dependencies": { "dependencies": {
"cors": "^2.8.6", "cors": "^2.8.6",
"express": "^4.17.1", "express": "^4.17.1",
"mysql2": "^3.18.2", "mysql2": "^2.3.3",
"sequelize": "^6.37.7" "sequelize": "^6.37.7"
} }
} }