rentease-backend-new/controllers/rentalController.js

798 lines
22 KiB
JavaScript
Raw Normal View History

2026-04-20 06:43:09 +00:00
const { Rental, Room, Apartment, Bill, Transaction, Renter, MeterReading } = require('../models');
const { Op } = require('sequelize');
2026-04-22 06:48:32 +00:00
const response = require('../utils/response');
2026-04-20 06:43:09 +00:00
// 格式化时间(考虑时区,转换为北京时间)
const formatDate = (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().split('T')[0];
};
2026-05-09 09:01:41 +00:00
// 格式化日期时间(年月日时分秒)
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);
};
2026-04-20 06:43:09 +00:00
// 格式化租房数据
const formatRentalData = (rental) => {
const formattedRental = {
...rental.toJSON(),
startDate: formatDate(rental.startDate),
endDate: formatDate(rental.endDate),
2026-05-09 09:01:41 +00:00
createTime: formatDateTime(rental.createTime),
updateTime: formatDateTime(rental.updateTime)
2026-04-20 06:43:09 +00:00
};
return formattedRental;
};
// 检查并更新租房状态
2026-05-09 09:01:41 +00:00
const checkAndUpdateRentalStatus = async (tenantId) => {
2026-04-20 06:43:09 +00:00
try {
// 获取当前日期
const currentDate = new Date();
// 计算5天后的日期
const fiveDaysLater = new Date();
fiveDaysLater.setDate(currentDate.getDate() + 5);
2026-05-09 09:01:41 +00:00
// 查找该租户下所有活跃的租房记录
2026-04-20 06:43:09 +00:00
const rentals = await Rental.findAll({
2026-05-09 09:01:41 +00:00
where: { tenantId, status: 'active', isDeleted: 0 },
2026-04-20 06:43:09 +00:00
include: [
{
model: Room,
where: { isDeleted: 0 }
}
]
});
// 检查每个租房记录的状态
for (const rental of rentals) {
const endDate = new Date(rental.endDate);
// 检查是否已到期
if (endDate < currentDate) {
// 更新房间租约状态为已到期
const room = await Room.findByPk(rental.roomId);
if (room && room.status === 'rented') {
await room.update({ rentalStatus: 'expired' });
}
} else if (endDate <= fiveDaysLater) {
// 更新房间租约状态为即将到期
const room = await Room.findByPk(rental.roomId);
if (room && room.status === 'rented') {
await room.update({ rentalStatus: 'soon_expire' });
}
} else {
// 更新房间租约状态为正常
const room = await Room.findByPk(rental.roomId);
if (room && room.status === 'rented') {
await room.update({ rentalStatus: 'normal' });
}
}
}
console.log('租房状态检查和更新完成');
} catch (error) {
console.error('检查和更新租房状态时出错:', error);
}
};
// 获取所有租房(支持搜索和分页)
const getAllRentals = async (req, res) => {
try {
// 先检查并更新租房状态
2026-05-09 09:01:41 +00:00
await checkAndUpdateRentalStatus(req.user.tenantId);
2026-04-20 06:43:09 +00:00
const {
apartmentId,
roomId,
renterName,
status,
startDateFrom,
startDateTo,
endDateFrom,
endDateTo,
page = 1,
pageSize = 10
} = req.query;
// 构建查询条件
2026-05-09 09:01:41 +00:00
const where = { tenantId: req.user.tenantId, isDeleted: 0 };
2026-04-20 06:43:09 +00:00
if (status) {
where.status = status;
}
if (roomId) {
where.roomId = roomId;
}
if (startDateFrom && startDateTo) {
where.startDate = { [Op.between]: [new Date(startDateFrom), new Date(startDateTo)] };
}
if (endDateFrom && endDateTo) {
where.endDate = { [Op.between]: [new Date(endDateFrom), new Date(endDateTo)] };
}
// 构建包含关系
const include = [
{
model: Room,
where: {
isDeleted: 0,
...(apartmentId ? { apartmentId } : {})
},
include: [
{
model: Apartment,
where: { isDeleted: 0 }
}
]
},
{
model: Renter,
where: renterName ? { name: { [Op.like]: `%${renterName}%` } } : undefined,
required: !!renterName
}
];
// 计算偏移量
const offset = (page - 1) * pageSize;
// 查询租房数据
const { count, rows } = await Rental.findAndCountAll({
where,
include,
limit: parseInt(pageSize),
offset: parseInt(offset),
order: [['createTime', 'DESC']] // 按创建时间倒序排序
});
// 格式化数据
const formattedRentals = rows.map(formatRentalData);
// 返回结果
2026-04-22 06:48:32 +00:00
response.success(res, '获取成功', {
list: formattedRentals,
2026-04-20 06:43:09 +00:00
total: count,
page: parseInt(page),
pageSize: parseInt(pageSize)
});
} catch (error) {
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取租房列表失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 获取单个租房
const getRentalById = async (req, res) => {
try {
const { id } = req.params;
const rental = await Rental.findOne({
2026-05-09 09:01:41 +00:00
where: { id, tenantId: req.user.tenantId, isDeleted: 0 },
2026-04-20 06:43:09 +00:00
include: [
{
model: Room,
where: { isDeleted: 0 },
include: [
{
model: Apartment,
where: { isDeleted: 0 }
}
]
},
{
model: Renter
}
]
});
if (!rental) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '租房记录不存在');
2026-04-20 06:43:09 +00:00
}
const formattedRental = formatRentalData(rental);
2026-04-22 06:48:32 +00:00
response.success(res, '获取成功', formattedRental);
2026-04-20 06:43:09 +00:00
} catch (error) {
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取租房详情失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 创建租房
const createRental = async (req, res) => {
try {
console.log('接收到的请求数据:', req.body);
// 直接使用req.body中的数据
const body = req.body;
// 检查请求体是否存在
if (!body) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '请求体不能为空');
2026-04-20 06:43:09 +00:00
}
// 检查所有必要参数
if (!body.roomId) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '缺少房间ID');
2026-04-20 06:43:09 +00:00
}
if (!body.renterId) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '缺少租客ID');
2026-04-20 06:43:09 +00:00
}
if (!body.startDate) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '缺少开始日期');
2026-04-20 06:43:09 +00:00
}
if (!body.endDate) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '缺少结束日期');
2026-04-20 06:43:09 +00:00
}
if (!body.rent) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '缺少租金');
2026-04-20 06:43:09 +00:00
}
// 转换roomId和renterId为整数类型
const parsedRoomId = parseInt(body.roomId);
const parsedRenterId = parseInt(body.renterId);
if (isNaN(parsedRoomId)) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '无效的房间ID');
2026-04-20 06:43:09 +00:00
}
if (isNaN(parsedRenterId)) {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '无效的租客ID');
2026-04-20 06:43:09 +00:00
}
// 处理押金为空时设置为0
const deposit = body.deposit || 0;
// 获取租客信息用于账单备注
const renter = await Renter.findByPk(parsedRenterId);
const renterName = renter ? renter.name : '';
// 创建租房记录
console.log('创建租房记录:', {
roomId: parsedRoomId,
renterId: parsedRenterId,
startDate: body.startDate,
endDate: body.endDate,
paymentType: body.paymentType || 'monthly',
rent: body.rent,
deposit: deposit,
operator: body.operator,
waterMeterStart: body.waterMeterStart,
electricityMeterStart: body.electricityMeterStart,
status: body.status || 'active',
remark: body.remark
});
const rental = await Rental.create({
roomId: parsedRoomId,
renterId: parsedRenterId,
startDate: body.startDate,
endDate: body.endDate,
paymentType: body.paymentType || 'monthly',
rent: body.rent,
deposit: deposit,
operator: body.operator || null,
waterMeterStart: body.waterMeterStart || null,
electricityMeterStart: body.electricityMeterStart || null,
status: body.status || 'active',
remark: body.remark,
2026-05-09 09:01:41 +00:00
tenantId: req.user.tenantId,
2026-04-20 06:43:09 +00:00
createBy: req.user.id,
updateBy: req.user.id
});
console.log('租房记录:', rental);
// 更新房间状态为已租
await Room.update({ status: 'rented', rentalStatus: 'normal' }, { where: { id: parsedRoomId } });
// 自动生成租金账单
await Bill.create({
2026-05-09 09:01:41 +00:00
billNo: 'B' + Date.now(),
2026-04-20 06:43:09 +00:00
rentalId: rental.id,
roomId: parsedRoomId,
2026-05-09 09:01:41 +00:00
renterId: parsedRenterId,
2026-04-20 06:43:09 +00:00
type: 'income',
category: 'rent',
2026-05-09 09:01:41 +00:00
receivableAmount: body.rent,
receivedAmount: 0,
status: 'unpaid',
billDate: body.startDate,
billMonth: body.startDate.substring(0, 7),
2026-04-20 06:43:09 +00:00
remark: `租约租金 - ${renterName}`,
tenantId: req.user.tenantId,
createBy: req.user.id,
updateBy: req.user.id
});
// 自动生成押金账单(如果有押金)
if (deposit > 0) {
await Bill.create({
2026-05-09 09:01:41 +00:00
billNo: 'B' + Date.now() + '1',
2026-04-20 06:43:09 +00:00
rentalId: rental.id,
roomId: parsedRoomId,
2026-05-09 09:01:41 +00:00
renterId: parsedRenterId,
2026-04-20 06:43:09 +00:00
type: 'income',
category: 'deposit',
2026-05-09 09:01:41 +00:00
receivableAmount: deposit,
receivedAmount: 0,
status: 'unpaid',
billDate: body.startDate,
billMonth: body.startDate.substring(0, 7),
2026-04-20 06:43:09 +00:00
remark: `租约押金 - ${renterName}`,
tenantId: req.user.tenantId,
createBy: req.user.id,
updateBy: req.user.id
});
}
2026-04-22 06:48:32 +00:00
response.created(res, '创建成功', rental);
2026-04-20 06:43:09 +00:00
} catch (error) {
console.error('创建租房记录时出错:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '创建租房失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 更新租房
const updateRental = async (req, res) => {
try {
const { id } = req.params;
const { roomId, renterId, startDate, endDate, paymentType, rent, deposit, operator, waterMeterStart, electricityMeterStart, waterMeterEnd, electricityMeterEnd, status, remark } = req.body;
const rental = await Rental.findOne({
2026-05-09 09:01:41 +00:00
where: { id, tenantId: req.user.tenantId, isDeleted: 0 }
2026-04-20 06:43:09 +00:00
});
if (!rental) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '租房记录不存在');
2026-04-20 06:43:09 +00:00
}
// 处理押金为空时设置为0
const updateDeposit = deposit || 0;
await rental.update({
roomId,
renterId,
startDate,
endDate,
paymentType: paymentType || 'monthly',
rent,
deposit: updateDeposit,
operator: operator || null,
waterMeterStart: waterMeterStart || null,
electricityMeterStart: electricityMeterStart || null,
waterMeterEnd: waterMeterEnd || null,
electricityMeterEnd: electricityMeterEnd || null,
status,
remark,
updateBy: req.user.id
});
2026-04-22 06:48:32 +00:00
response.success(res, '更新成功', rental);
2026-04-20 06:43:09 +00:00
} catch (error) {
2026-04-22 06:48:32 +00:00
response.serverError(res, '更新租房失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 删除租房(软删除)
const deleteRental = async (req, res) => {
try {
const { id } = req.params;
const rental = await Rental.findOne({
2026-05-09 09:01:41 +00:00
where: { id, tenantId: req.user.tenantId, isDeleted: 0 }
2026-04-20 06:43:09 +00:00
});
if (!rental) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '租房记录不存在');
2026-04-20 06:43:09 +00:00
}
await rental.update({
isDeleted: 1,
updateBy: req.user.id
});
2026-04-22 06:48:32 +00:00
response.success(res, '租房记录删除成功');
2026-04-20 06:43:09 +00:00
} catch (error) {
2026-04-22 06:48:32 +00:00
response.serverError(res, '删除租房失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 退租处理
const terminateRental = async (req, res) => {
try {
const { id } = req.params;
const { waterMeterEnd, electricityMeterEnd, remark } = req.body;
const rental = await Rental.findOne({
2026-05-09 09:01:41 +00:00
where: { id, tenantId: req.user.tenantId, isDeleted: 0 },
2026-04-20 06:43:09 +00:00
include: [
{
model: Room,
where: { isDeleted: 0 },
include: [
{
model: Apartment,
where: { isDeleted: 0 }
}
]
},
{
model: Renter
}
]
});
if (!rental) {
2026-04-22 06:48:32 +00:00
return response.notFound(res, '租房记录不存在');
2026-04-20 06:43:09 +00:00
}
if (rental.status !== 'active') {
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '只有生效中的租约可以退租');
2026-04-20 06:43:09 +00:00
}
const room = rental.Room;
const apartment = room.Apartment;
const renterName = rental.Renter ? rental.Renter.name : '';
// 更新租约信息
await rental.update({
status: 'expired',
waterMeterEnd: waterMeterEnd || null,
electricityMeterEnd: electricityMeterEnd || null,
remark: remark ? `${rental.remark || ''}\n退租备注:${remark}` : rental.remark,
updateBy: req.user.id
});
// 生成水电费账单(如果有读数差异)
if (waterMeterEnd && rental.waterMeterStart) {
const waterUsage = parseFloat(waterMeterEnd) - parseFloat(rental.waterMeterStart);
if (waterUsage > 0 && apartment.waterPrice) {
const waterAmount = waterUsage * parseFloat(apartment.waterPrice);
await Bill.create({
2026-05-09 09:01:41 +00:00
billNo: 'B' + Date.now(),
2026-04-20 06:43:09 +00:00
rentalId: rental.id,
roomId: room.id,
2026-05-09 09:01:41 +00:00
renterId: rental.renterId,
2026-04-20 06:43:09 +00:00
type: 'income',
category: 'water',
2026-05-09 09:01:41 +00:00
receivableAmount: waterAmount,
receivedAmount: 0,
status: 'unpaid',
billDate: new Date(),
2026-04-20 06:43:09 +00:00
remark: `退租水费 - ${renterName}(用量:${waterUsage.toFixed(2)}吨)`,
tenantId: req.user.tenantId,
createBy: req.user.id,
updateBy: req.user.id
});
}
}
if (electricityMeterEnd && rental.electricityMeterStart) {
const electricityUsage = parseFloat(electricityMeterEnd) - parseFloat(rental.electricityMeterStart);
if (electricityUsage > 0 && apartment.electricityPrice) {
const electricityAmount = electricityUsage * parseFloat(apartment.electricityPrice);
await Bill.create({
2026-05-09 09:01:41 +00:00
billNo: 'B' + Date.now() + '1',
2026-04-20 06:43:09 +00:00
rentalId: rental.id,
roomId: room.id,
2026-05-09 09:01:41 +00:00
renterId: rental.renterId,
2026-04-20 06:43:09 +00:00
type: 'income',
category: 'electricity',
2026-05-09 09:01:41 +00:00
receivableAmount: electricityAmount,
receivedAmount: 0,
status: 'unpaid',
billDate: new Date(),
2026-04-20 06:43:09 +00:00
remark: `退租电费 - ${renterName}(用量:${electricityUsage.toFixed(2)}度)`,
tenantId: req.user.tenantId,
createBy: req.user.id,
updateBy: req.user.id
});
}
}
// 更新房间状态为空房
await Room.update(
{ status: 'empty', rentalStatus: 'normal' },
{ where: { id: room.id } }
);
2026-04-22 06:48:32 +00:00
response.success(res, '退租处理成功', rental);
2026-04-20 06:43:09 +00:00
} catch (error) {
console.error('退租处理时出错:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '退租处理失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 获取所有租房(不分页)
const listRentals = async (req, res) => {
try {
// 先检查并更新租房状态
2026-05-09 09:01:41 +00:00
await checkAndUpdateRentalStatus(req.user.tenantId);
2026-04-20 06:43:09 +00:00
const {
apartmentId,
roomId,
renterName,
status,
startDateFrom,
startDateTo,
endDateFrom,
endDateTo
} = req.query;
// 构建查询条件
2026-05-09 09:01:41 +00:00
const where = { tenantId: req.user.tenantId, isDeleted: 0 };
2026-04-20 06:43:09 +00:00
if (status) {
where.status = status;
}
if (roomId) {
where.roomId = roomId;
}
if (startDateFrom && startDateTo) {
where.startDate = { [Op.between]: [new Date(startDateFrom), new Date(startDateTo)] };
}
if (endDateFrom && endDateTo) {
where.endDate = { [Op.between]: [new Date(endDateFrom), new Date(endDateTo)] };
}
// 构建包含关系
const include = [
{
model: Room,
where: {
isDeleted: 0,
...(apartmentId ? { apartmentId } : {})
},
include: [
{
model: Apartment,
where: { isDeleted: 0 }
}
]
},
{
model: Renter,
where: renterName ? { name: { [Op.like]: `%${renterName}%` } } : undefined,
required: !!renterName
}
];
// 查询租房数据
const rentals = await Rental.findAll({
where,
include,
order: [['createTime', 'DESC']] // 按创建时间倒序排序
});
// 格式化数据
const formattedRentals = rentals.map(formatRentalData);
// 返回结果
2026-04-22 06:48:32 +00:00
response.success(res, '获取成功', formattedRentals);
2026-04-20 06:43:09 +00:00
} catch (error) {
2026-04-22 06:48:32 +00:00
response.serverError(res, '获取租房列表失败', error);
2026-04-20 06:43:09 +00:00
}
};
// 创建租房(包含租客、水电表读数)- 整合接口
const createRentalWithRenter = async (req, res) => {
const transaction = await require('../config/db').transaction();
try {
console.log('接收到的整合请求数据:', req.body);
const {
// 租客信息
renterName,
renterPhone,
renterIdCard,
// 租房信息
roomId,
paymentType = 'monthly',
startDate,
endDate,
rent,
deposit = 0,
operator,
remark,
// 水电表读数
waterStartReading,
electricStartReading
} = req.body;
const tenantId = req.user.tenantId;
const createBy = req.user.id;
// 参数验证
if (!renterName) {
await transaction.rollback();
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '租客姓名不能为空');
2026-04-20 06:43:09 +00:00
}
if (!roomId) {
await transaction.rollback();
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '房间ID不能为空');
2026-04-20 06:43:09 +00:00
}
if (!startDate || !endDate) {
await transaction.rollback();
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '开始日期和结束日期不能为空');
2026-04-20 06:43:09 +00:00
}
if (!rent) {
await transaction.rollback();
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '租金不能为空');
2026-04-20 06:43:09 +00:00
}
const parsedRoomId = parseInt(roomId);
if (isNaN(parsedRoomId)) {
await transaction.rollback();
2026-04-22 06:48:32 +00:00
return response.badRequest(res, '无效的房间ID');
2026-04-20 06:43:09 +00:00
}
// 1. 创建租客
const renterData = {
name: renterName,
phone: renterPhone || null,
idCard: renterIdCard || null,
tenantId,
createBy,
status: 'active'
};
const renter = await Renter.create(renterData, { transaction });
console.log('租客创建成功:', renter.id);
// 2. 创建租房记录
const rentalData = {
roomId: parsedRoomId,
renterId: renter.id,
startDate,
endDate,
paymentType,
rent,
deposit,
operator: operator || null,
waterMeterStart: waterStartReading || null,
electricityMeterStart: electricStartReading || null,
status: 'active',
remark: remark || null,
tenantId,
createBy,
updateBy: createBy
};
const rental = await Rental.create(rentalData, { transaction });
console.log('租房记录创建成功:', rental.id);
// 3. 更新房间状态为已租
await Room.update(
{ status: 'rented', rentalStatus: 'normal' },
{ where: { id: parsedRoomId }, transaction }
);
// 生成账单编号
const generateBillNo = () => {
const date = new Date()
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0')
return `B${year}${month}${day}${random}`
}
// 4. 创建租金账单
await Bill.create({
billNo: generateBillNo(),
rentalId: rental.id,
roomId: parsedRoomId,
renterId: renter.id,
type: 'income',
category: 'rent',
receivableAmount: rent,
receivedAmount: 0,
status: 'unpaid',
billDate: startDate,
billMonth: startDate.substring(0, 7),
remark: `租约租金 - ${renterName}`,
tenantId,
createBy,
updateBy: createBy
}, { transaction });
// 5. 创建押金账单(如果有押金)
if (deposit > 0) {
await Bill.create({
billNo: generateBillNo(),
rentalId: rental.id,
roomId: parsedRoomId,
renterId: renter.id,
type: 'income',
category: 'deposit',
receivableAmount: deposit,
receivedAmount: 0,
status: 'unpaid',
billDate: startDate,
billMonth: startDate.substring(0, 7),
remark: `租约押金 - ${renterName}`,
tenantId,
createBy,
updateBy: createBy
}, { transaction });
}
// 6. 创建水表读数记录(如果有)
if (waterStartReading !== null && waterStartReading !== '' && waterStartReading !== undefined) {
// 获取公寓水费单价
const room = await Room.findByPk(parsedRoomId, {
include: [{ model: Apartment, as: 'apartment' }],
transaction
});
const waterPrice = room?.apartment?.waterPrice || 0;
await MeterReading.create({
roomId: parsedRoomId,
renterId: renter.id,
rentalId: rental.id,
meterType: 'water',
previousReading: 0,
currentReading: waterStartReading,
usage: 0,
unitPrice: waterPrice,
amount: 0,
billMonth: startDate.substring(0, 7),
readingDate: startDate,
remark: '入住时水表读数',
tenantId,
createBy,
updateBy: createBy
}, { transaction });
console.log('水表读数记录创建成功');
}
// 7. 创建电表读数记录(如果有)
if (electricStartReading !== null && electricStartReading !== '' && electricStartReading !== undefined) {
// 获取公寓电费单价
const room = await Room.findByPk(parsedRoomId, {
include: [{ model: Apartment, as: 'apartment' }],
transaction
});
const electricityPrice = room?.apartment?.electricityPrice || 0;
await MeterReading.create({
roomId: parsedRoomId,
renterId: renter.id,
rentalId: rental.id,
meterType: 'electricity',
previousReading: 0,
currentReading: electricStartReading,
usage: 0,
unitPrice: electricityPrice,
amount: 0,
billMonth: startDate.substring(0, 7),
readingDate: startDate,
remark: '入住时电表读数',
tenantId,
createBy,
updateBy: createBy
}, { transaction });
console.log('电表读数记录创建成功');
}
// 提交事务
await transaction.commit();
2026-04-22 06:48:32 +00:00
response.created(res, '创建成功', {
rentalId: rental.id,
renterId: renter.id,
roomId: parsedRoomId
2026-04-20 06:43:09 +00:00
});
} catch (error) {
// 回滚事务
await transaction.rollback();
console.error('创建租房(整合)时出错:', error);
2026-04-22 06:48:32 +00:00
response.serverError(res, '创建租房失败', error);
2026-04-20 06:43:09 +00:00
}
};
module.exports = {
getAllRentals,
listRentals,
getRentalById,
createRental,
updateRental,
deleteRental,
terminateRental,
createRentalWithRenter
};