Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9f7ec48
rooms migration file
eric-kitagawa Feb 25, 2026
3967f59
Merge branch 'main' into eric/rooms-migration
eric-kitagawa Mar 8, 2026
33cf39f
feat: guest booking migration
eric-kitagawa Mar 9, 2026
f0e18cc
rls fix
manueltorres0 Mar 9, 2026
6fd9bf6
indexes on both tables
manueltorres0 Mar 9, 2026
6a67568
type fix
manueltorres0 Mar 9, 2026
da22ba4
incomplete guest bookings table + endpoint
manueltorres0 Mar 9, 2026
fae3721
server integrated + openapi
manueltorres0 Mar 9, 2026
4fbeb9b
moved getRooms to rooms repo
manueltorres0 Mar 10, 2026
074032b
get guests endpoint
manueltorres0 Mar 10, 2026
9b5449d
changes
manueltorres0 Mar 10, 2026
e6442b9
fixed openapi
manueltorres0 Mar 10, 2026
38df682
remove stale webhook dir
eric-kitagawa Mar 10, 2026
394febf
route for specific guest info
manueltorres0 Mar 10, 2026
9a508e3
cleanup GetBookingsByFloor handler
eric-kitagawa Mar 10, 2026
138b68f
changes to endpoints and fe
manueltorres0 Mar 10, 2026
0bfab1e
changed some models
manueltorres0 Mar 11, 2026
47d04b7
Merge branch 'feat/guest-and-booking-endpoint' into feat/link-backend…
manueltorres0 Mar 11, 2026
40d21eb
bum ass
manueltorres0 Mar 11, 2026
959351a
small refactor of model
manueltorres0 Mar 11, 2026
872212b
swag fix
manueltorres0 Mar 11, 2026
e05f10d
build issues
manueltorres0 Mar 11, 2026
0242c4f
merged guest bookings
manueltorres0 Mar 11, 2026
c3017e5
small fix
manueltorres0 Mar 16, 2026
d10e876
Merge branch 'main' into feat/guest-and-booking-endpoint
manueltorres0 Mar 16, 2026
e4310ad
filtered by hotel id
manueltorres0 Mar 16, 2026
2a5d7d5
Merge branch 'feat/guest-and-booking-endpoint' into feat/link-backend…
manueltorres0 Mar 16, 2026
d9b1aa0
fixes and more fixes
manueltorres0 Mar 16, 2026
b44bf13
pagination
manueltorres0 Mar 16, 2026
be57799
pretty much done
manueltorres0 Mar 17, 2026
05be5dc
final things and removed logs
manueltorres0 Mar 17, 2026
64f5105
uncomment middleware
manueltorres0 Mar 17, 2026
65dfa4c
Merge branch 'main' into feat/link-backend-mobile-guests
manueltorres0 Mar 17, 2026
29728a6
fixes
manueltorres0 Mar 17, 2026
3273d8d
pipeline fix
manueltorres0 Mar 17, 2026
e4aeab0
merged
manueltorres0 Mar 18, 2026
c1e8117
merged main
manueltorres0 Mar 18, 2026
5a02cd7
merged
manueltorres0 Mar 18, 2026
d83d009
swagger fix
manueltorres0 Mar 18, 2026
85e516a
comments
manueltorres0 Mar 23, 2026
defceac
comp refactor
manueltorres0 Mar 23, 2026
522e018
merged main
manueltorres0 Mar 23, 2026
392d3e1
lint
manueltorres0 Mar 23, 2026
3dbe0da
please linter
manueltorres0 Mar 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 109 additions & 69 deletions backend/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,12 @@ basePath: /api/v1
definitions:
CreateGuest:
properties:
email:
example: jane.doe@example.com
type: string
first_name:
example: Jane
type: string
last_name:
example: Doe
type: string
notes:
example: VIP
type: string
phone:
example: +1 (617) 012-3456
type: string
preferences:
example: extra pillows
type: string
profile_picture:
example: https://example.com/john.jpg
type: string
Expand Down Expand Up @@ -83,9 +71,6 @@ definitions:
created_at:
example: "2024-01-02T00:00:00Z"
type: string
email:
example: jane.doe@example.com
type: string
first_name:
example: Jane
type: string
Expand All @@ -95,15 +80,6 @@ definitions:
last_name:
example: Doe
type: string
notes:
example: VIP
type: string
phone:
example: +1 (617) 012-3456
type: string
preferences:
example: extra pillows
type: string
profile_picture:
example: https://example.com/john.jpg
type: string
Expand All @@ -114,6 +90,51 @@ definitions:
example: "2024-01-02T00:00:00Z"
type: string
type: object
GuestBooking:
properties:
arrival_date:
type: string
departure_date:
type: string
guest:
$ref: '#/definitions/Guest'
hotel_id:
example: 521e8400-e458-41d4-a716-446655440000
type: string
id:
example: f353ca91-4fc5-49f2-9b9e-304f83d11914
type: string
room:
$ref: '#/definitions/Room'
status:
$ref: '#/definitions/github_com_generate_selfserve_internal_models.BookingStatus'
type: object
GuestFilters:
properties:
cursor:
type: string
floors:
items:
type: integer
type: array
hotel_id:
type: string
limit:
maximum: 100
minimum: 1
type: integer
required:
- hotel_id
type: object
GuestPage:
properties:
data:
items:
$ref: '#/definitions/GuestWithBooking'
type: array
next_cursor:
type: string
type: object
GuestWithBooking:
properties:
first_name:
Expand All @@ -126,6 +147,12 @@ definitions:
type: string
room_number:
type: integer
required:
- first_name
- floor
- id
- last_name
- room_number
type: object
GuestWithStays:
properties:
Expand Down Expand Up @@ -159,9 +186,11 @@ definitions:
example: extra pillows
type: string
required:
- current_stays
- first_name
- id
- last_name
- past_stays
type: object
Hotel:
properties:
Expand Down Expand Up @@ -293,6 +322,17 @@ definitions:
example: 521ee400-e458-41d4-a716-446655440000
type: string
type: object
Room:
properties:
floor:
type: integer
room_number:
type: integer
room_status:
type: string
suite_type:
type: string
type: object
RoomWithOptionalGuestBooking:
properties:
booking_status:
Expand Down Expand Up @@ -420,78 +460,44 @@ info:
version: "1.0"
paths:
/api/v1/guests:
get:
description: Retrieves guests optionally filtered by floor in which they are
staying
post:
consumes:
- application/json
description: Retrieves guests optionally filtered by floor
parameters:
- description: Hotel ID (UUID)
in: header
name: X-Hotel-ID
required: true
type: string
- description: Floor
in: query
name: number
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/GuestWithBooking'
type: array
"400":
description: Bad Request
schema:
additionalProperties:
type: string
type: object
"500":
description: Internal Server Error
schema:
additionalProperties:
type: string
type: object
security:
- BearerAuth: []
summary: Get Guests
tags:
- guests
post:
consumes:
- application/json
description: Creates a guest with the given data
parameters:
- description: Guest data
- description: Guest filters
in: body
name: request
name: body
required: true
schema:
$ref: '#/definitions/CreateGuest'
$ref: '#/definitions/GuestFilters'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/Guest'
$ref: '#/definitions/GuestPage'
"400":
description: Invalid guest body format
description: Bad Request
schema:
additionalProperties:
type: string
type: object
"500":
description: Internal server error
description: Internal Server Error
schema:
additionalProperties:
type: string
type: object
security:
- BearerAuth: []
summary: Creates a guest
summary: Get Guests
tags:
- guests
/api/v1/guests/{id}:
Expand Down Expand Up @@ -720,6 +726,40 @@ paths:
summary: Get developer member
tags:
- devs
/guest_bookings/floor:
get:
description: Retrieves multiple guest bookings whose booked rooms are in the
provided floors array
parameters:
- description: Comma-separated floor numbers
in: query
name: floors
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/GuestBooking'
type: array
"400":
description: Bad Request
schema:
additionalProperties:
type: string
type: object
"500":
description: Internal Server Error
schema:
additionalProperties:
type: string
type: object
summary: Get guest Bookings By Floor
tags:
- guest-bookings
/hello:
get:
consumes:
Expand Down
65 changes: 65 additions & 0 deletions backend/internal/handler/bookings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package handler

