room reservation model, controller, seeder and migration files added

This commit is contained in:
Kiss Dávid
2026-04-01 12:13:38 +02:00
parent 821ec88882
commit b281724a1a
7 changed files with 330 additions and 0 deletions
@@ -0,0 +1,128 @@
import type { HttpContext } from '@adonisjs/core/http'
import Room from '#models/room'
import Reservation from '#models/reservation'
import {
createReservationValidator,
updateReservationValidator,
createRoomValidator,
updateRoomValidator,
} from '#validators/reservation'
import logger from '@adonisjs/core/services/logger'
export default class RoomReservationsController {
/**
* List all rooms.
*/
async listRooms() {
return Room.all()
}
/**
* Create a new room (Admin only).
*/
async createRoom({ request, response }: HttpContext) {
try {
const data = await request.validateUsing(createRoomValidator)
const room = await Room.create(data)
return room
} catch (error) {
logger.error('Room creation failed: %s', error)
return response.internalServerError({ message: 'Room creation failed' })
}
}
/**
* Update a room (Admin only).
*/
async updateRoom({ request, response }: HttpContext) {
try {
const data = await request.validateUsing(updateRoomValidator)
const room = await Room.find(data.id)
if (!room) {
return response.notFound({ message: 'Room not found' })
}
room.merge(data)
await room.save()
return room
} catch (error) {
logger.error('Room update failed: %s', error)
return response.internalServerError({ message: 'Room update failed' })
}
}
/**
* Delete a room (Admin only).
*/
async deleteRoom({ request, response }: HttpContext) {
const { id } = request.body()
try {
const room = await Room.find(id)
if (!room) {
return response.notFound({ message: 'Room not found' })
}
await room.delete()
return response.ok({ message: 'Room deleted' })
} catch (error) {
logger.error('Room deletion failed: %s', error)
return response.internalServerError({ message: 'Room deletion failed' })
}
}
/**
* List all reservations (Frontend/Admin).
*/
async index() {
return Reservation.query().preload('room').orderBy('startsAt', 'desc')
}
/**
* Create a new reservation (Admin only).
*/
async store({ request, response }: HttpContext) {
try {
const data = await request.validateUsing(createReservationValidator)
const reservation = await Reservation.create(data)
return reservation
} catch (error) {
logger.error('Reservation creation failed: %s', error)
return response.internalServerError({ message: 'Reservation creation failed' })
}
}
/**
* Update a reservation (Admin only).
*/
async update({ request, response }: HttpContext) {
try {
const data = await request.validateUsing(updateReservationValidator)
const reservation = await Reservation.find(data.id)
if (!reservation) {
return response.notFound({ message: 'Reservation not found' })
}
reservation.merge(data)
await reservation.save()
return reservation
} catch (error) {
logger.error('Reservation update failed: %s', error)
return response.internalServerError({ message: 'Reservation update failed' })
}
}
/**
* Delete a reservation (Admin only).
*/
async destroy({ request, response }: HttpContext) {
const { id } = request.body()
try {
const reservation = await Reservation.find(id)
if (!reservation) {
return response.notFound({ message: 'Reservation not found' })
}
await reservation.delete()
return response.ok({ message: 'Reservation deleted' })
} catch (error) {
logger.error('Reservation deletion failed: %s', error)
return response.internalServerError({ message: 'Reservation deletion failed' })
}
}
}
+42
View File
@@ -0,0 +1,42 @@
import { DateTime } from 'luxon'
import { BaseModel, column, belongsTo } from '@adonisjs/lucid/orm'
import type { BelongsTo } from '@adonisjs/lucid/types/relations'
import Room from '#models/room'
export default class Reservation extends BaseModel {
@column({ isPrimary: true })
declare id: number
@column()
declare roomId: number
@column()
declare customerName: string
@column()
declare customerPhone: string
@column()
declare guestsCount: number
@column.dateTime()
declare startsAt: DateTime
@column.dateTime()
declare endsAt: DateTime
@column()
declare status: 'confirmed' | 'cancelled'
@column()
declare notes: string | null
@belongsTo(() => Room)
declare room: BelongsTo<typeof Room>
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime
}
+27
View File
@@ -0,0 +1,27 @@
import { DateTime } from 'luxon'
import { BaseModel, column, hasMany } from '@adonisjs/lucid/orm'
import type { HasMany } from '@adonisjs/lucid/types/relations'
import Reservation from '#models/reservation'
export default class Room extends BaseModel {
@column({ isPrimary: true })
declare id: number
@column()
declare name: string
@column()
declare capacity: number
@column()
declare description: string | null
@hasMany(() => Reservation)
declare reservations: HasMany<typeof Reservation>
@column.dateTime({ autoCreate: true })
declare createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
declare updatedAt: DateTime
}
+53
View File
@@ -0,0 +1,53 @@
import vine from '@vinejs/vine'
export const createReservationValidator = vine.compile(
vine.object({
roomId: vine.number().exists(async (db, value) => {
const room = await db.from('rooms').where('id', value).first()
return !!room
}),
customerName: vine.string().trim(),
customerPhone: vine.string().trim(),
guestsCount: vine.number().positive(),
startsAt: vine.string().trim(),
endsAt: vine.string().trim(),
notes: vine.string().trim().optional(),
})
)
export const updateReservationValidator = vine.compile(
vine.object({
id: vine.number(),
roomId: vine
.number()
.exists(async (db, value) => {
const room = await db.from('rooms').where('id', value).first()
return !!room
})
.optional(),
customerName: vine.string().trim().optional(),
customerPhone: vine.string().trim().optional(),
guestsCount: vine.number().positive().optional(),
startsAt: vine.string().trim().optional(),
endsAt: vine.string().trim().optional(),
status: vine.enum(['confirmed', 'cancelled']).optional(),
notes: vine.string().trim().optional(),
})
)
export const createRoomValidator = vine.compile(
vine.object({
name: vine.string().trim(),
capacity: vine.number().positive(),
description: vine.string().trim().optional(),
})
)
export const updateRoomValidator = vine.compile(
vine.object({
id: vine.number(),
name: vine.string().trim().optional(),
capacity: vine.number().positive().optional(),
description: vine.string().trim().optional(),
})
)