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