diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..acb35f4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,9 @@ +repos: + + # Next hooks are Code Quality hooks. + - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.14.0 + hooks: + - id: pretty-format-golang + args: + - --autofix \ No newline at end of file diff --git a/README.md b/README.md index b1d0676..825691e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=pangolin-do-golang_tech-challenge&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=pangolin-do-golang_tech-challenge) ![Known Vulnerabilities](https://snyk.io/test/github/pcbarretos/pangolin-do-golang/tech-challenge/badge.svg) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=pangolin-do-golang_tech-challenge&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=pangolin-do-golang_tech-challenge) ![Known Vulnerabilities](https://snyk.io/test/github/pcbarretos/pangolin-do-golang/tech-challenge-customer-api/badge.svg) Miro Board: https://miro.com/app/board/uXjVKVoZwos=/?share_link_id=718027124865 -# Tech Challenge +# Tech Challenge Customer API ## Install @@ -45,7 +45,7 @@ docker compose build docker compose up -d -curl --request GET --url http://localhost:8080/health +curl --request GET --url http://localhost:8085/health ## Expected response = Status Code 200 @@ -59,7 +59,7 @@ Go to http://localhost:8080/swagger/index.html#/ after the application is runnin ## Guide -Follow the guide (in portuguese) for a step-by-step guide to the project [here](https://github.com/pangolin-do-golang/tech-challenge/wiki/Guia-de-uso-da-API). +Follow the guide (in portuguese) for a step-by-step guide to the project [here](https://github.com/pangolin-do-golang/tech-challenge-customer-api/wiki/Guia-de-uso-da-API). ## Stack @@ -109,7 +109,7 @@ The documentation can be founded at the path `/docs/swagger.yaml` or accessing t ## Infrastructure -[Requirements Infrastructure](https://github.com/pangolin-do-golang/tech-challenge/blob/main/terraform/README.md) +[Requirements Infrastructure](https://github.com/pangolin-do-golang/tech-challenge-customer-api/blob/main/terraform/README.md) ## Kubernetes @@ -125,7 +125,7 @@ The order of execution is: You can forward the port with the following command: ```bash -kubectl port-forward svc/tech-challenge-service 4000:80 -n dev +kubectl port-forward svc/tech-challenge-customer-api-service 4000:80 -n dev ``` ### Kubernates Architecture @@ -137,11 +137,8 @@ kubectl port-forward svc/tech-challenge-service 4000:80 -n dev - `cmd`: Application entry point directory for the application's main entry points, dependency injection, or commands. The web subdirectory contains the main entry point to the REST API. - `internal`: Directory to contain application code that should not be exposed to external packages. - `core`: Directory that contains the application's core business logic. - - `cart`: Directory contains definition of the entity's heights, interfaces, repository and service of the entity Cart. - `customer`: Directory contains definition of the entity's heights, interfaces, repository and service of the entity Customer. - - `order`: Directory contains definition of the entity's heights, interfaces, repository and service of the entity Order. - - `product`: Directory contains definition of the entity's heights, interfaces, repository and service of the entity Product. - `adapters`: Directory to contain external services that will interact with the application core. - `db`: Directory contains the implementation of the repositories. - `rest`: Directory that contains the definition of the application's controllers and handlers for manipulating data provided by the controller - - `domainerrors`: Directory that contains the definition of the application's domain errors. \ No newline at end of file + - `domainerrors`: Directory that contains the definition of the application's domain errors. diff --git a/cmd/http/main.go b/cmd/http/main.go index 458d267..f2d3e1c 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -6,18 +6,15 @@ import ( "os" "github.com/joho/godotenv" - _ "github.com/pangolin-do-golang/tech-challenge/docs" - dbAdapter "github.com/pangolin-do-golang/tech-challenge/internal/adapters/db" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/server" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "github.com/pangolin-do-golang/tech-challenge/internal/core/customer" - "github.com/pangolin-do-golang/tech-challenge/internal/core/order" - "github.com/pangolin-do-golang/tech-challenge/internal/core/product" + _ "github.com/pangolin-do-golang/tech-challenge-customer-api/docs" + dbAdapter "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/adapters/db" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/adapters/rest/server" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/core/customer" "gorm.io/driver/postgres" "gorm.io/gorm" ) -// @title Tech Challenge Food API +// @title Tech Challenge Customer Food API // @version 0.1.0 // @description Fast Food API for FIAP Tech course @@ -32,21 +29,7 @@ func main() { customerRepository := dbAdapter.NewPostgresCustomerRepository(db) customerService := customer.NewService(customerRepository) - productRepository := dbAdapter.NewPostgresProductRepository(db) - productService := product.NewProductService(productRepository) - - cartRepository := dbAdapter.NewPostgresCartRepository(db) - cartProductsRepository := dbAdapter.NewPostgresCartProductsRepository(db) - cartService := cart.NewService(cartRepository, cartProductsRepository) - - orderRepository := dbAdapter.NewPostgresOrderRepository(db) - orderProductRepository := dbAdapter.NewPostgresOrderProductsRepository(db) - orderService := order.NewOrderService(orderRepository, orderProductRepository, cartService, productService) - restServer := server.NewRestServer(&server.RestServerOptions{ - OrderService: orderService, - ProductService: productService, - CartService: cartService, CustomerService: customerService, }) @@ -69,12 +52,6 @@ func initDb() (*gorm.DB, error) { err = db.AutoMigrate( &dbAdapter.CustomerPostgres{}, - &dbAdapter.ProductPostgres{}, - &dbAdapter.OrderPostgres{}, - &dbAdapter.CartPostgres{}, - &dbAdapter.CartProductsPostgres{}, - &dbAdapter.OrderPostgres{}, - &dbAdapter.OrderProductPostgres{}, ) if err != nil { log.Fatalln(err) diff --git a/docker-compose.yaml b/docker-compose.yaml index 56437bc..99c946a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,12 +20,12 @@ services: server: build: context: . - container_name: go_tech_challenge_app + container_name: go_tech_challenge_customer_app restart: always links: - pgsql:pgsql ports: - - "8080:8080" + - "8085:8080" depends_on: pgsql: condition: service_started diff --git a/docs/docs.go b/docs/docs.go index 1eac24a..7fcd2e9 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,145 +15,6 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/cart/add-product": { - "post": { - "description": "Adds a Product to Customer's Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "AddProductPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.AddProductPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "{\\\"error\\\": \\\"Internal Server Error\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/cart/edit-product": { - "post": { - "description": "Edits a Product from Customer's Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "EditProductPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.EditProductPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "{\\\"error\\\": \\\"Internal Server Error\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/cart/overview": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "GetCartPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.GetCartPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "Internal Server Error" - } - } - } - }, - "/cart/remove-product": { - "post": { - "description": "Removes a Product from Customer's Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "RemoveProductPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.RemoveProductPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "Internal Server Error" - } - } - } - }, "/customer": { "get": { "description": "Overview all customer's list", @@ -331,314 +192,9 @@ const docTemplate = `{ } } } - }, - "/orders": { - "get": { - "description": "Get all order's list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Get order list", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/order.Order" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - }, - "post": { - "description": "Create order from Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Create order from Cart", - "parameters": [ - { - "description": "CreateOrderPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.CreateOrderPayload" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/order.Order" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - } - }, - "/orders/{id}": { - "get": { - "description": "Get an order by ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Get order by ID", - "parameters": [ - { - "type": "string", - "description": "ID of the order", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/order.Order" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - }, - "patch": { - "description": "Update by json an Order", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Update an Order", - "parameters": [ - { - "type": "string", - "description": "ID of the Order", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "UpdateOrderPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.UpdateOrderPayload" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/order.Order" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - } - }, - "/product": { - "get": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Product" - ], - "summary": "Search products with given criteria", - "parameters": [ - { - "type": "string", - "description": "Name of Product", - "name": "search", - "in": "path" - }, - { - "type": "string", - "description": "Category of Product", - "name": "category", - "in": "path" - } - ], - "responses": { - "200": { - "description": "product.Product", - "schema": { - "$ref": "#/definitions/product.Product" - } - }, - "500": { - "description": "{\\\"error\\\": \\\"something went bad :(\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/product/{id}": { - "delete": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Product" - ], - "summary": "Delete a Product with given ID", - "parameters": [ - { - "type": "string", - "description": "ID of Product", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "500": { - "description": "{\\\"error\\\": \\\"something went bad :(\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } } }, "definitions": { - "controller.AddProductPayload": { - "type": "object", - "required": [ - "client_id", - "product_id", - "quantity" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - }, - "comments": { - "type": "string" - }, - "product_id": { - "type": "string", - "format": "uuid" - }, - "quantity": { - "type": "integer", - "minimum": 1, - "example": 1 - } - } - }, - "controller.CreateOrderPayload": { - "type": "object", - "required": [ - "client_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - } - } - }, "controller.CustomerPayload": { "type": "object", "required": [ @@ -665,80 +221,6 @@ const docTemplate = `{ } } }, - "controller.EditProductPayload": { - "type": "object", - "required": [ - "client_id", - "product_id", - "quantity" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - }, - "comments": { - "type": "string" - }, - "product_id": { - "type": "string", - "format": "uuid" - }, - "quantity": { - "type": "integer", - "example": 2 - } - } - }, - "controller.GetCartPayload": { - "type": "object", - "required": [ - "client_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - } - } - }, - "controller.HTTPError": { - "type": "object", - "properties": { - "error": { - "type": "string" - } - } - }, - "controller.RemoveProductPayload": { - "type": "object", - "required": [ - "client_id", - "product_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - }, - "product_id": { - "type": "string", - "format": "uuid" - } - } - }, - "controller.UpdateOrderPayload": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "example": "paid" - } - } - }, "customer.Customer": { "type": "object", "properties": { @@ -758,49 +240,6 @@ const docTemplate = `{ "type": "string" } } - }, - "order.Order": { - "type": "object", - "properties": { - "client_id": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "total_amount": { - "type": "number" - } - } - }, - "product.Product": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "price": { - "type": "number" - } - } } } }` @@ -811,7 +250,7 @@ var SwaggerInfo = &swag.Spec{ Host: "localhost:8080", BasePath: "/", Schemes: []string{}, - Title: "Tech Challenge Food API", + Title: "Tech Challenge Customer Food API", Description: "Fast Food API for FIAP Tech course", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, diff --git a/docs/swagger.json b/docs/swagger.json index 41203ab..ef1c287 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -2,152 +2,13 @@ "swagger": "2.0", "info": { "description": "Fast Food API for FIAP Tech course", - "title": "Tech Challenge Food API", + "title": "Tech Challenge Customer Food API", "contact": {}, "version": "0.1.0" }, "host": "localhost:8080", "basePath": "/", "paths": { - "/cart/add-product": { - "post": { - "description": "Adds a Product to Customer's Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "AddProductPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.AddProductPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "{\\\"error\\\": \\\"Internal Server Error\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/cart/edit-product": { - "post": { - "description": "Edits a Product from Customer's Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "EditProductPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.EditProductPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "{\\\"error\\\": \\\"Internal Server Error\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/cart/overview": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "GetCartPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.GetCartPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "Internal Server Error" - } - } - } - }, - "/cart/remove-product": { - "post": { - "description": "Removes a Product from Customer's Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Cart" - ], - "parameters": [ - { - "description": "RemoveProductPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.RemoveProductPayload" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "500": { - "description": "Internal Server Error" - } - } - } - }, "/customer": { "get": { "description": "Overview all customer's list", @@ -325,314 +186,9 @@ } } } - }, - "/orders": { - "get": { - "description": "Get all order's list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Get order list", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/order.Order" - } - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - }, - "post": { - "description": "Create order from Cart", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Create order from Cart", - "parameters": [ - { - "description": "CreateOrderPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.CreateOrderPayload" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/order.Order" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - } - }, - "/orders/{id}": { - "get": { - "description": "Get an order by ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Get order by ID", - "parameters": [ - { - "type": "string", - "description": "ID of the order", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/order.Order" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - }, - "patch": { - "description": "Update by json an Order", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Order" - ], - "summary": "Update an Order", - "parameters": [ - { - "type": "string", - "description": "ID of the Order", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "UpdateOrderPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.UpdateOrderPayload" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/order.Order" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "422": { - "description": "Unprocessable Entity", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/controller.HTTPError" - } - } - } - } - }, - "/product": { - "get": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Product" - ], - "summary": "Search products with given criteria", - "parameters": [ - { - "type": "string", - "description": "Name of Product", - "name": "search", - "in": "path" - }, - { - "type": "string", - "description": "Category of Product", - "name": "category", - "in": "path" - } - ], - "responses": { - "200": { - "description": "product.Product", - "schema": { - "$ref": "#/definitions/product.Product" - } - }, - "500": { - "description": "{\\\"error\\\": \\\"something went bad :(\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/product/{id}": { - "delete": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Product" - ], - "summary": "Delete a Product with given ID", - "parameters": [ - { - "type": "string", - "description": "ID of Product", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "500": { - "description": "{\\\"error\\\": \\\"something went bad :(\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } } }, "definitions": { - "controller.AddProductPayload": { - "type": "object", - "required": [ - "client_id", - "product_id", - "quantity" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - }, - "comments": { - "type": "string" - }, - "product_id": { - "type": "string", - "format": "uuid" - }, - "quantity": { - "type": "integer", - "minimum": 1, - "example": 1 - } - } - }, - "controller.CreateOrderPayload": { - "type": "object", - "required": [ - "client_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - } - } - }, "controller.CustomerPayload": { "type": "object", "required": [ @@ -659,80 +215,6 @@ } } }, - "controller.EditProductPayload": { - "type": "object", - "required": [ - "client_id", - "product_id", - "quantity" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - }, - "comments": { - "type": "string" - }, - "product_id": { - "type": "string", - "format": "uuid" - }, - "quantity": { - "type": "integer", - "example": 2 - } - } - }, - "controller.GetCartPayload": { - "type": "object", - "required": [ - "client_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - } - } - }, - "controller.HTTPError": { - "type": "object", - "properties": { - "error": { - "type": "string" - } - } - }, - "controller.RemoveProductPayload": { - "type": "object", - "required": [ - "client_id", - "product_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - }, - "product_id": { - "type": "string", - "format": "uuid" - } - } - }, - "controller.UpdateOrderPayload": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "example": "paid" - } - } - }, "customer.Customer": { "type": "object", "properties": { @@ -752,49 +234,6 @@ "type": "string" } } - }, - "order.Order": { - "type": "object", - "properties": { - "client_id": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "total_amount": { - "type": "number" - } - } - }, - "product.Product": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "price": { - "type": "number" - } - } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 96d2ea9..9434671 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,32 +1,5 @@ basePath: / definitions: - controller.AddProductPayload: - properties: - client_id: - format: uuid - type: string - comments: - type: string - product_id: - format: uuid - type: string - quantity: - example: 1 - minimum: 1 - type: integer - required: - - client_id - - product_id - - quantity - type: object - controller.CreateOrderPayload: - properties: - client_id: - format: uuid - type: string - required: - - client_id - type: object controller.CustomerPayload: properties: age: @@ -46,57 +19,6 @@ definitions: - email - name type: object - controller.EditProductPayload: - properties: - client_id: - format: uuid - type: string - comments: - type: string - product_id: - format: uuid - type: string - quantity: - example: 2 - type: integer - required: - - client_id - - product_id - - quantity - type: object - controller.GetCartPayload: - properties: - client_id: - format: uuid - type: string - required: - - client_id - type: object - controller.HTTPError: - properties: - error: - type: string - type: object - controller.RemoveProductPayload: - properties: - client_id: - format: uuid - type: string - product_id: - format: uuid - type: string - required: - - client_id - - product_id - type: object - controller.UpdateOrderPayload: - properties: - status: - example: paid - type: string - required: - - status - type: object customer.Customer: properties: age: @@ -110,130 +32,13 @@ definitions: name: type: string type: object - order.Order: - properties: - client_id: - type: string - created_at: - type: string - id: - type: string - status: - type: string - total_amount: - type: number - type: object - product.Product: - properties: - category: - type: string - created_at: - type: string - description: - type: string - id: - type: string - name: - type: string - price: - type: number - type: object host: localhost:8080 info: contact: {} description: Fast Food API for FIAP Tech course - title: Tech Challenge Food API + title: Tech Challenge Customer Food API version: 0.1.0 paths: - /cart/add-product: - post: - consumes: - - application/json - description: Adds a Product to Customer's Cart - parameters: - - description: AddProductPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.AddProductPayload' - produces: - - application/json - responses: - "200": - description: OK - "500": - description: '{\"error\": \"Internal Server Error\"}' - schema: - additionalProperties: true - type: object - tags: - - Cart - /cart/edit-product: - post: - consumes: - - application/json - description: Edits a Product from Customer's Cart - parameters: - - description: EditProductPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.EditProductPayload' - produces: - - application/json - responses: - "200": - description: OK - "500": - description: '{\"error\": \"Internal Server Error\"}' - schema: - additionalProperties: true - type: object - tags: - - Cart - /cart/overview: - post: - consumes: - - application/json - parameters: - - description: GetCartPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.GetCartPayload' - produces: - - application/json - responses: - "200": - description: OK - "500": - description: Internal Server Error - tags: - - Cart - /cart/remove-product: - post: - consumes: - - application/json - description: Removes a Product from Customer's Cart - parameters: - - description: RemoveProductPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.RemoveProductPayload' - produces: - - application/json - responses: - "200": - description: OK - "500": - description: Internal Server Error - tags: - - Cart /customer: get: consumes: @@ -352,180 +157,4 @@ paths: summary: Update customer tags: - Customer - /orders: - get: - consumes: - - application/json - description: Get all order's list - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/order.Order' - type: array - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/controller.HTTPError' - summary: Get order list - tags: - - Order - post: - consumes: - - application/json - description: Create order from Cart - parameters: - - description: CreateOrderPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.CreateOrderPayload' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/order.Order' - "400": - description: Bad Request - schema: - $ref: '#/definitions/controller.HTTPError' - "422": - description: Unprocessable Entity - schema: - $ref: '#/definitions/controller.HTTPError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/controller.HTTPError' - summary: Create order from Cart - tags: - - Order - /orders/{id}: - get: - consumes: - - application/json - description: Get an order by ID - parameters: - - description: ID of the order - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/order.Order' - "400": - description: Bad Request - schema: - $ref: '#/definitions/controller.HTTPError' - "422": - description: Unprocessable Entity - schema: - $ref: '#/definitions/controller.HTTPError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/controller.HTTPError' - summary: Get order by ID - tags: - - Order - patch: - consumes: - - application/json - description: Update by json an Order - parameters: - - description: ID of the Order - in: path - name: id - required: true - type: string - - description: UpdateOrderPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.UpdateOrderPayload' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/order.Order' - "400": - description: Bad Request - schema: - $ref: '#/definitions/controller.HTTPError' - "422": - description: Unprocessable Entity - schema: - $ref: '#/definitions/controller.HTTPError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/controller.HTTPError' - summary: Update an Order - tags: - - Order - /product: - get: - consumes: - - application/json - parameters: - - description: Name of Product - in: path - name: search - type: string - - description: Category of Product - in: path - name: category - type: string - produces: - - application/json - responses: - "200": - description: product.Product - schema: - $ref: '#/definitions/product.Product' - "500": - description: '{\"error\": \"something went bad :(\"}' - schema: - additionalProperties: true - type: object - summary: Search products with given criteria - tags: - - Product - /product/{id}: - delete: - consumes: - - application/json - parameters: - - description: ID of Product - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "204": - description: No Content - "500": - description: '{\"error\": \"something went bad :(\"}' - schema: - additionalProperties: true - type: object - summary: Delete a Product with given ID - tags: - - Product swagger: "2.0" diff --git a/go.mod b/go.mod index 2823ac0..74b81df 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/pangolin-do-golang/tech-challenge +module github.com/pangolin-do-golang/tech-challenge-customer-api go 1.22.2 @@ -6,6 +6,7 @@ require ( github.com/gin-gonic/gin v1.10.0 github.com/google/uuid v1.6.0 github.com/joho/godotenv v1.5.1 + github.com/stretchr/testify v1.9.0 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.3 @@ -21,6 +22,7 @@ require ( github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect @@ -46,16 +48,18 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/net v0.25.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.22.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index e7bf099..661b6ce 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -96,11 +96,12 @@ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6 github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -127,18 +128,18 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= @@ -151,8 +152,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -161,16 +162,14 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/adapters/db/cart.go b/internal/adapters/db/cart.go deleted file mode 100644 index 7b4b6a4..0000000 --- a/internal/adapters/db/cart.go +++ /dev/null @@ -1,62 +0,0 @@ -package db - -import ( - "errors" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" - - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "gorm.io/gorm" -) - -type PostgresCartRepository struct { - db *gorm.DB -} - -type CartPostgres struct { - BaseModel - ClientID uuid.UUID `gorm:"client_id"` - Customer CustomerPostgres `gorm:"foreignKey:ClientID"` - Products []CartProductsPostgres `gorm:"foreignKey:CartID"` -} - -func (op CartPostgres) TableName() string { - return "cart" -} - -func NewPostgresCartRepository(db *gorm.DB) cart.ICartRepository { - return &PostgresCartRepository{db: db} -} - -func (p *PostgresCartRepository) Create(clientID uuid.UUID) (*cart.Cart, error) { - record := &CartPostgres{ - ClientID: clientID, - } - - err := p.db.Create(record).Error - if err != nil { - return nil, err - } - - return &cart.Cart{ - ID: record.ID, - ClientID: record.ClientID, - }, nil -} - -func (p *PostgresCartRepository) Get(clientID uuid.UUID) (*cart.Cart, error) { - var row CartPostgres - err := p.db.First(&row, "client_id = ?", clientID).Error - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, errutil.ErrRecordNotFound - } - - return nil, err - } - - return &cart.Cart{ - ID: row.ID, - ClientID: row.ClientID, - }, nil -} diff --git a/internal/adapters/db/cart_products.go b/internal/adapters/db/cart_products.go deleted file mode 100644 index ceb2fbc..0000000 --- a/internal/adapters/db/cart_products.go +++ /dev/null @@ -1,79 +0,0 @@ -package db - -import ( - "context" - - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "gorm.io/gorm" -) - -type PostgresCartProductsRepository struct { - db *gorm.DB -} - -type CartProductsPostgres struct { - BaseModel - CartID uuid.UUID `gorm:"type:uuid"` - ProductID uuid.UUID `gorm:"type:uuid"` - Quantity int `gorm:"quantity"` - Comments string `gorm:"comments"` - Cart CartPostgres `gorm:"foreignKey:CartID"` - Product ProductPostgres `gorm:"foreignKey:ProductID"` -} - -func (op *CartProductsPostgres) TableName() string { - return "cart_products" -} - -func NewPostgresCartProductsRepository(db *gorm.DB) cart.ICartProductRepository { - return &PostgresCartProductsRepository{db: db} -} - -func (p *PostgresCartProductsRepository) Create(_ context.Context, cartID uuid.UUID, product *cart.Product) error { - cartProduct := CartProductsPostgres{ - CartID: cartID, - ProductID: product.ProductID, - Quantity: product.Quantity, - Comments: product.Comments, - } - - result := p.db.Create(&cartProduct) - if result.Error != nil { - return result.Error - } - - return nil -} - -func (p *PostgresCartProductsRepository) GetByCartID(_ context.Context, cartID uuid.UUID) ([]*cart.Product, error) { - var cartProducts []CartProductsPostgres - err := p.db.Where("cart_id = ?", cartID).Find(&cartProducts).Error - if err != nil { - return nil, err - } - - var products []*cart.Product - for _, cp := range cartProducts { - products = append(products, &cart.Product{ - ProductID: cp.ProductID, - Quantity: cp.Quantity, - Comments: cp.Comments, - }) - } - - return products, nil -} - -func (p *PostgresCartProductsRepository) DeleteByProductID(_ context.Context, cartID, productID uuid.UUID) error { - return p.db.Delete(&CartProductsPostgres{}, "cart_id = ? AND product_id = ?", cartID, productID).Error -} - -func (p *PostgresCartProductsRepository) UpdateProductByProductID(_ context.Context, cartID, productID uuid.UUID, product *cart.Product) error { - return p.db.Model(&CartProductsPostgres{}). - Where("cart_id = ? AND product_id = ?", cartID, productID). - Updates(map[string]interface{}{ - "quantity": product.Quantity, - "comments": product.Comments, - }).Error -} diff --git a/internal/adapters/db/customer.go b/internal/adapters/db/customer.go index 87aad00..b8ea522 100644 --- a/internal/adapters/db/customer.go +++ b/internal/adapters/db/customer.go @@ -3,8 +3,8 @@ package db import ( "errors" "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/customer" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/core/customer" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/errutil" "gorm.io/gorm" ) @@ -14,11 +14,11 @@ type PostgresCustomerRepository struct { type CustomerPostgres struct { BaseModel - Name string `gorm:"name"` - Cpf string `gorm:"uniqueIndex" json:"cpf"` - Email string `gorm:"email"` - Age int `gorm:"age"` - Orders []OrderPostgres `gorm:"foreignKey:ClientID"` + Name string `gorm:"name"` + Cpf string `gorm:"uniqueIndex" json:"cpf"` + Email string `gorm:"email"` + Age int `gorm:"age"` + Orders []int `gorm:"client_id"` } func (cp CustomerPostgres) TableName() string { diff --git a/internal/adapters/db/order.go b/internal/adapters/db/order.go deleted file mode 100644 index 900cefc..0000000 --- a/internal/adapters/db/order.go +++ /dev/null @@ -1,151 +0,0 @@ -package db - -import ( - "errors" - "fmt" - "strings" - - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/order" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" - "gorm.io/gorm" -) - -type PostgresOrderRepository struct { - db *gorm.DB -} - -type OrderPostgres struct { - BaseModel - ClientID uuid.UUID `gorm:"client_id,type:uuid"` - TotalAmount float64 `gorm:"total_amount"` - Status string `gorm:"status"` - Customer CustomerPostgres `gorm:"foreignKey:ClientID"` - Products []OrderProductPostgres `gorm:"foreignKey:OrderID"` -} - -func (op OrderPostgres) TableName() string { - return "order" -} - -func NewPostgresOrderRepository(db *gorm.DB) order.IOrderRepository { - return &PostgresOrderRepository{db: db} -} - -func (r *PostgresOrderRepository) Update(order *order.Order) error { - result := r.db.Model(&OrderPostgres{}). - Where("id", order.ID). - Update("status", order.Status). - Update("total_amount", order.TotalAmount) - if result.Error != nil { - return result.Error - } - - return nil -} - -func (r *PostgresOrderRepository) Create(order *order.Order) (*order.Order, error) { - dbOrder := OrderPostgres{ - BaseModel: BaseModel{ID: uuid.New()}, - ClientID: order.ClientID, - TotalAmount: order.TotalAmount, - Status: order.Status, - } - - result := r.db.Create(&dbOrder) - if result.Error != nil { - return nil, result.Error - } - - order.ID = dbOrder.ID - order.CreatedAt = dbOrder.CreatedAt - return order, nil -} - -func (r *PostgresOrderRepository) Get(id uuid.UUID) (*order.Order, error) { - var record OrderPostgres - - if err := r.db.First(&record, "id = ?", id).Error; err != nil { - return nil, errutil.ErrRecordNotFound - } - - return &order.Order{ - ID: record.ID, - ClientID: record.ClientID, - CreatedAt: record.CreatedAt, - TotalAmount: record.TotalAmount, - Status: record.Status, - }, nil -} - -func (r *PostgresOrderRepository) GetAll() ([]order.Order, error) { - var records []OrderPostgres - - err := r.db.Raw(buildGetAllQuery()).Scan(&records).Error - - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, errutil.ErrRecordNotFound - } - - if err != nil { - return nil, err - } - - parsedOrders := make([]order.Order, len(records)) - for i, record := range records { - parsedOrders[i] = order.Order{ - ID: record.ID, - ClientID: record.ClientID, - CreatedAt: record.CreatedAt, - TotalAmount: record.TotalAmount, - Status: record.Status, - } - } - - return parsedOrders, nil -} - -func buildGetAllQuery() string { - ignoredStatus := []string{ - order.StatusFinished, - order.StatusDeclined, - } - - statusSortedPriority := []string{ - order.StatusReady, - order.StatusPreparing, - order.StatusPaid, - order.StatusPending, - order.StatusCreated, - } - - return fmt.Sprintf(` - SELECT * FROM "order" - WHERE status NOT IN (%s) - ORDER BY - CASE %s - END, created_at - `, - buildIgnoredStatusCondition(ignoredStatus), - buildSortedStatusCase(statusSortedPriority), - ) -} - -func buildIgnoredStatusCondition(ignoredStatus []string) string { - var ignoredParts []string - for _, status := range ignoredStatus { - ignoredParts = append(ignoredParts, fmt.Sprintf("'%s'", status)) - } - - return strings.Join(ignoredParts, ", ") -} - -func buildSortedStatusCase(statusSortedPriority []string) string { - var caseParts []string - for i, status := range statusSortedPriority { - caseParts = append(caseParts, fmt.Sprintf("WHEN status = '%s' THEN %d", status, i+1)) - } - caseParts = append(caseParts, fmt.Sprintf("ELSE %d", len(statusSortedPriority))) - - return strings.Join(caseParts, " ") -} diff --git a/internal/adapters/db/order_products.go b/internal/adapters/db/order_products.go deleted file mode 100644 index e6b1eb0..0000000 --- a/internal/adapters/db/order_products.go +++ /dev/null @@ -1,66 +0,0 @@ -package db - -import ( - "context" - "github.com/pangolin-do-golang/tech-challenge/internal/core/order" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -type PostgresOrderProductsRepository struct { - db *gorm.DB -} - -type OrderProductPostgres struct { - BaseModel - OrderID uuid.UUID `gorm:"type:uuid"` - ProductID uuid.UUID `gorm:"type:uuid"` - Quantity int `gorm:"quantity"` - Comments string `gorm:"comments"` - Order OrderPostgres `gorm:"foreignKey:OrderID"` - Product ProductPostgres `gorm:"foreignKey:ProductID"` -} - -func (op *OrderProductPostgres) TableName() string { - return "order_products" -} - -func NewPostgresOrderProductsRepository(db *gorm.DB) order.IOrderProductRepository { - return &PostgresOrderProductsRepository{db: db} -} - -func (p *PostgresOrderProductsRepository) Create(_ context.Context, orderID uuid.UUID, product *order.Product) error { - orderProduct := OrderProductPostgres{ - OrderID: orderID, - ProductID: product.ProductID, - Quantity: product.Quantity, - Comments: product.Comments, - } - - result := p.db.Create(&orderProduct) - if result.Error != nil { - return result.Error - } - - return nil -} - -func (p *PostgresOrderProductsRepository) GetByOrderID(_ context.Context, cartID uuid.UUID) ([]*order.Product, error) { - var cartProducts []OrderProductPostgres - err := p.db.Where("order_id = ?", cartID).Find(&cartProducts).Error - if err != nil { - return nil, err - } - - var products []*order.Product - for _, cp := range cartProducts { - products = append(products, &order.Product{ - ProductID: cp.ProductID, - Quantity: cp.Quantity, - Comments: cp.Comments, - }) - } - - return products, nil -} diff --git a/internal/adapters/db/product.go b/internal/adapters/db/product.go deleted file mode 100644 index ee0decd..0000000 --- a/internal/adapters/db/product.go +++ /dev/null @@ -1,107 +0,0 @@ -package db - -import ( - "fmt" - "time" - - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/product" - "gorm.io/gorm" -) - -type PostgresProductRepository struct { - db *gorm.DB -} - -type ProductPostgres struct { - BaseModel - Name string `gorm:"name"` - Description string `gorm:"description"` - Category string `gorm:"category"` - Price float64 `gorm:"price"` -} - -func (pp ProductPostgres) TableName() string { - return "product" -} - -func NewPostgresProductRepository(db *gorm.DB) product.Repository { - return &PostgresProductRepository{db: db} -} - -func (repo *PostgresProductRepository) GetByID(id uuid.UUID) (*product.Product, error) { - var dbRecord ProductPostgres - - if err := repo.db.Where("id = ? and deleted_at is null", id).First(&dbRecord).Error; err != nil { - return nil, err - } - - if dbRecord.ID == uuid.Nil { - return nil, nil - } - - return &product.Product{ - Id: dbRecord.ID, - Name: dbRecord.Name, - Description: dbRecord.Description, - Category: dbRecord.Category, - Price: dbRecord.Price, - }, nil -} - -func (repo *PostgresProductRepository) Search(search string, category string) (*[]product.Product, error) { - var dbRecords []ProductPostgres - - db := repo.db - - if len(search) > 0 { - parsedSearch := fmt.Sprintf("%%%s%%", search) - db = db.Where("name ILIKE ?", parsedSearch) - } - - if len(category) > 0 { - db = db.Where("category = ?", category) - } - - if err := db.Where("deleted_at is null").Find(&dbRecords).Error; err != nil { - return nil, err - } - - if len(dbRecords) == 0 { - emptyResult := make([]product.Product, 0) - return &emptyResult, nil - } - - var results []product.Product - - for _, record := range dbRecords { - results = append(results, product.Product{ - Id: record.ID, - Name: record.Name, - Description: record.Description, - Category: record.Category, - Price: record.Price, - }) - } - - return &results, nil -} - -func (repo *PostgresProductRepository) Delete(id uuid.UUID) error { - var dbRecord *ProductPostgres - - if err := repo.db.Where("id = ? and deleted_at is null", id).First(&dbRecord).Error; err != nil { - return err - } - - if dbRecord == nil { - return nil - } - - if err := repo.db.Model(&dbRecord).Where("id = ? and deleted_at is null", id).Update("deleted_at", time.Now()).Error; err != nil { - fmt.Println(err) - return err - } - - return nil -} diff --git a/internal/adapters/rest/controller/abstract_controller.go b/internal/adapters/rest/controller/abstract_controller.go index d57aea5..6588f27 100644 --- a/internal/adapters/rest/controller/abstract_controller.go +++ b/internal/adapters/rest/controller/abstract_controller.go @@ -3,7 +3,7 @@ package controller import ( "errors" "github.com/gin-gonic/gin" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/errutil" "log" ) diff --git a/internal/adapters/rest/controller/cart_controller.go b/internal/adapters/rest/controller/cart_controller.go deleted file mode 100644 index 8946bd0..0000000 --- a/internal/adapters/rest/controller/cart_controller.go +++ /dev/null @@ -1,156 +0,0 @@ -package controller - -import ( - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/google/uuid" -) - -type CartController struct { - AbstractController - service cart.IService -} - -func NewCartController(cart cart.IService) *CartController { - return &CartController{ - service: cart, - } -} - -type AddProductPayload struct { - ClientID uuid.UUID `json:"client_id" binding:"required" format:"uuid"` - ProductID uuid.UUID `json:"product_id" binding:"required" format:"uuid"` - Quantity int `json:"quantity" binding:"required,min=1" example:"1"` - Comments string `json:"comments"` -} - -// AddProduct adds a Product to Customer's Cart -// @Description Adds a Product to Customer's Cart -// @Tags Cart -// @Param payload body controller.AddProductPayload true "AddProductPayload" -// @Accept json -// @Produce json -// @Success 200 -// @Failure 500 {object} map[string]any "{\"error\": \"Internal Server Error\"}" -// @Router /cart/add-product [post] -func (ctrl CartController) AddProduct(c *gin.Context) { - payload := &AddProductPayload{} - err := c.BindJSON(payload) - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - err = ctrl.service.AddProduct(c.Request.Context(), payload.ClientID, &cart.Product{ - ProductID: payload.ProductID, - Quantity: payload.Quantity, - Comments: payload.Comments, - }) - - if err != nil { - ctrl.Error(c, err) - return - } - - c.Status(http.StatusOK) -} - -type EditProductPayload struct { - ClientID uuid.UUID `json:"client_id" binding:"required" format:"uuid"` - ProductID uuid.UUID `json:"product_id" binding:"required" format:"uuid"` - Quantity int `json:"quantity" binding:"required" example:"2"` - Comments string `json:"comments"` -} - -// EditProduct edits a Product from Cart by ID -// @Description Edits a Product from Customer's Cart -// @Tags Cart -// @Param payload body controller.EditProductPayload true "EditProductPayload" -// @Accept json -// @Produce json -// @Success 200 -// @Failure 500 {object} map[string]any "{\"error\": \"Internal Server Error\"}" -// @Router /cart/edit-product [post] -func (ctrl CartController) EditProduct(c *gin.Context) { - payload := &EditProductPayload{} - err := c.BindJSON(payload) - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - err = ctrl.service.EditProduct(c.Request.Context(), payload.ClientID, &cart.Product{ - ProductID: payload.ProductID, - Quantity: payload.Quantity, - Comments: payload.Comments, - }) - if err != nil { - ctrl.Error(c, err) - return - } - - c.Status(http.StatusOK) -} - -type RemoveProductPayload struct { - ClientID uuid.UUID `json:"client_id" binding:"required" format:"uuid"` - ProductID uuid.UUID `json:"product_id" binding:"required" format:"uuid"` -} - -// RemoveProduct removes a Product from Customer's Cart -// @Description Removes a Product from Customer's Cart -// @Tags Cart -// @Param payload body controller.RemoveProductPayload true "RemoveProductPayload" -// @Accept json -// @Produce json -// @Success 200 -// @Failure 500 "Internal Server Error" -// @Router /cart/remove-product [post] -func (ctrl CartController) RemoveProduct(c *gin.Context) { - payload := &RemoveProductPayload{} - err := c.BindJSON(payload) - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - err = ctrl.service.RemoveProduct(c.Request.Context(), payload.ClientID, payload.ProductID) - if err != nil { - ctrl.Error(c, err) - return - } - - c.Status(http.StatusOK) -} - -type GetCartPayload struct { - ClientID uuid.UUID `json:"client_id" binding:"required" format:"uuid"` -} - -// Overview get the full cart and its products -// @Tags Cart -// @Param payload body controller.GetCartPayload true "GetCartPayload" -// @Accept json -// @Produce json -// @Success 200 -// @Failure 500 "Internal Server Error" -// @Router /cart/overview [post] -func (ctrl CartController) Overview(c *gin.Context) { - payload := &GetCartPayload{} - err := c.BindJSON(payload) - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - fullcart, err := ctrl.service.GetFullCart(payload.ClientID) - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusOK, fullcart) -} diff --git a/internal/adapters/rest/controller/customer_controller.go b/internal/adapters/rest/controller/customer_controller.go index 39a0af9..52322bb 100644 --- a/internal/adapters/rest/controller/customer_controller.go +++ b/internal/adapters/rest/controller/customer_controller.go @@ -1,12 +1,12 @@ package controller import ( - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/errutil" "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/customer" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/core/customer" ) type CustomerController struct { diff --git a/internal/adapters/rest/controller/order_controller.go b/internal/adapters/rest/controller/order_controller.go deleted file mode 100644 index 4ba9aad..0000000 --- a/internal/adapters/rest/controller/order_controller.go +++ /dev/null @@ -1,145 +0,0 @@ -package controller - -import ( - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" - "net/http" - "strings" - - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/order" -) - -type OrderController struct { - AbstractController - service order.IOrderService -} - -func NewOrderController(service order.IOrderService) *OrderController { - return &OrderController{ - service: service, - } -} - -// GetAll Get all order's list -// @Summary Get order list -// @Description Get all order's list -// @Tags Order -// @Accept json -// @Produce json -// @Success 200 {object} []order.Order{} -// @Success 500 {object} HTTPError -// @Router /orders [get] -func (ctrl *OrderController) GetAll(c *gin.Context) { - orderSlice, err := ctrl.service.GetAll() - - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusOK, orderSlice) -} - -type CreateOrderPayload struct { - ClientID uuid.UUID `json:"client_id" binding:"required" format:"uuid"` -} - -// Create Order godoc -// @Summary Create order from Cart -// @Description Create order from Cart -// @Param payload body controller.CreateOrderPayload true "CreateOrderPayload" -// @Tags Order -// @Accept json -// @Produce json -// @Success 200 {object} order.Order{} -// @Failure 400 {object} HTTPError -// @Failure 422 {object} HTTPError -// @Failure 500 {object} HTTPError -// @Router /orders [post] -func (ctrl *OrderController) Create(c *gin.Context) { - payload := &CreateOrderPayload{} - - if err := c.ShouldBindJSON(&payload); err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - - return - } - - o, err := ctrl.service.Create(payload.ClientID) - if err != nil { - ctrl.Error(c, err) - - return - } - - c.JSON(http.StatusOK, o) -} - -// Get an order by ID -// @Summary Get order by ID -// @Description Get an order by ID -// @Tags Order -// @Param id path string true "ID of the order" -// @Accept json -// @Produce json -// @Success 200 {object} order.Order{} -// @Failure 400 {object} HTTPError -// @Failure 422 {object} HTTPError -// @Failure 500 {object} HTTPError -// @Router /orders/{id} [get] -func (ctrl *OrderController) Get(c *gin.Context) { - id, err := uuid.Parse(c.Param("id")) - - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - o, err := ctrl.service.Get(id) - if err != nil { - ctrl.Error(c, err) - - return - } - - c.JSON(http.StatusOK, o) -} - -type UpdateOrderPayload struct { - Status string `json:"status" binding:"required" example:"paid"` -} - -// Update Order godoc -// @Summary Update an Order -// @Description Update by json an Order -// @Param id path string true "ID of the Order" -// @Param payload body controller.UpdateOrderPayload true "UpdateOrderPayload" -// @Tags Order -// @Accept json -// @Produce json -// @Success 200 {object} order.Order{} -// @Failure 400 {object} HTTPError -// @Failure 422 {object} HTTPError -// @Failure 500 {object} HTTPError -// @Router /orders/{id} [patch] -func (ctrl *OrderController) Update(c *gin.Context) { - id, err := uuid.Parse(c.Param("id")) - payload := &UpdateOrderPayload{} - - if err := c.ShouldBindJSON(&payload); err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - o, err := ctrl.service.Update(&order.Order{ - ID: id, - Status: strings.ToUpper(payload.Status), - }) - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusOK, o) -} diff --git a/internal/adapters/rest/controller/product_controller.go b/internal/adapters/rest/controller/product_controller.go deleted file mode 100644 index dd9d0a5..0000000 --- a/internal/adapters/rest/controller/product_controller.go +++ /dev/null @@ -1,69 +0,0 @@ -package controller - -import ( - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/product" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" - "net/http" -) - -type ProductController struct { - AbstractController - service *product.Service -} - -func NewProductController(service *product.Service) *ProductController { - return &ProductController{ - service: service, - } -} - -// Search for products -// @Summary Search products with given criteria -// @Tags Product -// @Param search path string false "Name of Product" -// @Param category path string false "Category of Product" -// @Accept json -// @Produce json -// @Success 200 {object} product.Product "product.Product" -// @Failure 500 {object} map[string]any "{\"error\": \"something went bad :(\"}" -// @Router /product [get] -func (ctrl *ProductController) Search(c *gin.Context) { - search := c.Query("search") - category := c.Query("category") - - products, err := ctrl.service.Search(search, category) - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusOK, products) -} - -// Delete a Product -// @Summary Delete a Product with given ID -// @Tags Product -// @Param id path string true "ID of Product" -// @Accept json -// @Produce json -// @Success 204 -// @Failure 500 {object} map[string]any "{\"error\": \"something went bad :(\"}" -// @Router /product/{id} [delete] -func (ctrl *ProductController) Delete(c *gin.Context) { - id, err := uuid.Parse(c.Param("id")) - - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - err = ctrl.service.Delete(id) - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusNoContent, gin.H{}) -} diff --git a/internal/adapters/rest/handler/cart.go b/internal/adapters/rest/handler/cart.go deleted file mode 100644 index 0d92231..0000000 --- a/internal/adapters/rest/handler/cart.go +++ /dev/null @@ -1,16 +0,0 @@ -package handler - -import ( - "github.com/gin-gonic/gin" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/controller" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" -) - -func RegisterCartHandlers(router *gin.Engine, service cart.IService) { - cartController := controller.NewCartController(service) - - router.POST("/cart/overview", cartController.Overview) - router.POST("/cart/add-product", cartController.AddProduct) - router.POST("/cart/remove-product", cartController.RemoveProduct) - router.POST("/cart/edit-product", cartController.EditProduct) -} diff --git a/internal/adapters/rest/handler/customer.go b/internal/adapters/rest/handler/customer.go index ec200ee..3f92340 100644 --- a/internal/adapters/rest/handler/customer.go +++ b/internal/adapters/rest/handler/customer.go @@ -2,8 +2,8 @@ package handler import ( "github.com/gin-gonic/gin" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/controller" - "github.com/pangolin-do-golang/tech-challenge/internal/core/customer" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/adapters/rest/controller" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/core/customer" ) func RegisterCustomerHandlers(router *gin.Engine, service customer.IService) { diff --git a/internal/adapters/rest/handler/order.go b/internal/adapters/rest/handler/order.go deleted file mode 100644 index 8e25172..0000000 --- a/internal/adapters/rest/handler/order.go +++ /dev/null @@ -1,21 +0,0 @@ -package handler - -import ( - "github.com/gin-gonic/gin" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/controller" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "github.com/pangolin-do-golang/tech-challenge/internal/core/order" -) - -type OrderHandler struct { - service *cart.Service -} - -func RegisterOrderHandlers(router *gin.Engine, service order.IOrderService) { - orderController := controller.NewOrderController(service) - - router.POST("/orders", orderController.Create) - router.GET("/orders", orderController.GetAll) - router.GET("/orders/:id", orderController.Get) - router.PATCH("/orders/:id", orderController.Update) -} diff --git a/internal/adapters/rest/handler/product.go b/internal/adapters/rest/handler/product.go deleted file mode 100644 index e8dac05..0000000 --- a/internal/adapters/rest/handler/product.go +++ /dev/null @@ -1,15 +0,0 @@ -package handler - -import ( - "github.com/gin-gonic/gin" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/controller" - "github.com/pangolin-do-golang/tech-challenge/internal/core/product" -) - -func RegisterProductHandlers(router *gin.Engine, service *product.Service) { - productController := controller.NewProductController(service) - - router.GET("/product", productController.Search) - - router.DELETE("/product/:id") -} diff --git a/internal/adapters/rest/server/server.go b/internal/adapters/rest/server/server.go index f11d322..9628fe2 100644 --- a/internal/adapters/rest/server/server.go +++ b/internal/adapters/rest/server/server.go @@ -4,33 +4,21 @@ import ( "net/http" "github.com/gin-gonic/gin" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/handler" - "github.com/pangolin-do-golang/tech-challenge/internal/adapters/rest/middleware" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "github.com/pangolin-do-golang/tech-challenge/internal/core/customer" - "github.com/pangolin-do-golang/tech-challenge/internal/core/order" - "github.com/pangolin-do-golang/tech-challenge/internal/core/product" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/adapters/rest/handler" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/adapters/rest/middleware" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/core/customer" ) type RestServer struct { - orderService order.IOrderService - productService *product.Service - cartService cart.IService customerService customer.IService } type RestServerOptions struct { - OrderService order.IOrderService - ProductService *product.Service - CartService cart.IService CustomerService customer.IService } func NewRestServer(options *RestServerOptions) *RestServer { return &RestServer{ - orderService: options.OrderService, - productService: options.ProductService, - cartService: options.CartService, customerService: options.CustomerService, } } @@ -42,9 +30,6 @@ func (rs RestServer) Serve() { c.Status(http.StatusOK) }) - handler.RegisterOrderHandlers(r, rs.orderService) - handler.RegisterProductHandlers(r, rs.productService) - handler.RegisterCartHandlers(r, rs.cartService) handler.RegisterCustomerHandlers(r, rs.customerService) handler.RegisterSwaggerHandlers(r) err := r.Run("0.0.0.0:8080") diff --git a/internal/core/cart/cart.go b/internal/core/cart/cart.go deleted file mode 100644 index 8abc985..0000000 --- a/internal/core/cart/cart.go +++ /dev/null @@ -1,40 +0,0 @@ -package cart - -import ( - "context" - - "github.com/google/uuid" -) - -type Cart struct { - ID uuid.UUID `json:"id"` - ClientID uuid.UUID `json:"client_id"` - Products []*Product `json:"products"` -} - -type Product struct { - ProductID uuid.UUID `json:"product_id"` - Quantity int `json:"quantity"` - Comments string `json:"comments,omitempty"` -} - -type ICartRepository interface { - Create(clientID uuid.UUID) (*Cart, error) - Get(clientID uuid.UUID) (*Cart, error) -} - -type ICartProductRepository interface { - Create(ctx context.Context, cartID uuid.UUID, product *Product) error - GetByCartID(ctx context.Context, cartID uuid.UUID) ([]*Product, error) - DeleteByProductID(ctx context.Context, cartID, productID uuid.UUID) error - UpdateProductByProductID(ctx context.Context, cartID, productID uuid.UUID, product *Product) error -} - -type IService interface { - LoadCart(ctx context.Context, clientID uuid.UUID) (*Cart, error) - GetFullCart(clientID uuid.UUID) (*Cart, error) - AddProduct(ctx context.Context, clientID uuid.UUID, product *Product) error - RemoveProduct(ctx context.Context, clientID uuid.UUID, productID uuid.UUID) error - EditProduct(ctx context.Context, clientID uuid.UUID, product *Product) error - Cleanup(clientID uuid.UUID) error -} diff --git a/internal/core/cart/cart_service.go b/internal/core/cart/cart_service.go deleted file mode 100644 index 82df029..0000000 --- a/internal/core/cart/cart_service.go +++ /dev/null @@ -1,109 +0,0 @@ -package cart - -import ( - "context" - "errors" - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" -) - -type Service struct { - CartRepository ICartRepository - CartProductsRepository ICartProductRepository -} - -func NewService(cartRepository ICartRepository, cartProductsRepository ICartProductRepository) IService { - return &Service{ - CartRepository: cartRepository, - CartProductsRepository: cartProductsRepository, - } -} - -func (s *Service) LoadCart(_ context.Context, clientID uuid.UUID) (*Cart, error) { - cart, err := s.CartRepository.Get(clientID) - if err != nil { - if !errors.Is(err, errutil.ErrRecordNotFound) { - return nil, err - } - - cart, err = s.CartRepository.Create(clientID) - if err != nil { - return nil, err - } - } - - return cart, nil - -} - -func (s *Service) GetFullCart(clientID uuid.UUID) (*Cart, error) { - cart, err := s.CartRepository.Get(clientID) - if err != nil { - return nil, err - } - - products, err := s.CartProductsRepository.GetByCartID(context.Background(), cart.ID) - if err != nil { - return nil, err - } - - cart.Products = products - - return cart, nil -} - -func (s *Service) Cleanup(clientID uuid.UUID) error { - cart, err := s.LoadCart(context.Background(), clientID) - if err != nil { - return err - } - - products, err := s.CartProductsRepository.GetByCartID(context.Background(), cart.ID) - for _, p := range products { - err = s.CartProductsRepository.DeleteByProductID(context.Background(), cart.ID, p.ProductID) - if err != nil { - return err - } - } - - return nil -} - -func (s *Service) AddProduct(ctx context.Context, clientID uuid.UUID, product *Product) error { - cart, err := s.LoadCart(ctx, clientID) - if err != nil { - return err - } - - // TODO verificar se produto já tá no carrinho/colocar índice de unicidade - return s.CartProductsRepository.Create(ctx, cart.ID, product) -} - -func (s *Service) RemoveProduct(ctx context.Context, clientID uuid.UUID, productID uuid.UUID) error { - cart, err := s.LoadCart(ctx, clientID) - if err != nil { - return err - } - - products, err := s.CartProductsRepository.GetByCartID(ctx, cart.ID) - if err != nil { - return err - } - - for _, product := range products { - if product.ProductID == productID { - return s.CartProductsRepository.DeleteByProductID(ctx, cart.ID, productID) - } - } - - return nil -} - -func (s *Service) EditProduct(ctx context.Context, clientID uuid.UUID, product *Product) error { - cart, err := s.LoadCart(ctx, clientID) - if err != nil { - return err - } - - return s.CartProductsRepository.UpdateProductByProductID(ctx, cart.ID, product.ProductID, product) -} diff --git a/internal/core/customer/customer_service.go b/internal/core/customer/customer_service.go index d776480..385e441 100644 --- a/internal/core/customer/customer_service.go +++ b/internal/core/customer/customer_service.go @@ -16,7 +16,10 @@ func NewService(customerRepository IRepository) *Service { } func (s *Service) Create(customer Customer) (*Customer, error) { - existingCustomer, _ := s.GetByCpf(customer.Cpf) + existingCustomer, err := s.GetByCpf(customer.Cpf) + if err != nil { + return nil, errors.New("failed to get customer by cpf") + } if existingCustomer != nil { return nil, errors.New("entered cpf is already registered in our system") diff --git a/internal/core/customer/customer_service_test.go b/internal/core/customer/customer_service_test.go new file mode 100644 index 0000000..fe14342 --- /dev/null +++ b/internal/core/customer/customer_service_test.go @@ -0,0 +1,354 @@ +package customer_test + +import ( + "errors" + "github.com/google/uuid" + "github.com/pangolin-do-golang/tech-challenge-customer-api/internal/core/customer" + "github.com/pangolin-do-golang/tech-challenge-customer-api/mocks" + "reflect" + "testing" +) + +func TestService_Create(t *testing.T) { + c := customer.Customer{ + Name: "Teste", + Cpf: "123", + } + + type fields struct { + genRepository func() customer.IRepository + } + type args struct { + customer customer.Customer + } + tests := []struct { + name string + fields fields + args args + want *customer.Customer + wantErr bool + }{ + { + name: "returns error for existing", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetByCpf", c.Cpf).Return(nil, errors.New("error")) + return m + }, + }, + args: args{ + customer: c, + }, + want: nil, + wantErr: true, + }, + { + name: "returns error for non-null c", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetByCpf", c.Cpf).Return(&customer.Customer{}, nil) + return m + }, + }, + args: args{ + customer: c, + }, + want: nil, + wantErr: true, + }, + { + name: "returns error from c creation", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetByCpf", c.Cpf).Return(nil, nil) + m.On("Create", c).Return(nil, errors.New("error")) + return m + }, + }, + args: args{ + customer: c, + }, + want: nil, + wantErr: true, + }, + { + name: "creates c", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetByCpf", c.Cpf).Return(nil, nil) + m.On("Create", c).Return(&c, nil) + return m + }, + }, + args: args{ + customer: c, + }, + want: &c, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := customer.NewService(tt.fields.genRepository()) + got, err := s.Create(tt.args.customer) + if (err != nil) != tt.wantErr { + t.Errorf("Create() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Create() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestService_Update(t *testing.T) { + c := customer.Customer{ + Id: uuid.MustParse("cd661160-4624-49dd-a531-ba48dfce45c2"), + Name: "Ronaldinho", + } + + updatedCustomer := customer.Customer{ + Id: uuid.MustParse("cd661160-4624-49dd-a531-ba48dfce45c2"), + Name: "Ronaldo", + } + + type fields struct { + genRepository func() customer.IRepository + } + type args struct { + customerId uuid.UUID + customer customer.Customer + } + tests := []struct { + name string + fields fields + args args + want *customer.Customer + wantErr bool + }{ + { + name: "returns error from update method", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("Update", c.Id, c).Return(nil, errors.New("error")) + return m + }, + }, + args: args{ + customerId: c.Id, + customer: c, + }, + want: nil, + wantErr: true, + }, + { + name: "updates customer", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("Update", c.Id, c).Return(&updatedCustomer, nil) + return m + }, + }, + args: args{ + customerId: c.Id, + customer: c, + }, + want: &updatedCustomer, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := customer.NewService(tt.fields.genRepository()) + got, err := s.Update(tt.args.customerId, tt.args.customer) + if (err != nil) != tt.wantErr { + t.Errorf("Update() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Update() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestService_Delete(t *testing.T) { + id := uuid.MustParse("d8cdc2b2-3014-4053-941f-2af4fd036a50") + type fields struct { + genRepository func() customer.IRepository + } + type args struct { + customerId uuid.UUID + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "returns error from delete method", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("Delete", id).Return(errors.New("error")) + return m + }, + }, + args: args{ + customerId: id, + }, + wantErr: true, + }, + { + name: "deletes customer", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("Delete", id).Return(nil) + return m + }, + }, + args: args{ + customerId: id, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := customer.NewService(tt.fields.genRepository()) + if err := s.Delete(tt.args.customerId); (err != nil) != tt.wantErr { + t.Errorf("Delete() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestService_GetAll(t *testing.T) { + type fields struct { + genRepository func() customer.IRepository + } + tests := []struct { + name string + fields fields + want []customer.Customer + wantErr bool + }{ + { + name: "returns error from get all method", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetAll").Return([]customer.Customer{}, errors.New("error")) + return m + }, + }, + want: []customer.Customer{}, + wantErr: true, + }, + { + name: "gets all customers", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetAll").Return([]customer.Customer{ + { + Name: "Ronaldo", + }, + }, nil) + return m + }, + }, + want: []customer.Customer{ + { + Name: "Ronaldo", + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := customer.NewService(tt.fields.genRepository()) + got, err := s.GetAll() + if (err != nil) != tt.wantErr { + t.Errorf("GetAll() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAll() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestService_GetByCpf(t *testing.T) { + cpf := "132" + type fields struct { + genRepository func() customer.IRepository + } + type args struct { + cpf string + } + tests := []struct { + name string + fields fields + args args + want *customer.Customer + wantErr bool + }{ + { + name: "returns error from get by cpf method", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetByCpf", cpf).Return(nil, errors.New("error")) + return m + }, + }, + args: args{ + cpf: cpf, + }, + want: nil, + wantErr: true, + }, + { + name: "gets customer by cpf", + fields: fields{ + genRepository: func() customer.IRepository { + m := new(mocks.IRepository) + m.On("GetByCpf", cpf).Return(&customer.Customer{ + Name: "Ronaldo", + }, nil) + return m + }, + }, + args: args{ + cpf: cpf, + }, + want: &customer.Customer{Name: "Ronaldo"}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := customer.NewService(tt.fields.genRepository()) + got, err := s.GetByCpf(tt.args.cpf) + if (err != nil) != tt.wantErr { + t.Errorf("GetByCpf() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetByCpf() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/core/order/order.go b/internal/core/order/order.go deleted file mode 100644 index 34ac964..0000000 --- a/internal/core/order/order.go +++ /dev/null @@ -1,84 +0,0 @@ -package order - -import ( - "context" - "errors" - - "time" - - "github.com/google/uuid" -) - -const ( - StatusPending = "PENDING" - StatusCreated = "CREATED" - StatusPreparing = "PREPARING" - StatusReady = "READY" - StatusFinished = "FINISHED" - StatusPaid = "PAID" - StatusDeclined = "DECLINED" - StatusCanceled = "CANCELED" -) - -var ErrInvalidStatus = errors.New("invalid status transition") - -type Order struct { - ID uuid.UUID `json:"id"` - CreatedAt time.Time `json:"created_at"` - ClientID uuid.UUID `json:"client_id"` - TotalAmount float64 `json:"total_amount"` - Status string `json:"status"` -} - -func (o Order) ValidateStatusTransition(nextStatus string) error { - switch o.Status { - case StatusCreated: - if nextStatus != StatusPending { - return ErrInvalidStatus - } - case StatusPending: - if nextStatus != StatusPaid && nextStatus != StatusDeclined { - return ErrInvalidStatus - } - case StatusPaid: - if nextStatus != StatusPreparing { - return ErrInvalidStatus - } - case StatusPreparing: - if nextStatus != StatusFinished { - return ErrInvalidStatus - } - case StatusCanceled: - return ErrInvalidStatus - default: - return ErrInvalidStatus - } - return nil -} - -type Product struct { - ClientID uuid.UUID `json:"client_id"` - ProductID uuid.UUID `json:"product_id"` - Quantity int `json:"quantity"` - Comments string `json:"comments"` - Total float64 `json:"total"` -} - -type IOrderService interface { - Get(id uuid.UUID) (*Order, error) - Create(clientID uuid.UUID) (*Order, error) - GetAll() ([]Order, error) - Update(order *Order) (*Order, error) -} - -type IOrderProductRepository interface { - Create(ctx context.Context, orderID uuid.UUID, product *Product) error - GetByOrderID(ctx context.Context, orderID uuid.UUID) ([]*Product, error) -} - -type IOrderRepository interface { - Create(order *Order) (*Order, error) - Update(order *Order) error - Get(id uuid.UUID) (*Order, error) - GetAll() ([]Order, error) -} diff --git a/internal/core/order/order_service.go b/internal/core/order/order_service.go deleted file mode 100644 index 40b350b..0000000 --- a/internal/core/order/order_service.go +++ /dev/null @@ -1,133 +0,0 @@ -package order - -import ( - "context" - "errors" - "fmt" - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/cart" - "github.com/pangolin-do-golang/tech-challenge/internal/core/product" - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" -) - -type Service struct { - OrderRepository IOrderRepository - OrderProductRepository IOrderProductRepository - CartService cart.IService - ProductService *product.Service -} - -func NewOrderService(repo IOrderRepository, orderProductRepository IOrderProductRepository, cartService cart.IService, productService *product.Service) IOrderService { - return &Service{ - OrderRepository: repo, - OrderProductRepository: orderProductRepository, - CartService: cartService, - ProductService: productService, - } -} - -func (s *Service) Get(id uuid.UUID) (*Order, error) { - o, err := s.OrderRepository.Get(id) - if err != nil { - if errors.Is(err, errutil.ErrRecordNotFound) { - return nil, errutil.NewBusinessError(err, "order not found") - } - - return nil, err - } - - return o, nil -} - -func (s *Service) GetAll() ([]Order, error) { - return s.OrderRepository.GetAll() -} - -func (s *Service) Update(order *Order) (*Order, error) { - o, err := s.OrderRepository.Get(order.ID) - if err != nil { - return nil, errutil.NewBusinessError(err, "order not found") - } - - if err := o.ValidateStatusTransition(order.Status); err != nil { - return nil, errutil.NewBusinessError(err, err.Error()) - } - - o.Status = order.Status - err = s.OrderRepository.Update(o) - if err != nil { - return nil, err - } - oldOrder := *o - - // "simula" o período de uma tarefa async/em segundo plano pegar o - // pedido "pago" e mudar o status para "preparando"1 - // dessa forma o usuário recebe o status "PAID" - if o.Status == StatusPaid { - o.Status = StatusPreparing - if err := s.OrderRepository.Update(o); err != nil { - return nil, err - } - } - - return &oldOrder, nil -} - -func (s *Service) Create(clientID uuid.UUID) (*Order, error) { - c, err := s.CartService.GetFullCart(clientID) - if err != nil { - return nil, err - } - - if len(c.Products) == 0 { - return nil, fmt.Errorf("empty cart") - } - - order := &Order{ - ClientID: clientID, - Status: StatusCreated, - } - - o, err := s.OrderRepository.Create(order) - if err != nil { - return nil, err - } - - var total float64 - for _, p := range c.Products { - stockProduct, err := s.ProductService.GetByID(p.ProductID) - if err != nil { - return nil, err - } - - productTotal := stockProduct.Price * float64(p.Quantity) - - orderProduct := &Product{ - ClientID: clientID, - ProductID: p.ProductID, - Quantity: p.Quantity, - Comments: p.Comments, - Total: productTotal, - } - - err = s.OrderProductRepository.Create(context.Background(), o.ID, orderProduct) - if err != nil { - return nil, err - } - - total += productTotal - } - - o.TotalAmount = total - o.Status = StatusPending - err = s.OrderRepository.Update(o) - if err != nil { - return nil, err - } - - if err = s.CartService.Cleanup(clientID); err != nil { - return nil, err - } - - return o, nil -} diff --git a/internal/core/product/product.go b/internal/core/product/product.go deleted file mode 100644 index 2f9fc21..0000000 --- a/internal/core/product/product.go +++ /dev/null @@ -1,22 +0,0 @@ -package product - -import ( - "time" - - "github.com/google/uuid" -) - -type Product struct { - Id uuid.UUID `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Category string `json:"category"` - Price float64 `json:"price"` - CreatedAt time.Time `json:"created_at"` -} - -type Repository interface { - Search(search string, category string) (*[]Product, error) - Delete(id uuid.UUID) error - GetByID(id uuid.UUID) (*Product, error) -} diff --git a/internal/core/product/product_service.go b/internal/core/product/product_service.go deleted file mode 100644 index 0676a97..0000000 --- a/internal/core/product/product_service.go +++ /dev/null @@ -1,27 +0,0 @@ -package product - -import ( - "github.com/google/uuid" -) - -type Service struct { - repo Repository -} - -func NewProductService(repo Repository) *Service { - return &Service{ - repo: repo, - } -} - -func (s *Service) Search(search string, category string) (*[]Product, error) { - return s.repo.Search(search, category) -} - -func (s *Service) Delete(id uuid.UUID) error { - return s.repo.Delete(id) -} - -func (s *Service) GetByID(id uuid.UUID) (*Product, error) { - return s.repo.GetByID(id) -} diff --git a/internal/errutil/errors.go b/internal/errutil/errors.go index 94605bb..8964bf1 100644 --- a/internal/errutil/errors.go +++ b/internal/errutil/errors.go @@ -14,14 +14,6 @@ func (e *Error) Error() string { return e.Message } -func NewSystemError(err error, mes string) *Error { - return &Error{ - Message: mes, - Type: "SYSTEM", - originalError: err, - } -} - func NewBusinessError(err error, mes string) *Error { return &Error{ Message: mes,