import (
"context"
"strconv"
"strings"

"github.com/generate/selfserve/internal/errs"
"github.com/generate/selfserve/internal/models"
"github.com/gofiber/fiber/v2"
)

type GuestBookingsRepository interface {
FindBookingByFloor(ctx context.Context, floors []int) ([]*models.GuestBooking, error)
}

type GuestBookingHandler struct {
repo GuestBookingsRepository
}

func NewGuestBookingsHandler(repo GuestBookingsRepository) *GuestBookingHandler {
return &GuestBookingHandler{repo: repo}
}

// GetBookingsByFloor godoc
// @Summary Get guest Bookings By Floor
// @Description Retrieves multiple guest bookings whose booked rooms are in the provided floors array
// @Tags guest-bookings
// @Produce json
// @Param floors query string true "Comma-separated floor numbers"
// @Success 200 {object} []models.GuestBooking
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /guest_bookings/floor [get]
func (h *GuestBookingHandler) GetBookingsByFloor(c *fiber.Ctx) error {
floors, err := getQueryFloors(c.Query("floors"))
if err != nil {
return err
}

bookings, err := h.repo.FindBookingByFloor(c.Context(), floors)

if err != nil {
return errs.InternalServerError()
}

return c.JSON(bookings)
}

func getQueryFloors(rawFloors string) ([]int, error) {
if rawFloors == "" {
return nil, errs.BadRequest("Floors must be provided")
}

parts := strings.Split(rawFloors, ",")
floors := make([]int, 0, len(parts))
for _, p := range parts {
floor, err := strconv.Atoi(strings.TrimSpace(p))
if err != nil {
return nil, errs.BadRequest("Floors must be an array of integers")
}
floors = append(floors, floor)
}
return floors, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left this cmt on a your other pr but might be relevant here

I'm missing some context on what you're using this for so I'll just be adding additional info and let you use your best judgement.

If your page only requires to filter by floor, this is ok for now. But typically, filtering should be done using a post endpoint, since it's not really ideal to filter a lot of data using a query parameter. The query body is a much better use case for passing more complicated objects to the backend, and so filtering typically use query bodies to pass their objects/lists instead.

Also note that if you only want to retrieve bookings for rooms 1-50, your query would be very long.

Overall, if it's just fetching this to display a fixed amount that you know is small, than this is fine. Otherwise, I'd advise swapping over to use a POST to pass more complicated objects and data in the body.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot to delete this on this pr too, but this is not needed and dont think it will be in general, so I will delete, if it is needed later on we have to refactor anyway

Loading
Loading