From 9cebcdbd377b22eae126f0e77972601118b12a14 Mon Sep 17 00:00:00 2001 From: Kevin Martins Date: Mon, 18 Nov 2024 11:03:39 -0300 Subject: [PATCH] Add Cart service --- .pre-commit-config.yaml | 9 + README.md | 4 +- cmd/http/main.go | 15 +- docs/docs.go | 465 ------------------ docs/swagger.json | 465 ------------------ docs/swagger.yaml | 309 ------------ .../rest/controller/customer_controller.go | 172 ------- .../rest/controller/order_controller.go | 145 ------ internal/adapters/rest/handler/customer.go | 17 - internal/adapters/rest/handler/order.go | 21 - internal/adapters/rest/server/server.go | 22 +- internal/core/customer/customer.go | 27 - internal/core/customer/customer_service.go | 42 -- internal/core/order/order.go | 84 ---- internal/core/order/order_service.go | 133 ----- 15 files changed, 18 insertions(+), 1912 deletions(-) create mode 100644 .pre-commit-config.yaml delete mode 100644 internal/adapters/rest/controller/customer_controller.go delete mode 100644 internal/adapters/rest/controller/order_controller.go delete mode 100644 internal/adapters/rest/handler/customer.go delete mode 100644 internal/adapters/rest/handler/order.go delete mode 100644 internal/core/customer/customer.go delete mode 100644 internal/core/customer/customer_service.go delete mode 100644 internal/core/order/order.go delete mode 100644 internal/core/order/order_service.go 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..09abc7c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Miro Board: https://miro.com/app/board/uXjVKVoZwos=/?share_link_id=718027124865 -# Tech Challenge +# Tech Challenge Cart API ## Install @@ -138,8 +138,6 @@ kubectl port-forward svc/tech-challenge-service 4000:80 -n dev - `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. diff --git a/cmd/http/main.go b/cmd/http/main.go index 458d267..3006f06 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -10,8 +10,6 @@ import ( 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" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -29,9 +27,6 @@ func main() { panic(err) } - customerRepository := dbAdapter.NewPostgresCustomerRepository(db) - customerService := customer.NewService(customerRepository) - productRepository := dbAdapter.NewPostgresProductRepository(db) productService := product.NewProductService(productRepository) @@ -39,15 +34,9 @@ func main() { 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, + ProductService: productService, + CartService: cartService, }) restServer.Serve() diff --git a/docs/docs.go b/docs/docs.go index 1eac24a..7fc3f93 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -154,373 +154,6 @@ const docTemplate = `{ } } }, - "/customer": { - "get": { - "description": "Overview all customer's list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Overview customer list", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/customer.Customer" - } - } - } - } - }, - "post": { - "description": "Create a new customer", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Create customer", - "parameters": [ - { - "description": "CustomerPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.CustomerPayload" - } - } - ], - "responses": { - "200": { - "description": "customer.Customer", - "schema": { - "$ref": "#/definitions/customer.Customer" - } - }, - "400": { - "description": "{\\\"error\\\": \\\"Invalid CPF\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/customer/{cpf}": { - "get": { - "description": "Overview a customer by cpf", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Overview customer by cpf", - "parameters": [ - { - "type": "string", - "description": "customer cpf", - "name": "cpf", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/customer.Customer" - } - }, - "404": { - "description": "Customer not found" - } - } - } - }, - "/customer/{id}": { - "put": { - "description": "Update a customer by id", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Update customer", - "parameters": [ - { - "type": "string", - "description": "ID of the customer", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "CustomerPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.CustomerPayload" - } - } - ], - "responses": { - "200": { - "description": "customer.Customer", - "schema": { - "$ref": "#/definitions/customer.Customer" - } - }, - "400": { - "description": "{\\\"error\\\": \\\"Invalid CPF\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - }, - "delete": { - "description": "Delete a customer by id", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Delete customer", - "parameters": [ - { - "type": "string", - "description": "123456789", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Invalid identifier informed" - } - } - } - }, - "/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": [ @@ -627,44 +260,6 @@ const docTemplate = `{ } } }, - "controller.CreateOrderPayload": { - "type": "object", - "required": [ - "client_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - } - } - }, - "controller.CustomerPayload": { - "type": "object", - "required": [ - "cpf", - "email", - "name" - ], - "properties": { - "age": { - "type": "integer", - "maximum": 120, - "minimum": 18 - }, - "cpf": { - "type": "string" - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 20, - "minLength": 5 - } - } - }, "controller.EditProductPayload": { "type": "object", "required": [ @@ -702,14 +297,6 @@ const docTemplate = `{ } } }, - "controller.HTTPError": { - "type": "object", - "properties": { - "error": { - "type": "string" - } - } - }, "controller.RemoveProductPayload": { "type": "object", "required": [ @@ -727,58 +314,6 @@ const docTemplate = `{ } } }, - "controller.UpdateOrderPayload": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "example": "paid" - } - } - }, - "customer.Customer": { - "type": "object", - "properties": { - "age": { - "type": "integer" - }, - "cpf": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "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": { diff --git a/docs/swagger.json b/docs/swagger.json index 41203ab..330c8c6 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -148,373 +148,6 @@ } } }, - "/customer": { - "get": { - "description": "Overview all customer's list", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Overview customer list", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/customer.Customer" - } - } - } - } - }, - "post": { - "description": "Create a new customer", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Create customer", - "parameters": [ - { - "description": "CustomerPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.CustomerPayload" - } - } - ], - "responses": { - "200": { - "description": "customer.Customer", - "schema": { - "$ref": "#/definitions/customer.Customer" - } - }, - "400": { - "description": "{\\\"error\\\": \\\"Invalid CPF\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "/customer/{cpf}": { - "get": { - "description": "Overview a customer by cpf", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Overview customer by cpf", - "parameters": [ - { - "type": "string", - "description": "customer cpf", - "name": "cpf", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/customer.Customer" - } - }, - "404": { - "description": "Customer not found" - } - } - } - }, - "/customer/{id}": { - "put": { - "description": "Update a customer by id", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Update customer", - "parameters": [ - { - "type": "string", - "description": "ID of the customer", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "CustomerPayload", - "name": "payload", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/controller.CustomerPayload" - } - } - ], - "responses": { - "200": { - "description": "customer.Customer", - "schema": { - "$ref": "#/definitions/customer.Customer" - } - }, - "400": { - "description": "{\\\"error\\\": \\\"Invalid CPF\\\"}", - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - }, - "delete": { - "description": "Delete a customer by id", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Customer" - ], - "summary": "Delete customer", - "parameters": [ - { - "type": "string", - "description": "123456789", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK" - }, - "400": { - "description": "Invalid identifier informed" - } - } - } - }, - "/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": [ @@ -621,44 +254,6 @@ } } }, - "controller.CreateOrderPayload": { - "type": "object", - "required": [ - "client_id" - ], - "properties": { - "client_id": { - "type": "string", - "format": "uuid" - } - } - }, - "controller.CustomerPayload": { - "type": "object", - "required": [ - "cpf", - "email", - "name" - ], - "properties": { - "age": { - "type": "integer", - "maximum": 120, - "minimum": 18 - }, - "cpf": { - "type": "string" - }, - "email": { - "type": "string" - }, - "name": { - "type": "string", - "maxLength": 20, - "minLength": 5 - } - } - }, "controller.EditProductPayload": { "type": "object", "required": [ @@ -696,14 +291,6 @@ } } }, - "controller.HTTPError": { - "type": "object", - "properties": { - "error": { - "type": "string" - } - } - }, "controller.RemoveProductPayload": { "type": "object", "required": [ @@ -721,58 +308,6 @@ } } }, - "controller.UpdateOrderPayload": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "example": "paid" - } - } - }, - "customer.Customer": { - "type": "object", - "properties": { - "age": { - "type": "integer" - }, - "cpf": { - "type": "string" - }, - "email": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "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": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 96d2ea9..97e3103 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -19,33 +19,6 @@ definitions: - product_id - quantity type: object - controller.CreateOrderPayload: - properties: - client_id: - format: uuid - type: string - required: - - client_id - type: object - controller.CustomerPayload: - properties: - age: - maximum: 120 - minimum: 18 - type: integer - cpf: - type: string - email: - type: string - name: - maxLength: 20 - minLength: 5 - type: string - required: - - cpf - - email - - name - type: object controller.EditProductPayload: properties: client_id: @@ -72,11 +45,6 @@ definitions: required: - client_id type: object - controller.HTTPError: - properties: - error: - type: string - type: object controller.RemoveProductPayload: properties: client_id: @@ -89,40 +57,6 @@ definitions: - client_id - product_id type: object - controller.UpdateOrderPayload: - properties: - status: - example: paid - type: string - required: - - status - type: object - customer.Customer: - properties: - age: - type: integer - cpf: - type: string - email: - type: string - id: - type: string - 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: @@ -234,249 +168,6 @@ paths: description: Internal Server Error tags: - Cart - /customer: - get: - consumes: - - application/json - description: Overview all customer's list - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/customer.Customer' - type: array - summary: Overview customer list - tags: - - Customer - post: - consumes: - - application/json - description: Create a new customer - parameters: - - description: CustomerPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.CustomerPayload' - produces: - - application/json - responses: - "200": - description: customer.Customer - schema: - $ref: '#/definitions/customer.Customer' - "400": - description: '{\"error\": \"Invalid CPF\"}' - schema: - additionalProperties: true - type: object - summary: Create customer - tags: - - Customer - /customer/{cpf}: - get: - consumes: - - application/json - description: Overview a customer by cpf - parameters: - - description: customer cpf - in: path - name: cpf - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/customer.Customer' - "404": - description: Customer not found - summary: Overview customer by cpf - tags: - - Customer - /customer/{id}: - delete: - consumes: - - application/json - description: Delete a customer by id - parameters: - - description: "123456789" - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - "400": - description: Invalid identifier informed - summary: Delete customer - tags: - - Customer - put: - consumes: - - application/json - description: Update a customer by id - parameters: - - description: ID of the customer - in: path - name: id - required: true - type: string - - description: CustomerPayload - in: body - name: payload - required: true - schema: - $ref: '#/definitions/controller.CustomerPayload' - produces: - - application/json - responses: - "200": - description: customer.Customer - schema: - $ref: '#/definitions/customer.Customer' - "400": - description: '{\"error\": \"Invalid CPF\"}' - schema: - additionalProperties: true - type: object - 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: diff --git a/internal/adapters/rest/controller/customer_controller.go b/internal/adapters/rest/controller/customer_controller.go deleted file mode 100644 index 39a0af9..0000000 --- a/internal/adapters/rest/controller/customer_controller.go +++ /dev/null @@ -1,172 +0,0 @@ -package controller - -import ( - "github.com/pangolin-do-golang/tech-challenge/internal/errutil" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/pangolin-do-golang/tech-challenge/internal/core/customer" -) - -type CustomerController struct { - AbstractController - service customer.IService -} - -type CustomerPayload struct { - Name string `json:"name" binding:"required,min=5,max=20"` - Cpf string `json:"cpf" binding:"required,numeric,len=11"` - Email string `json:"email" binding:"required,email"` - Age int `json:"age" binding:"gte=18,lte=120"` -} - -func NewCustomerController(service customer.IService) *CustomerController { - return &CustomerController{ - service: service, - } -} - -// Create a new customer -// @Summary Create customer -// @Description Create a new customer -// @Tags Customer -// @Param payload body controller.CustomerPayload true "CustomerPayload" -// @Accept json -// @Produce json -// @Success 200 {object} customer.Customer "customer.Customer" -// @Failure 400 {object} map[string]any "{\"error\": \"Invalid CPF\"}" -// @Router /customer [post] -func (ctrl CustomerController) Create(c *gin.Context) { - var payload CustomerPayload - - if err := c.ShouldBindJSON(&payload); err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - created, err := ctrl.service.Create(customer.Customer{ - Name: payload.Name, - Cpf: payload.Cpf, - Email: payload.Email, - Age: payload.Age, - }) - - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusCreated, created) -} - -// Update a customer by id -// @Summary Update customer -// @Description Update a customer by id -// @Tags Customer -// @Param id path string true "ID of the customer" -// @Param payload body controller.CustomerPayload true "CustomerPayload" -// @Accept json -// @Produce json -// @Success 200 {object} customer.Customer "customer.Customer" -// @Failure 400 {object} map[string]any "{\"error\": \"Invalid CPF\"}" -// @Router /customer/{id} [put] -func (ctrl CustomerController) Update(c *gin.Context) { - id, err := uuid.Parse(c.Param("id")) - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - var payload CustomerPayload - - if err := c.ShouldBindJSON(&payload); err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - updated, err := ctrl.service.Update(id, customer.Customer{ - Name: payload.Name, - Cpf: payload.Cpf, - Email: payload.Email, - Age: payload.Age, - }) - - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusCreated, updated) -} - -// Delete a customer by id -// @Summary Delete customer -// @Description Delete a customer by id -// @Tags Customer -// @Param id path string true "123456789" -// @Accept json -// @Produce json -// @Success 200 -// @Failure 400 "Invalid identifier informed" -// @Router /customer/{id} [delete] -func (ctrl CustomerController) Delete(c *gin.Context) { - id, err := uuid.Parse(c.Param("id")) - - if err != nil { - ctrl.Error(c, errutil.NewInputError(err)) - return - } - - if err := ctrl.service.Delete(id); err != nil { - ctrl.Error(c, err) - return - } - - c.Status(http.StatusOK) -} - -// GetAll Overview all customer's list -// @Summary Overview customer list -// @Description Overview all customer's list -// @Tags Customer -// @Accept json -// @Produce json -// @Success 200 {object} []customer.Customer{} -// @Router /customer [get] -func (ctrl CustomerController) GetAll(c *gin.Context) { - customerSlice, err := ctrl.service.GetAll() - if err != nil { - ctrl.Error(c, err) - return - } - - c.JSON(http.StatusOK, customerSlice) -} - -// GetByCpf Overview a customer by cpf -// @Summary Overview customer by cpf -// @Description Overview a customer by cpf -// @Tags Customer -// @Param cpf path string true "customer cpf" -// @Accept json -// @Produce json -// @Success 200 {object} customer.Customer{} -// @Failure 404 "Customer not found" -// @Router /customer/{cpf} [get] -func (ctrl CustomerController) GetByCpf(c *gin.Context) { - cpf := c.Param("cpf") - - customerRecord, err := ctrl.service.GetByCpf(cpf) - if err != nil { - ctrl.Error(c, err) - return - } - - if customerRecord.Id == uuid.Nil { - ctrl.Error(c, errutil.NewBusinessError(err, "Customer not found")) - return - } - - c.JSON(http.StatusOK, customerRecord) -} 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/handler/customer.go b/internal/adapters/rest/handler/customer.go deleted file mode 100644 index ec200ee..0000000 --- a/internal/adapters/rest/handler/customer.go +++ /dev/null @@ -1,17 +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/customer" -) - -func RegisterCustomerHandlers(router *gin.Engine, service customer.IService) { - customerController := controller.NewCustomerController(service) - - router.POST("/customer", customerController.Create) - router.PUT("/customer/:id", customerController.Update) - router.DELETE("/customer/:id", customerController.Delete) - router.GET("/customer", customerController.GetAll) - router.GET("/customer/:cpf", customerController.GetByCpf) -} 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/server/server.go b/internal/adapters/rest/server/server.go index f11d322..05b9052 100644 --- a/internal/adapters/rest/server/server.go +++ b/internal/adapters/rest/server/server.go @@ -7,31 +7,23 @@ import ( "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" ) type RestServer struct { - orderService order.IOrderService - productService *product.Service - cartService cart.IService - customerService customer.IService + productService *product.Service + cartService cart.IService } type RestServerOptions struct { - OrderService order.IOrderService - ProductService *product.Service - CartService cart.IService - CustomerService customer.IService + ProductService *product.Service + CartService cart.IService } func NewRestServer(options *RestServerOptions) *RestServer { return &RestServer{ - orderService: options.OrderService, - productService: options.ProductService, - cartService: options.CartService, - customerService: options.CustomerService, + productService: options.ProductService, + cartService: options.CartService, } } @@ -42,10 +34,8 @@ 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") if err != nil { diff --git a/internal/core/customer/customer.go b/internal/core/customer/customer.go deleted file mode 100644 index 859507f..0000000 --- a/internal/core/customer/customer.go +++ /dev/null @@ -1,27 +0,0 @@ -package customer - -import "github.com/google/uuid" - -type Customer struct { - Id uuid.UUID `json:"id"` - Name string `json:"name"` - Cpf string `json:"cpf"` - Email string `json:"email"` - Age int `json:"age"` -} - -type IService interface { - Create(customer Customer) (*Customer, error) - Update(customerId uuid.UUID, customer Customer) (*Customer, error) - Delete(customerId uuid.UUID) error - GetAll() ([]Customer, error) - GetByCpf(customerCpf string) (*Customer, error) -} - -type IRepository interface { - Create(customer Customer) (*Customer, error) - Update(customerId uuid.UUID, customer Customer) (*Customer, error) - Delete(customerId uuid.UUID) error - GetAll() ([]Customer, error) - GetByCpf(customerCpf string) (*Customer, error) -} diff --git a/internal/core/customer/customer_service.go b/internal/core/customer/customer_service.go deleted file mode 100644 index d776480..0000000 --- a/internal/core/customer/customer_service.go +++ /dev/null @@ -1,42 +0,0 @@ -package customer - -import ( - "errors" - "github.com/google/uuid" -) - -type Service struct { - repository IRepository -} - -func NewService(customerRepository IRepository) *Service { - return &Service{ - repository: customerRepository, - } -} - -func (s *Service) Create(customer Customer) (*Customer, error) { - existingCustomer, _ := s.GetByCpf(customer.Cpf) - - if existingCustomer != nil { - return nil, errors.New("entered cpf is already registered in our system") - } - - return s.repository.Create(customer) -} - -func (s *Service) Update(customerId uuid.UUID, customer Customer) (*Customer, error) { - return s.repository.Update(customerId, customer) -} - -func (s *Service) Delete(customerId uuid.UUID) error { - return s.repository.Delete(customerId) -} - -func (s *Service) GetAll() ([]Customer, error) { - return s.repository.GetAll() -} - -func (s *Service) GetByCpf(cpf string) (*Customer, error) { - return s.repository.GetByCpf(cpf) -} 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 -}