diff --git a/modules/adminBookings/index.js b/modules/adminBookings/index.js index d4539c3..dbb0c31 100644 --- a/modules/adminBookings/index.js +++ b/modules/adminBookings/index.js @@ -68,9 +68,9 @@ function getBookingsForAdmin(req, res) { const params = []; if (search) { - whereClause += ' AND (b.name LIKE ? OR b.phone LIKE ? OR b.room_type LIKE ?)'; + whereClause += ' AND (b.name LIKE ? OR b.phone LIKE ? OR b.room_type LIKE ? OR r.name LIKE ?)'; const searchTerm = `%${search}%`; - params.push(searchTerm, searchTerm, searchTerm); + params.push(searchTerm, searchTerm, searchTerm, searchTerm); } if (statusFilter && statusFilter !== 'all') { @@ -78,7 +78,7 @@ function getBookingsForAdmin(req, res) { params.push(statusFilter); } - db.get(`SELECT COUNT(*) as total FROM bookings b WHERE ${whereClause}`, params, (err, countRow) => { + db.get(`SELECT COUNT(*) as total FROM bookings b LEFT JOIN rooms r ON b.room_id = r.id WHERE ${whereClause}`, params, (err, countRow) => { if (err) { console.error(err); return res.status(500).json({ error: 'Database error' }); @@ -87,8 +87,10 @@ function getBookingsForAdmin(req, res) { const total = countRow.total; const totalPages = Math.ceil(total / limit); - db.all(`SELECT b.*, p.code as promocode_code FROM bookings b + db.all(`SELECT b.*, p.code as promocode_code, r.name as room_name, r.type as room_type + FROM bookings b LEFT JOIN promocodes p ON b.promocode_id = p.id + LEFT JOIN rooms r ON b.room_id = r.id WHERE ${whereClause} ORDER BY b.checkin_date ASC LIMIT ? OFFSET ?`, [...params, limit, offset], (err, rows) => { @@ -123,7 +125,11 @@ function updateBookingStatus(req, res) { db.run(`UPDATE bookings SET status = ? WHERE id = ?`, [status, bookingId], (err) => { if (err) return res.status(500).json({ error: 'Database error' }); logHistory(bookingId, req.user.id, req.user.login, 'status', oldValue, status); - db.get(`SELECT b.*, p.code as promocode_code FROM bookings b LEFT JOIN promocodes p ON b.promocode_id = p.id WHERE b.id = ?`, [bookingId], (err, row) => { + db.get(`SELECT b.*, p.code as promocode_code, r.name as room_name, r.type as room_type + FROM bookings b + LEFT JOIN promocodes p ON b.promocode_id = p.id + LEFT JOIN rooms r ON b.room_id = r.id + WHERE b.id = ?`, [bookingId], (err, row) => { if (err) return res.status(500).json({ error: 'Database error' }); res.json({ message: 'Status updated', booking: row }); }); @@ -133,25 +139,38 @@ function updateBookingStatus(req, res) { function updateBookingRoom(req, res) { const bookingId = parseInt(req.params.id); - const { room_type } = req.body; - const validRooms = config.ROOM_TYPE_LIST; - if (!room_type || !validRooms.includes(room_type)) { - return res.status(400).json({ error: 'Invalid room type. Valid: ' + validRooms.join(', ') }); - } - db.get(`SELECT room_type, checkin_date, checkout_date, discount_percent FROM bookings WHERE id = ?`, [bookingId], (err, row) => { + const { room_id } = req.body; + + db.get(`SELECT * FROM bookings WHERE id = ?`, [bookingId], (err, booking) => { if (err) return res.status(500).json({ error: 'Database error' }); - if (!row) return res.status(404).json({ error: 'Booking not found' }); - const oldValue = row.room_type || 'Не указан'; - const basePrice = config.calculateBasePrice(room_type, row.checkin_date, row.checkout_date); - const discountAmount = Math.round(basePrice * (row.discount_percent || 0) / 100); - const totalPrice = basePrice - discountAmount; - db.run(`UPDATE bookings SET room_type = ?, base_price = ?, discount_amount = ?, total_price = ? WHERE id = ?`, - [room_type, basePrice, discountAmount, totalPrice, bookingId], (err) => { + if (!booking) return res.status(404).json({ error: 'Booking not found' }); + + if (!room_id) { + return res.status(400).json({ error: 'room_id is required' }); + } + + db.get(`SELECT * FROM rooms WHERE id = ?`, [room_id], (err, room) => { if (err) return res.status(500).json({ error: 'Database error' }); - logHistory(bookingId, req.user.id, req.user.login, 'room_type', oldValue, room_type); - db.get(`SELECT b.*, p.code as promocode_code FROM bookings b LEFT JOIN promocodes p ON b.promocode_id = p.id WHERE b.id = ?`, [bookingId], (err, row) => { + if (!room) return res.status(400).json({ error: 'Room not found' }); + + const oldValue = booking.room_name ? booking.room_type + ' — ' + booking.room_name : booking.room_type || 'Не указан'; + const newValue = room.type + ' — ' + room.name; + const basePrice = config.calculateBasePrice(room.type, booking.checkin_date, booking.checkout_date); + const discountAmount = Math.round(basePrice * (booking.discount_percent || 0) / 100); + const totalPrice = basePrice - discountAmount; + + db.run(`UPDATE bookings SET room_id = ?, room_type = ?, base_price = ?, discount_amount = ?, total_price = ? WHERE id = ?`, + [room.id, room.type, basePrice, discountAmount, totalPrice, bookingId], (err) => { if (err) return res.status(500).json({ error: 'Database error' }); - res.json({ message: 'Room updated', booking: row }); + logHistory(bookingId, req.user.id, req.user.login, 'room', oldValue, newValue); + db.get(`SELECT b.*, p.code as promocode_code, r.name as room_name, r.type as room_type + FROM bookings b + LEFT JOIN promocodes p ON b.promocode_id = p.id + LEFT JOIN rooms r ON b.room_id = r.id + WHERE b.id = ?`, [bookingId], (err, row) => { + if (err) return res.status(500).json({ error: 'Database error' }); + res.json({ message: 'Room updated', booking: row }); + }); }); }); }); @@ -167,7 +186,11 @@ function updateBookingComment(req, res) { db.run(`UPDATE bookings SET comment = ? WHERE id = ?`, [comment || null, bookingId], (err) => { if (err) return res.status(500).json({ error: 'Database error' }); logHistory(bookingId, req.user.id, req.user.login, 'comment', oldValue, comment || 'Нет'); - db.get(`SELECT b.*, p.code as promocode_code FROM bookings b LEFT JOIN promocodes p ON b.promocode_id = p.id WHERE b.id = ?`, [bookingId], (err, row) => { + db.get(`SELECT b.*, p.code as promocode_code, r.name as room_name, r.type as room_type + FROM bookings b + LEFT JOIN promocodes p ON b.promocode_id = p.id + LEFT JOIN rooms r ON b.room_id = r.id + WHERE b.id = ?`, [bookingId], (err, row) => { if (err) return res.status(500).json({ error: 'Database error' }); res.json({ message: 'Comment updated', booking: row }); }); @@ -192,10 +215,14 @@ function updateBookingDiscount(req, res) { [discount_percent, discountAmount, totalPrice, bookingId], (err) => { if (err) return res.status(500).json({ error: 'Database error' }); logHistory(bookingId, req.user.id, req.user.login, 'discount_percent', oldValue.toString(), discount_percent.toString()); - db.get(`SELECT b.*, p.code as promocode_code FROM bookings b LEFT JOIN promocodes p ON b.promocode_id = p.id WHERE b.id = ?`, [bookingId], (err, row) => { - if (err) return res.status(500).json({ error: 'Database error' }); - res.json({ message: 'Discount updated', booking: row }); - }); + db.get(`SELECT b.*, p.code as promocode_code, r.name as room_name, r.type as room_type + FROM bookings b + LEFT JOIN promocodes p ON b.promocode_id = p.id + LEFT JOIN rooms r ON b.room_id = r.id + WHERE b.id = ?`, [bookingId], (err, row) => { + if (err) return res.status(500).json({ error: 'Database error' }); + res.json({ message: 'Discount updated', booking: row }); + }); }); }); } @@ -287,7 +314,11 @@ function updateBookingDetails(req, res) { }); }); function finishUpdate() { - db.get(`SELECT b.*, p.code as promocode_code FROM bookings b LEFT JOIN promocodes p ON b.promocode_id = p.id WHERE b.id = ?`, [bookingId], (err, row) => { + db.get(`SELECT b.*, p.code as promocode_code, r.name as room_name, r.type as room_type + FROM bookings b + LEFT JOIN promocodes p ON b.promocode_id = p.id + LEFT JOIN rooms r ON b.room_id = r.id + WHERE b.id = ?`, [bookingId], (err, row) => { if (err) return res.status(500).json({ error: 'Database error' }); res.json({ message: 'Booking details updated', booking: row }); }); diff --git a/modules/bookings/index.js b/modules/bookings/index.js index f86a215..c4c7b6c 100644 --- a/modules/bookings/index.js +++ b/modules/bookings/index.js @@ -30,7 +30,7 @@ function validatePromocode(promocode, callback) { } function createBooking(req, res) { - const { name, phone, adults, children, checkin, checkout, wishes, room, promocode } = req.body; + const { name, phone, adults, children, checkin, checkout, wishes, room, room_id, promocode } = req.body; if (!name || !phone || !adults || !checkin || !checkout) { return res.status(400).json({ error: 'Missing required fields' }); } @@ -46,9 +46,10 @@ function createBooking(req, res) { const safeBasePrice = basePrice || 0; const discountAmount = Math.round(safeBasePrice * discountPercent / 100); const totalPrice = safeBasePrice - discountAmount; - const stmt = db.prepare(`INSERT INTO bookings (name, phone, adults, children, checkin_date, checkout_date, wishes, status, room_type, base_price, discount_percent, discount_amount, total_price, promocode_id) - VALUES (?, ?, ?, ?, ?, ?, ?, 'новая', ?, ?, ?, ?, ?, ?)`); - stmt.run(name, phone, parseInt(adults), parseInt(children || 0), checkin, checkout, wishes || null, room || null, + const roomIdValue = room_id ? parseInt(room_id) : null; + const stmt = db.prepare(`INSERT INTO bookings (name, phone, adults, children, checkin_date, checkout_date, wishes, status, room_type, room_id, base_price, discount_percent, discount_amount, total_price, promocode_id) + VALUES (?, ?, ?, ?, ?, ?, ?, 'новая', ?, ?, ?, ?, ?, ?, ?)`); + stmt.run(name, phone, parseInt(adults), parseInt(children || 0), checkin, checkout, wishes || null, room || null, roomIdValue, safeBasePrice || null, discountPercent || 0, discountAmount || 0, totalPrice || null, promocodeId, function(err) { if (err) { console.error(err); diff --git a/public/admin.html b/public/admin.html index 1575e8a..a4110aa 100644 --- a/public/admin.html +++ b/public/admin.html @@ -626,7 +626,7 @@ function initTabs() { document.getElementById('tab-' + tab).classList.add('active'); if (tab === 'dashboard') loadDashboard(); if (tab === 'users') loadUsers(); - if (tab === 'bookings') { bookingsLoaded = false; loadBookings(); } + if (tab === 'bookings') { bookingsLoaded = false; loadRoomsForBookingEdit(); loadBookings(); } if (tab === 'rooms') loadRooms(); if (tab === 'promocodes') loadPromocodes(); if (tab === 'reviews') loadReviews(); @@ -701,14 +701,14 @@ async function loadDashboard() { document.getElementById('statAdmins').textContent = users.filter(u => u.role === 'admin').length; } catch(e) {} try { - const rows = await api('/api/admin/bookings'); - document.getElementById('statBookings').textContent = rows.length; - document.getElementById('statNew').textContent = rows.filter(r => r.status === 'новая').length; - document.getElementById('recentBookings').innerHTML = rows.filter(r => r.status !== 'отменена' && r.status !== 'выехала').slice(0, 5).map(r => '