Cadê Buffet? is an application that aims to connect potential clients to companies that provide Buffet services. Users can browse through a selection of registered Buffets with different Event Types. Events can be ordered via the app, with scheduled date, guests quantity, and much more. The Order system provides a clear way to create, approve, confirm, or cancel an ordered event, with the interaction of the User and the Buffet provider. Once an order is created, the User and Buffet can chat via the App to discuss details. The Buffet provider can set cancel fines for confirmed orders. After a confirmed Event occurs, the User can Rate the Buffet.
ruby
version 3.0.2
rails
version 7.1.3.2 (if not already installed, bin/setup will automatically install Rails)
libvips
for image processing
To install libvips
in Ubuntu, just run:
sudo apt install libvips
For other OS, see how to install libvips
With Ruby installed, clone this repository via git:
git clone https://github.com/angelomaia/cade-buffet.git
Navigate to the folder:
cd cade-buffet
Run bin/setup:
bin/setup
To avoid any SQLite issues, run:
rails db:reset
Run rails server:
rails server
Access the App via localhost:3000 in your browser:
http://localhost:3000
The whole app was built following TDD (Test-driven development) practices. Hence, there are several system, requests, and unit tests. All tests can be run with the following command:
rspec
Example credentials are set in the seeds, with a preset Order, Rating, and a ready-to-order Buffet with two Event Types. The examples should be installed when running bin/setup:
- To access as Buffet Owner, use:
- Login:
- [email protected]
- Password:
- password
- To access as User, use:
- Login:
- [email protected]
- Password:
- password
- Authentication using Devise
- Sign up and log in as a User
- Sign up and log in as a Buffet Owner
- Register a Buffet as an Owner
- Activate or Deactivate your Buffet as an Owner to make it visible/invisible
- Add Event Types to a Buffet
- Set predefined prices for Events
- Add a cover photo to an Event
- Add Gallery photos to an Event
- Set Cancel Fines for an Event, based on days before order date and a percentage of the total value
- Activate or Deactivate your Event Type as an Owner to make it visible/invisible
- List Buffets
- Search for Buffets by their names, associated Events, or locations
- Orders system
- User can order an Event by inputting date, guest quantity, and location
- Buffet Owner can evaluate an order and approve it by setting the price
- User can confirm the order if approved by the Buffet
- User and Buffet Owner can chat via the Order view page
- Both the User and Buffet can cancel the event, except when confirmed
- Only the User can cancel a confirmed event, but cancel fines may apply
- A User can Rate a Buffet after an ordered event occurs, adding a Grade, a Comment, and optionally adding Photos
- The app provides API endpoints that are further described below
The main API endpoint is a list of all Buffets registered in the app, and can be accessed by:
http://localhost:3000/api/v1/buffets
This path returns an array containing the list of all Buffets registered in the app ordered by name:
[
{
"id": 3,
"name": "Bons Momentos",
"corporate_name": "Bons Momentos Buffet Ltda",
"cnpj": "56473829100",
"phone": "4198526374",
"email": "[email protected]",
"address": "Praça da Estação, 45",
"neighborhood": "Centro",
"city": "Recife",
"state": "PE",
"zipcode": "52000123",
"description": null,
"pix": true,
"debit": false,
"credit": true,
"cash": true,
"owner_id": 3
},
{
"id": 2,
"name": "Celebra",
"corporate_name": "Celebrações e Festas S.A.",
"cnpj": "98765432109",
"phone": "3197654321",
"email": "[email protected]",
"address": "Avenida dos Diamantes, 300",
"neighborhood": "Industrial",
"city": "Belo Horizonte",
"state": "MG",
"zipcode": "52000123",
"description": null,
"pix": false,
"debit": true,
"credit": true,
"cash": true,
"owner_id": 2
},
{
"id": 1,
"name": "Festim",
"corporate_name": "Festim Eventos Ltda",
"cnpj": "12345678901",
"phone": "1198765432",
"email": "[email protected]",
"address": "Rua das Camélias, 58",
"neighborhood": "Jardim",
"city": "São Paulo",
"state": "SP",
"zipcode": "52000123",
"description": null,
"pix": true,
"debit": true,
"credit": true,
"cash": false,
"owner_id": 1
}
]
Attributes:
id
integer : the ID of the Buffet object in the Database
name
string : the Name of the Buffet
corporate_name
string : the legal name of the Buffet
cnpj
string : the registration number of the Buffet
phone
string : the phone of the Buffet
email
string : the email of the Buffet
address
string : the street address of where the Buffet is located
city
string : the city in which the Buffet is located
state
string : the state in which the Buffet is located
zipcode
string : the zipcode of the location
description
string : a brief description of the Buffet
pix
boolean : defines whether the Buffet accepts PIX as the payment method
debit
boolean : defines whether the Buffet accepts debit card as the payment method
credit
boolean : defines whether the Buffet accepts credit card as the payment method
cash
boolean : defines whether the Buffet accepts cash as the payment method
owner_id
integer : the ID of the owner (devise model object) which the Buffet belongs to
Details of a Buffet can also be accessed by ID:
http://localhost:3000/api/v1/buffets/1
This path returns a list of details from the Buffet with ID == 1:
{
"id": 1,
"name": "Festim",
"phone": "1198765432",
"email": "[email protected]",
"address": "Rua das Camélias, 58",
"neighborhood": "Jardim",
"city": "São Paulo",
"state": "SP",
"zipcode": "52000123",
"description": null,
"pix": true,
"debit": true,
"credit": true,
"cash": false,
"owner_id": 1
}
The Event types associated with a Buffet can also be retrieved:
http://localhost:3000/api/v1/buffets/1/event_types
This path returns an array containing all Event Types associated with the Buffet with ID == 1:
[
{
"id": 1,
"name": "Festa de Casamento",
"description": "Festa completa",
"min_people": "20",
"max_people": "100",
"duration": "240",
"menu": "Sushi, mesa de frios, strogonoff",
"alcohol": null,
"decoration": null,
"parking": null,
"location": "exclusive",
"buffet_id": 1,
"price": {
"id": 1,
"base": 5000,
"extra_person": 200,
"extra_hour": 1500,
"weekend_base": null,
"weekend_extra_person": null,
"weekend_extra_hour": null,
"event_type_id": 1
}
},
{
"id": 2,
"name": "Festa Infantil",
"description": "Festa completa",
"min_people": "10",
"max_people": "100",
"duration": "240",
"menu": "Sushi, mesa de frios, strogonoff",
"alcohol": null,
"decoration": null,
"parking": null,
"location": "anywhere",
"buffet_id": 1
}
]
Attributes:
id
integer : the ID of the EventType object in the Database
name
string : the Name of the Event
description
string : a brief description of the Event
min_people
string : the minimum number of people, used to set the base price of the Event
max_people
string : the maximum number of people that the Event can provide for
duration
string : the duration of the Event in minutes
menu
string : a freely described menu for the Event
alcohol
boolean : defines whether the Event provides alcoholic beverages
decoration
boolean : defines whether the Event provides decoration service
parking
boolean : defines whether the Event provide parking or valet services
buffet_id
integer : the ID of the Buffet which the Event belongs to
price
Child Object : an object that belongs_to the EventType, which has_one Price
price.id
integer : the ID of the EventType object in the Database
price.base
float : the base Price for the event, based on the duration and the min_people
price.extra_person
float : additional value per extra person on the min_people quantity
price.extra_hour
float : additional value per extra hour on the Event duration
price.weekend_base
float : base price for weekends
price.weekend_extra_person
float : weekend additional value per extra person on the min_people quantity
price.weekend_extra_hour
float : weekend additional value per extra hour on the Event duration
price.event_type_id
integer : the ID of the EventType which the Price belongs to
An endpoint to check the availability of an event is also provided:
http://localhost:3000/api/v1/availability_check
However, three params need to be passed to the URL: a Date (date), the guest quantity (guests), and the ID of the EventType object (event_type_id):
http://localhost:3000/api/v1/availability_check?date=2024-12-12&guests=50&event_type_id=1
If the date is available (that is, the Buffet has no Event approved OR confirmed for the date AND the guest quantity is equal or less the maximum number of people that the Event can serve), the response should be the expected price of the event:
{
"price": 11000
}
If the date is unavailable, the response should be a warnings array containing one string:
{
"warnings": [
"O Buffet já possui um evento marcado para esta data."
]
}
If the guest quantity is higher than the max_people attribute of the EventType object, the response should be a warnings array containing one string:
{
"warnings": [
"Quantidade de convidados acima do limite."
]
}