room reservation model, controller, seeder and migration files added
This commit is contained in:
@@ -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' })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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(),
|
||||
})
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
import { BaseSchema } from '@adonisjs/lucid/schema'
|
||||
|
||||
export default class extends BaseSchema {
|
||||
protected tableName = 'rooms'
|
||||
|
||||
async up() {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id')
|
||||
table.string('name').notNullable()
|
||||
table.integer('capacity').notNullable()
|
||||
table.string('description').nullable()
|
||||
|
||||
table.timestamp('created_at')
|
||||
table.timestamp('updated_at')
|
||||
})
|
||||
}
|
||||
|
||||
async down() {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { BaseSchema } from '@adonisjs/lucid/schema'
|
||||
|
||||
export default class extends BaseSchema {
|
||||
protected tableName = 'reservations'
|
||||
|
||||
async up() {
|
||||
this.schema.createTable(this.tableName, (table) => {
|
||||
table.increments('id')
|
||||
table.integer('room_id').unsigned().references('id').inTable('rooms').onDelete('CASCADE')
|
||||
table.string('customer_name').notNullable()
|
||||
table.string('customer_phone').notNullable()
|
||||
table.integer('guests_count').notNullable()
|
||||
table.timestamp('starts_at').notNullable()
|
||||
table.timestamp('ends_at').notNullable()
|
||||
table.string('status').defaultTo('confirmed') // confirmed, cancelled
|
||||
table.text('notes').nullable()
|
||||
|
||||
table.timestamp('created_at')
|
||||
table.timestamp('updated_at')
|
||||
})
|
||||
}
|
||||
|
||||
async down() {
|
||||
this.schema.dropTable(this.tableName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { BaseSeeder } from '@adonisjs/lucid/seeders'
|
||||
import Room from '#models/room'
|
||||
|
||||
export default class extends BaseSeeder {
|
||||
async run() {
|
||||
await Room.updateOrCreate(
|
||||
{ name: 'Kisterem' },
|
||||
{
|
||||
name: 'Kisterem',
|
||||
capacity: 20,
|
||||
description: 'Cozy small room for private gatherings.',
|
||||
}
|
||||
)
|
||||
|
||||
await Room.updateOrCreate(
|
||||
{ name: 'Nagyterem' },
|
||||
{
|
||||
name: 'Nagyterem',
|
||||
capacity: 50,
|
||||
description: 'Large hall for big events and weddings.',
|
||||
}
|
||||
)
|
||||
|
||||
await Room.updateOrCreate(
|
||||
{ name: 'Terasz' },
|
||||
{
|
||||
name: 'Terasz',
|
||||
capacity: 30,
|
||||
description: 'Outdoor terrace with a view.',
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user