This project is an API for a fast food system.
https://miro.com/app/board/uXjVKXKeOYw=/
Link to video that explain this project
This repository contains the source code for a project that implements a domain-driven design (DDD) with hexagonal architecture. The project structure is as follows:
project-root
│── src
│ ├── application
│ │ ├── controllers
│ │ │ ├── CustomerController.ts
│ │ │ ├── OrderController.ts
│ │ │ └── ProductController.ts
│ │ ├── dtos
│ │ │ ├── ComboDto.ts
│ │ │ ├── CustomerDtos.ts
│ │ │ ├── OrderDto.ts
│ │ │ └── ProductDto.ts
│ │ ├── routes
│ │ │ ├── CustomerRoutes.ts
│ │ │ ├── index.ts
│ │ │ ├── OrderRoutes.ts
│ │ │ └── ProductRoutes.ts
│ │ └── schemas
│ │ ├── CreateCustomer.ts
│ │ ├── CreateOrder.ts
│ │ ├── CreateProduct.ts
│ │ ├── DeleteProduct.ts
│ │ ├── EditProduct.ts
│ │ ├── IdentifyCustomerSchema.ts
│ │ ├── ListOrders.ts
│ │ └── ListProductsByCategory.ts
│ ├── config
│ │ └── app.ts
│ ├── core
│ │ ├── domain
│ │ │ ├── entities
│ │ │ │ ├── Combo.ts
│ │ │ │ ├── Customer.ts
│ │ │ │ ├── Order.ts
│ │ │ │ └── Product.ts
│ │ │ ├── events
│ │ │ │ ├── ComboEvents.ts
│ │ │ │ ├── CustomerEvents.ts
│ │ │ │ ├── OrderEvents.ts
│ │ │ │ └── ProductEvents.ts
│ │ │ ├── use-cases
│ │ │ │ ├── ComboUseCase.ts
│ │ │ │ ├── CustomerUseCase.ts
│ │ │ │ ├── OrderUseCase.ts
│ │ │ │ └── ProductUseCase.ts
│ │ │ └── value-objects
│ │ │ ├── CPF.ts
│ │ │ ├── OrderStatus.ts
│ │ │ ├── PaymentStatus.ts
│ │ │ ├── ProductCategory.ts
│ │ │ └── ProductImage.ts
│ │ └── repositories
│ │ ├── ComboRepository.ts
│ │ ├── CustomerRepository.ts
│ │ ├── OrderRepository.ts
│ │ └── ProductRepository.ts
│ ├── index.ts
│ └── infra
│ └── repositories
│ ├── memory
│ │ ├── ComboRepository.ts
│ │ ├── CustomerRepository.ts
│ │ ├── OrderRepository.ts
│ │ └── ProductRepository.ts
│ └── prisma
│ ├── ComboRepository.ts
│ ├── CustomerRepository.ts
│ ├── index.ts
│ ├── OrderRepository.ts
│ └── ProductRepository.ts
├── tests
└── README.md
Product.ts
: Defines theProduct
entity with properties such ascategory
,price
,description
, andimages
.ProductRepository.ts
: Interface for the product repository, including methods such asaddProduct
,editProduct
, andremoveProduct
.ProductEvents.ts
: Events likeProductRegistered
,ProductEdited
, andProductRemoved
.
Order.ts
: Aggregate managing orders, including methods to add products or combos to the order.OrderRepository.ts
: Interface for the order repository, responsible for saving and retrieving orders.OrderEvents.ts
: Events likeOrderCreated
,OrderUpdated
, andOrderConfirmed
.
Customer.ts
: Entity representing the customer, including data such asCPF
,name
, andemail
.CustomerRepository.ts
: Interface for the customer repository, including methods for creating and managing customer information.CustomerEvents.ts
: Events likeCustomerRegistered
andCustomerUpdated
.
Combo.ts
: Aggregate for managing combos, which are collections of products.ComboRepository.ts
: Interface for the combo repository.ComboEvents.ts
: Events likeComboCreated
andComboUpdated
.
ProductUseCase.ts
: UseCases related to product management.OrderUseCase.ts
: UseCases for handling orders, including confirmation and status updates.CustomerUseCase.ts
: UseCases for managing customers, including registration and data updates.ComboUseCase.ts
: UseCases for managing the creation and modification of combos.
Please refer to the individual files for more details on their implementation.
The data model presented represents a system for managing fast-food orders. It includes entities for customers, products, orders, combos and product images.
- Attributes:
- id (PK): serial
- cpf: text (unique)
- name: text
- email: text (unique)
- Relationships:
- One-to-Many with Order
- Attributes:
- id (PK): serial
- name: text
- category: text
- price: numeric(65,30)
- description: text
- Relationships:
- One-to-Many with ProductImages
- Many-to-Many with Combo through ComboProducts
- Attributes:
- id (PK): serial
- productId (FK): integer
- url: text
- Relationships:
- Many-to-One with Product
- Attributes:
- id (PK): serial
- customer_id (FK): integer
- created_at: timestamp(3)
- status: text
- payment_status: text
- payment_gateway_id: text
- Relationships:
- Many-to-One with Customer
- One-to-Many with Combo
- Attributes:
- id (PK): serial
- order_id (FK): integer
- Relationships:
- Many-to-One with Order
- Many-to-Many with Product through ComboProducts
- Attributes:
- product_id (PK, FK): integer
- combo_id (PK, FK): integer
- created_at: timestamp(3)
- Relationships:
- Represents the Many-to-Many relationship between Combo and Product
The data model presented is implemented in a relational database, specifically PostgreSQL. This choice is justified by the following factors:
-
Relational data structure: The system requires a well-structured data model with clear relationships between entities, which is ideal for relational databases.
-
Data Integrity: PostgreSQL offers robust support for primary keys, foreign keys and constraints, ensuring referential integrity and data consistency.
-
ACID Transactions: For an ordering system, it is crucial to have support for ACID transactions (Atomicity, Consistency, Isolation, Durability), which PostgreSQL provides.
-
Scalability: PostgreSQL is known for its good performance and ability to handle large volumes of data, which is important for an ordering system that can grow over time.
-
Advanced Features: PostgreSQL offers advanced features such as indexes, views, stored procedures and triggers, which can be useful for future optimizations and complex business logic.
-
ORM compatibility: The use of capitalized table names suggests the use of an ORM (possibly Prisma, given the table name _prisma_migrations). PostgreSQL has excellent support for several ORM tools.
-
Open Source and Active Community: Being open source, PostgreSQL has an active community, extensive documentation and is constantly updated with new features and security improvements.
-
Flexible Data Types: PostgreSQL supports a wide variety of data types, including JSON, which can be useful for storing semi-structured data in the future.
The data model was designed following the principles of normalization, reaching up to Third Normal Form (3NF) and possibly Boyce-Codd Normal Form (BCNF) in all its tables. This ensures that redundancy and problematic dependencies in the data are minimized.
All tables are in 1NF because:
- Each column contains atomic (indivisible) values
- There are no repetitive groups
- Each table has a defined primary key
Example: The “Customer” table has a primary key (id) and all its attributes are atomic.
The tables are in 2NF because:
- They are in 1NF
- All non-key attributes are totally dependent on the primary key
Example: In the “Product” table, all the attributes (name, category, price, description) are totally dependent on the primary key (id).
The tables are in 3NF because:
- They are in 2NF
- There are no transitive dependencies between non-key attributes
Example: In the “Order” table, there are no obvious transitive dependencies between the non-key attributes.
Applying these normal forms to the data model helps to:
- minimizing data redundancy
- Ensuring data integrity
- Facilitating database maintenance and updating
- Improve the flexibility of the schema for future extensions
This standardized structure provides a solid foundation for the system, enabling efficient and consistent management of data related to fast-food orders.
-
Clone the repository.
-
Build the project.
-
Run in the terminal
docker compose build
-
-
Start the application.
-
Run in the terminal
docker compose up
-
-
Clone the repository.
-
Build the app image and push it to Docker Hub
-
Run in the terminal
sudo docker build -t <your_username>/<your_image_name>:<image_version> docker push <your_username>/<your_image_name>:<image_version>
-
-
Create PG database.
-
Run in the terminal
kubectl apply -f /K8S/db kubectl apply -f /K8S/app
-
To run the project, follow these steps:
-
Clone the repository.
-
Install the dependencies.
-
Run in the terminal
docker compose up db
-
-
Build the project.
-
Run in the other terminal
yarn build yarn migrate
-
-
Start the application.
yarn dev
-
Access the application http://localhost:3000/
Access the application http://localhost:3000/documentation
or
Access the webpage from swagger.json
-
Access container
<!-- For Docker --> docker exec -it postgres_container bash <!-- For K8S --> kubectl exec -it <pod_name> bash
-
Conect database
psql -U fast-food -d fast-food
-
List tables
\dt
After setup de application, run:
yarn test
After setup de application standalone, run:
yarn test:cucumber
The GitHub Actions workflow is designed to automate the process of building and publishing the Docker image for this repository. It ensures that the Docker image is built on every push to any branch and conditionally publishes it to GitHub Container Registry on merges to the main
branch.
The workflow is triggered automatically on every push to any branch. Additionally, it includes a conditional step that publishes the Docker image to GitHub Container Registry when changes are merged into the main
branch.
The workflow includes a conditional step that checks if the current branch is main
. If it is, the Docker image is published to GitHub Container Registry under the repository owner's profile.
Feel free to explore the code and make any necessary modifications to suit your needs.
Use the tags:
feat: (new feature for the user, not a new feature for build script) fix: (bug fix for the user, not a fix to a build script) docs: (changes to the documentation) style: (formatting, missing semi colons, etc; no production code change) refactor: (refactoring production code, eg. renaming a variable) test: (adding missing tests, refactoring tests; no production code change) chore: (updating grunt tasks etc; no production code change)
Ref.: Semantic Commit Messages
We welcome contributions to this project. Please follow the guidelines below to contribute:
- Fork the repository.
- Create a new branch for your feature or bugfix.
- Make your changes and commit them with a clear and concise commit message.
- Push your changes to your forked repository.
- Create a pull request to the main repository.
- Use clear and descriptive commit messages.
- Follow the conventional commit format:
type(scope): message
. - Example:
feat(auth): add user authentication
.
This project is licensed under the MIT License. See the LICENSE file for more information.