This application provides a flexible endpoint for creating or updating reservation details, supporting multiple payload formats without the need for explicit identifiers within the payload. By matching payload schemas to internal specifications, we seamlessly store the data in the corresponding model.attribute
. Administrators can easily add new payload formats by adding in the database.
first_name:string
last_name:string
phone_numbers:string[]
email:string
code:string
start_date:date
end_date:date
nights_count:integer
total_guests_count:integer
adults_count:integer
children_count:integer
infants_count:integer
status:string
host_currency:string
payout_price:money
security_price:money
total_price:money
guest:references
schema:json
provider:string
ReservationServices::ProcessPayload.call(payload:)
This service is the core of this app, which handles the format checking and resource handling.
- All values will be converted into their respective attribute type. Further improvements for specificity can be done.
- All money values will be converted into a money type to avoid float computation errors.
- All included payload formats have unique structure
- All fields from payload format schema is required
- String regex validation
- Date specific format
- Float to Integer or vice versa conversions
- Nested keys to avoid repetition, ie. Payload 2 schema
reservation.xx
- Strict required/optional fields
- PayloadFormat unique schema validation to avoid conflicts
{
"<payload_key_nested_with_dots>": "<model.attribute>"
}
Payload #1
{
"reservation_code": "reservation.code",
"start_date": "reservation.start_date",
"end_date": "reservation.end_at",
"nights": "reservation.nights_count",
"guests": "reservation.total_guests_count",
"adults": "reservation.adults_count",
"children": "reservation.children_count",
"infants": "reservation.infants_count",
"status": "reservation.status",
"guest.first_name": "guest.first_name",
"guest.last_name": "guest.last_name",
"guest.phone": "guest.phone_numbers[]",
"guest.email": "guest.email"
"currency": "reservation.host_currency",
"payout_price": "reservation.payout_price"
"security_price": "reservation.security_price",
"total_price": "reservation.total_price"
}
Payload #2
{
"reservation.code": "reservation.code",
"reservation.start_date": "reservation.start_date",
"reservation.end_date": "reservation.end_date",
"reservation.expected_payout_amount": "reservation.payout_price",
"reservation.guest_details.number_of_adults": "reservation.adults_count",
"reservation.guest_details.number_of_children": "reservation.children_count",
"reservation.guest_details.number_of_infants": "reservation.infant_count",
"reservation.guest_email": "guest.email",
"reservation.guest_first_name": "guest.first_name",
"reservation.guest_last_name": "guest.last_name",
"reservation.guest_phone_numbers": "guest.phone_numbers[]",
"reservation.listing_security_price_accurate": "reservation.security_price",
"reservation.host_currency": "resrevation.host_currency",
"reservation.nights": "reservation.nights_count",
"reservation.status_type": "reservation.status",
"reservation.total_paid_amount_accurate": "reservation.total_price"
}
# Install Ruby Version
rbenv install 3.1.3
# Bundle gemfile
bundle install
# Prepare database
bundle exec rails db:create db:schema:load db:seed
# Run server
bundle exec rails s -p 3000
# Server should be running at port 3000
Note: Aside from the default rails 7 api only gems, money-rails, rubocop, factory_bot, and rspec are included in the Gemfile.
Adding New Payload Formats
# You can create new payload formats by creating in the console. A sample can be seen in the seeds file.
FactoryBot.create(
:payload_format,
provider: "Payload #1",
schema: {
reservation_code: 'reservation.code',
start_date: 'reservation.start_date',
end_date: 'reservation.end_date',
nights: 'reservation.nights_count',
guests: 'reservation.total_guests_count',
adults: 'reservation.adults_count',
children: 'reservation.children_count',
infants: 'reservation.infants_count',
status: 'reservation.status',
'guest.first_name': 'guest.first_name',
'guest.last_name': 'guest.last_name',
'guest.phone': 'guest.phone_numbers',
'guest.email': 'guest.email',
currency: 'reservation.host_currency',
payout_price: 'reservation.payout_price',
security_price: 'reservation.security_price',
total_price: 'reservation.total_price'
}
)
This endpoint can create new reservations from expected payload schema. If a reservation code is already existing, it will attempt to update the existing reservation.
{
"reservation_code": "YYY12345678",
"start_date": "2021-04-14",
"end_date": "2021-04-18",
"nights": 4,
"guests": 4,
"adults": 2,
"children": 2,
"infants": 0,
"status": "accepted",
"guest": {
"first_name": "Wayne",
"last_name": "Woodbridge",
"phone": "639123456789",
"email": "wayne_woodbridge@bnb.com"
},
"currency": "AUD",
"payout_price": "4200.00",
"security_price": "500",
"total_price": "4700.00"
}
200
{
reservation: { reservation_data },
guest: { guest_data }
}
422
{
errors: [validation_errors]
}