diff --git a/.github/workflows/provisioning.yml b/.github/workflows/provision.yml similarity index 91% rename from .github/workflows/provisioning.yml rename to .github/workflows/provision.yml index 190b001..9a0c266 100644 --- a/.github/workflows/provisioning.yml +++ b/.github/workflows/provision.yml @@ -1,21 +1,21 @@ -name: Provisioning +name: Provision on: push: branches: - main paths: - - .github/workflows/provisioning.yml + - .github/workflows/provision.yml - 'terraform/**' pull_request: branches: - main paths: - - .github/workflows/provisioning.yml + - .github/workflows/provision.yml - 'terraform/**' jobs: - provisioning: + provision: runs-on: ubuntu-latest defaults: run: diff --git a/LICENSE b/LICENSE index 510b450..1dc4cee 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Bleno Claus, Giovanni di Luca, Mateus Albino, Wellyson Freitas +Copyright (c) 2023 Bleno Claus, Giovanni di Luca, Lucas Gabriel, Mateus Albino, Wellyson Freitas Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 0e65d80..5e1da8b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ # FIAP 3SOAT Tech Challenge - G15 -> **Para o avaliador da Fase 3 ✨** +> **Para o avaliador da Fase 4 ✨** > -> Queira encontrar todos os entregáveis nos outros repositórios desta organização no GitHub, todos com branches principais protegidas, pipelines para Continuous Integration (CI) e Continuous Delivery (CD) usando GitHub actions, com provisionamento de Infrastructure as Code (IaC) usando Terraform. A justificativa para a escolha do banco de dados foi documentada como Architecture Decision Record (ADR) em [`/docs/adr`](/docs/adr). +> Queira encontrar todos os entregáveis nos outros repositórios desta organização no GitHub incluindo **microsserviços** de [pagamentos](https://github.com/FIAP-3SOAT-G15/payments-api), [pedidos](https://github.com/FIAP-3SOAT-G15/orders-api), e [estoque](https://github.com/FIAP-3SOAT-G15/orders-api) (com testes usando **BDD / Cucumber**). +> +> Os microsserviços possuem seu próprio banco de dados isolado, sendo **NoSQL (DynamoDB)** no caso do microsserviço de [pagamentos](https://github.com/FIAP-3SOAT-G15/payments-api), e relacional (RDS / Postgres) nos demais. A comunicação é realizada de forma síncrona. +> +> Todos os repositórios têm branches principais protegidas, pipelines CI/CD usando GitHub Actions, com provisionamento de Infrastructure as Code (IaC) usando Terraform, e análise estática usando **SonarCloud** garantindo **80% de cobertura de testes**. +> +> Outros repositórios criados nas fases anteriores para o resto da infraestrutura também continuam ativos. Este projeto do curso de Pós-graduação em Arquitetura de Software da FIAP compreende uma solução possível para uma especificação referente a um sistema de autoatendimento de restaurante (do tipo fast-food), com quiosques ou terminais de autoatendimento. @@ -37,46 +43,28 @@ DDD foi a abordagem utilizada para o desenvolvimento, com as seguintes saídas d ## Arquitetura -O sistema expõe uma RESTful API para aplicações front-end, como terminais de autoatendimento para clientes e interfaces para administradores. Tem com dependência um provedor externo de pagamento, o Mercado Pago. As decisões de arquitetura foram devidamente documentadas como Architecture Decision Records (ADRs) em [`/docs/adr`](docs/adr). +O sistema expõe RESTful APIs para aplicações front-end, como terminais de autoatendimento para clientes e interfaces para administradores. Tem com dependência um provedor externo de pagamento, como o Mercado Pago. As decisões de arquitetura foram devidamente documentadas como Architecture Decision Records (ADRs) em [`/docs/adr`](docs/adr). ![Diagrama de Container C4](docs/diagrams/c4-container.png) -[Arquitetura Hexagonal](https://alistair.cockburn.us/hexagonal-architecture) (Ports and Adapters) e Clean Architecture são estritamente adotados no projeto, seguindo o princípio de Separation of Concerns. - -## Tecnologia - -Este é um projeto para JVM. Foi implementado em [Kotlin](https://kotlinlang.org) usando o [Maven](https://maven.apache.org) como gerenciador de dependências. Fora da camada de domínio algumas bibliotecas foram utilizadas, incluindo: - -- [Spring Framework](https://spring.io) como base do projeto -- [MapStruct](https://mapstruct.org) para mapeamento entre objetos (ex.: entity para model) -- [Flyway](https://flywaydb.org) para migrações de BD, permitindo [design evolutivo](https://martinfowler.com/articles/evodb.html) -- [Hibernate](https://hibernate.org) para mapeamento objeto-relacional +[Arquitetura Hexagonal](https://alistair.cockburn.us/hexagonal-architecture) (Ports and Adapters) e Clean Architecture são estritamente adotados no projeto. ## Mercado Pago Essa aplicação está integrada com o Mercado Pago, um provedor de pagamento. Com a realização do pedido, um QR code é criado num ponto de venda ("Point of Sale" ou "POS") da loja para ser pago pelo cliente através do aplicativo do Mercado Pago. Após o pagamento, o Mercado Pago notifica a aplicação através de um endpoint funcionando como webhook. -O fluxo de pagamento pode ser esquematizado no seguinte diagrama de sequência: - -![](docs/diagrams/payment-sequence.png) - [Consulte a documentação](/docs/mercado-pago.md) para saber mais sobre a integração. -## Banco de Dados - -O seguinte modelo de Entidade Relacionamento foi desenvolvido: - -![](docs/diagrams/db-er-diagram.png) - ## Infraestrutura Amazon Web Services (AWS) é usado como Cloud Provider e o Terraform é usado para provisionar Infrastructure as Code (IaC) hospedado neste repositório em [`/terraform`](terraform) e nos demais repositórios desta organização no GitHub. Os recursos incluem: -- repositório privado no Amazon Elastic Container Registry (ECR) +- repositórios privados no Amazon Elastic Container Registry (ECR) - cluster do Amazon Elastic Kubernetes Service (EKS) -- instância do Relational Database Service (RDS) for PostgreSQL +- instâncias do Relational Database Service (RDS) for PostgreSQL +- tabela do DynamoDB - secrets (de banco de dados e Mercado Pago) no Secrets Manager - parâmetros de sistema no SSM Parameter Store - API Gateway (Load Balancer no EKS como target) @@ -84,119 +72,3 @@ Os recursos incluem: - funções Lambda para autenticação Além de dependências como recursos do Virtual Private Cloud (VPC). - -![](docs/diagrams/aws.jpeg) - -## CI / CD - -Pipelines foram configuradas usando o [GitHub Actions](https://github.com/features/actions). - -Neste repositório existem as seguintes pipelines: - -- **app:** build, verificação, publicação da imagem no ECR -- **docs:** geração e publicação do website de documentação com [MkDocs](https://www.mkdocs.org/) -- **openapi:** geração OpenAPI em JSON e sincronização com Postman API -- **provisioning:** provisionamento de IaC na AWS com Terraform - -As imagens e containers Docker utilizados para implementação das pipelines podem ser verificados no [Makefile](Makefile). - -## Documentação - -Consulte a documentação em [`/docs`](docs) ou acesse: - -[http://fiap-3soat-g15.s3-website-us-east-1.amazonaws.com](http://fiap-3soat-g15.s3-website-us-east-1.amazonaws.com/) - -A especificação **OpenAPI (Swagger)** em formato JSON também é publicado: - -[http://fiap-3soat-g15.s3-website-us-east-1.amazonaws.com/openapi.json](http://fiap-3soat-g15.s3-website-us-east-1.amazonaws.com/openapi.json) - -Com a aplicação em execução, você tambem pode acessar o Swagger UI: - -[http://localhost:8080/swagger-ui/index.html](http://localhost:8080/swagger-ui/index.html) - -Preview: - -![Swagger UI](docs/img/swagger-ui.png) - -## Postman collection - -Acesse a API sincronizada no Postman: - -[Postman API](https://fiap-3soat-g15.postman.co/workspace/tech-challenge~febf1412-7ce2-4cb4-8bca-50f4fdd3a479/api/c77ec61d-c410-443e-92f7-c204be16083b?action=share&creator=12986472) - -Uma collection sincronizada também fica disponível em: - -[docs/postman-collection.json](docs/postman-collection.json) - -Use o seguinte token como header `x-admin-token` para testar endpoints `/admin/**`: - -``` -token -``` - -## Como executar localmente - -A forma mais simples é utilizando o [Docker Compose](https://docs.docker.com/compose): - -```bash -docker compose up -``` - -## Desenvolvimento - -### Mappers - -[MapStruct](https://mapstruct.org) é usado para mapear entities e models e implementaçōes para os mappers anotados com `@Mapper` são geradas em tempo de compilação: - -``` -mvn clean compile -``` - -### Testes - -``` -mvn clean verify -``` - -Para incluir os testes de integração: - -``` -mvn clean verify -DskipITs=false -``` - -### ktlint - -``` -mvn antrun:run@ktlint-format -``` - -### Kubernetes local - -``` -minikube start -``` - -Consulte: https://kubernetes.io/docs/tasks/tools - -### Imagem no Minikube - -Crie a imagem local com o mesmo nome da imagem remota. - -Exemplo com macOS: - -``` -eval $(minikube docker-env) -docker build -t 202062340677.dkr.ecr.us-east-1.amazonaws.com/tech-challenge:latest . -``` - -Consulte: https://minikube.sigs.k8s.io/docs/handbook/pushing - -### ngrok - -Para expor a aplicação local externalmente: - -``` -ngrok http http://localhost:8080 -``` - -Acesse o endereço de redirecionamento ("forwarding"). diff --git a/docs/diagrams/c4-container.png b/docs/diagrams/c4-container.png index 9dd121b..71efdb4 100644 Binary files a/docs/diagrams/c4-container.png and b/docs/diagrams/c4-container.png differ diff --git a/docs/mercado-pago.md b/docs/mercado-pago.md index 31a6cd2..ec90f79 100644 --- a/docs/mercado-pago.md +++ b/docs/mercado-pago.md @@ -2,8 +2,6 @@ Essa aplicação está integrada com o Mercado Pago, um provedor de pagamento. Com a realização do pedido, um QR code é criado num ponto de venda ("Point of Sale" ou "POS") da loja para ser pago pelo cliente através do aplicativo do Mercado Pago. Após o pagamento, o Mercado Pago notifica a aplicação através de um endpoint funcionando como webhook. -![](diagrams/payment-sequence.png) - O webhook exposto é `/payments/notifications/{orderNumber}`, e aceita notificações do Mercado Pago do tipo Instant Payment Notification (IPN), assinadas com header `x-signature`. A validação da assinatura, conforme documentação do Mercado Pago, não foi implementada por simplificação. ## Configuração e testes diff --git a/docs/puml/container.puml b/docs/puml/container.puml index 5c9dc0f..afbbfa4 100644 --- a/docs/puml/container.puml +++ b/docs/puml/container.puml @@ -2,18 +2,38 @@ !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml LAYOUT_LEFT_RIGHT() +LAYOUT_WITH_LEGEND() title Diagrama de Container C4 System_Boundary(self_order_system, "Sistema de Autoatendimento de Restaurante") { - Container(api, "API", "Spring Boot") - ContainerDb(db, "Banco de Dados", "Postgres") + System_Boundary(payment_system, "Pagamentos") { + Container(payment_api, "Pagamentos API", "Spring Boot") + ContainerDb(payment_db, "Pagamentos DB", "DynamoDB") + } + + System_Boundary(order_system, "Pedidos") { + Container(orders_api, "Pedidos API", "Spring Boot") + ContainerDb(orders_db, "Pedidos DB", "Postgres") + } + + System_Boundary(stock_system, "Estoque") { + Container(stock_api, "Estoque API", "Spring Boot") + ContainerDb(stock_db, "Estoque DB", "Postgres") + } } -System_Ext(payment_system, "Mercado Pago", "sistema de pagamento") +System_Ext(payment_provider_system, "Provedor de Pagamento", "ex.: Mercado Pago") + +Rel(orders_api, orders_db, "read / write", "JDBC") +Rel(orders_api, stock_api, "acessa", "HTTP") +Rel(orders_api, payment_api, "acessa", "HTTP") + +Rel(stock_api, stock_db, "read / write", "JDBC") -Rel(api, db, "read / write", "JDBC") -Rel(api, payment_system, "usa", "HTTP") -Rel(payment_system, api, "notifica", "HTTP") +Rel(payment_api, payment_db, "read / write", "JDBC") +Rel(payment_api, payment_provider_system, "usa", "HTTP") +Rel(payment_api, orders_api, "notifica", "HTTP") +Rel(payment_provider_system, payment_api, "notifica", "HTTP") @enduml diff --git a/docs/puml/context.puml b/docs/puml/context.puml index c739f0f..df0f868 100644 --- a/docs/puml/context.puml +++ b/docs/puml/context.puml @@ -9,7 +9,7 @@ Person_Ext(customer, "Cliente", "cliente do restaurante,\ncom ou sem cadastro") Person(admin, "Administrador", "administrador do restaurante") System(system, "Sistema de Autoatendimento de Restaurante", "permite fazer e acompanhar pedidos, além de gerenciar pedidos, clientes, produtos, estoque, etc") -System_Ext(payment_system, "Mercado Pago", "Sistema de pagamento") +System_Ext(payment_system, "Provedor de Pagamento", "ex.: Mercado Pago") Rel(customer, system, "usa") Rel(customer, payment_system, "paga") diff --git a/src/main/kotlin/com/fiap/selfordermanagement/SelfOrderManagementApplication.kt b/src/main/kotlin/com/fiap/selfordermanagement/SelfOrderManagementApplication.kt deleted file mode 100644 index fd47f14..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/SelfOrderManagementApplication.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.fiap.selfordermanagement - -import io.swagger.v3.oas.annotations.OpenAPIDefinition -import io.swagger.v3.oas.annotations.info.Contact -import io.swagger.v3.oas.annotations.info.Info -import io.swagger.v3.oas.annotations.servers.Server -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -@OpenAPIDefinition( - info = - Info( - title = "Self-Order Management API", - version = "1.0.0", - description = - "API de autoatendimento em restaurante como implementação do Tech Challenge" + - " referente à primeira fase do curso de pós-graduação em Arquitetura de Software pela FIAP.", - contact = - Contact( - name = "Grupo 15", - url = "http://fiap-3soat-g15.s3-website-us-east-1.amazonaws.com", - ), - ), - servers = [ - Server(url = "/"), - ], -) -class SelfOrderManagementApplication - -fun main(args: Array) { - runApplication(*args) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/ComponentController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/ComponentController.kt deleted file mode 100644 index a78bde7..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/ComponentController.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.driver.web.ComponentAPI -import com.fiap.selfordermanagement.driver.web.request.ComponentRequest -import com.fiap.selfordermanagement.usecases.CreateComponentUseCase -import com.fiap.selfordermanagement.usecases.LoadComponentUseCase -import com.fiap.selfordermanagement.usecases.SearchComponentUseCase -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.RestController - -@RestController -class ComponentController( - private val loadComponentUseCase: LoadComponentUseCase, - private val createComponentUseCase: CreateComponentUseCase, - private val searchComponentUseCase: SearchComponentUseCase, -) : ComponentAPI { - override fun findAll(): ResponseEntity> { - return ResponseEntity.ok(loadComponentUseCase.findAll()) - } - - override fun findByProductNumber(productNumber: Long): ResponseEntity> { - return ResponseEntity.ok(loadComponentUseCase.findByProductNumber(productNumber)) - } - - override fun create(componentRequest: ComponentRequest): ResponseEntity { - return ResponseEntity.ok( - createComponentUseCase.create( - componentRequest.toComponent(), - componentRequest.initialQuantity, - ), - ) - } - - override fun searchByName(name: String): ResponseEntity> { - return ResponseEntity.ok(searchComponentUseCase.searchByName(name.trim())) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/CustomerController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/CustomerController.kt deleted file mode 100644 index 5386cdc..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/CustomerController.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Customer -import com.fiap.selfordermanagement.driver.web.CustomersAPI -import com.fiap.selfordermanagement.driver.web.request.CustomerRequest -import com.fiap.selfordermanagement.usecases.* -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.RestController -import java.util.* - -@RestController -class CustomerController( - private val loadCustomersUseCase: LoadCustomerUseCase, - private val searchCustomerUseCase: SearchCustomerUseCase, - private val createCustomerUseCase: CreateCustomerUseCase, - private val updateCustomerUseCase: UpdateCustomerUseCase, - private val removeCustomerUseCase: RemoveCustomerUseCase, -) : CustomersAPI { - override fun getById(customerId: String): ResponseEntity { - customerId - .runCatching { UUID.fromString(this) } - .getOrElse { return ResponseEntity.notFound().build() } - .run { return ResponseEntity.ok(loadCustomersUseCase.getById(this)) } - } - - override fun findAll(): ResponseEntity> { - return ResponseEntity.ok(loadCustomersUseCase.findAll()) - } - - override fun searchByName(name: String): ResponseEntity> { - return ResponseEntity.ok(searchCustomerUseCase.searchByName(name)) - } - - override fun create(customerRequest: CustomerRequest): ResponseEntity { - return ResponseEntity.ok(createCustomerUseCase.create(customerRequest.toDomain())) - } - - override fun update( - customerId: String, - customerRequest: CustomerRequest, - ): ResponseEntity { - customerId - .runCatching { UUID.fromString(customerId) } - .getOrElse { return ResponseEntity.notFound().build() } - .let { customerRequest.toDomain().copy(id = it) } - .run { return ResponseEntity.ok(updateCustomerUseCase.update(this)) } - } - - override fun remove(customerId: String): ResponseEntity { - customerId - .runCatching { UUID.fromString(this) } - .getOrElse { return ResponseEntity.notFound().build() } - .run { return ResponseEntity.ok(removeCustomerUseCase.remove(this)) } - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/MenuController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/MenuController.kt deleted file mode 100644 index 3883e15..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/MenuController.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import com.fiap.selfordermanagement.driver.web.MenuAPI -import com.fiap.selfordermanagement.usecases.LoadProductUseCase -import com.fiap.selfordermanagement.usecases.SearchProductUseCase -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.RestController - -@RestController -class MenuController( - private val loadProductUseCase: LoadProductUseCase, - private val searchProductUseCase: SearchProductUseCase, -) : MenuAPI { - override fun findAll(): ResponseEntity> { - return ResponseEntity.ok(loadProductUseCase.findAll()) - } - - override fun findByCategory(category: String): ResponseEntity> { - return ResponseEntity.ok(loadProductUseCase.findByCategory(ProductCategory.fromString(category))) - } - - override fun searchByName(name: String): ResponseEntity> { - return ResponseEntity.ok(searchProductUseCase.searchByName(name)) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/OrderController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/OrderController.kt deleted file mode 100644 index 42406fa..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/OrderController.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import com.fiap.selfordermanagement.driver.web.OrdersAPI -import com.fiap.selfordermanagement.driver.web.request.OrderRequest -import com.fiap.selfordermanagement.driver.web.response.OrderToPayResponse -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import org.springframework.http.ResponseEntity -import org.springframework.security.core.context.SecurityContextHolder -import org.springframework.security.oauth2.core.ClaimAccessor -import org.springframework.web.bind.annotation.RestController -import java.util.* - -@RestController -class OrderController( - private val loadOrdersUseCase: com.fiap.selfordermanagement.usecases.LoadOrderUseCase, - private val createOrderUseCase: com.fiap.selfordermanagement.usecases.PlaceOrderUseCase, - private val loadPaymentUseCase: LoadPaymentUseCase, - private val prepareOrderUseCase: com.fiap.selfordermanagement.usecases.PrepareOrderUseCase, - private val completeOrderUseCase: com.fiap.selfordermanagement.usecases.CompleteOrderUseCase, - private val cancelOrderStatusUseCase: com.fiap.selfordermanagement.usecases.CancelOrderStatusUseCase, -) : OrdersAPI { - override fun getByOrderNumber(orderNumber: Long): ResponseEntity { - return ResponseEntity.ok(loadOrdersUseCase.getByOrderNumber(orderNumber)) - } - - override fun findAll(): ResponseEntity> { - return ResponseEntity.ok(loadOrdersUseCase.findAll()) - } - - override fun getByStatus(status: String): ResponseEntity> { - return ResponseEntity.ok(loadOrdersUseCase.findByStatus(OrderStatus.fromString(status))) - } - - override fun getByStatusAndCustomerId( - status: String, - customerId: String, - ): ResponseEntity> { - val orderStatus = OrderStatus.fromString(status) - customerId - .runCatching { UUID.fromString(this) } - .getOrElse { return ResponseEntity.notFound().build() } - .let { loadOrdersUseCase.findByCustomerIdAndStatus(it, orderStatus) } - .run { return ResponseEntity.ok(this) } - } - - override fun getByCustomerId(customerId: String): ResponseEntity> { - customerId - .runCatching { UUID.fromString(this) } - .getOrElse { return ResponseEntity.notFound().build() } - .let { loadOrdersUseCase.findByCustomerId(it) } - .run { return ResponseEntity.ok(this) } - } - - override fun create(orderRequest: OrderRequest): ResponseEntity { - var customerId: UUID? = null - try { - customerId = UUID.fromString((SecurityContextHolder.getContext().authentication.credentials as ClaimAccessor).getClaim("custom:CUSTOMER_ID")) - } catch (_: Exception) { - } - - val order = - createOrderUseCase.create( - customerId, - orderRequest.toOrderItemDomain(), - ) - val payment = loadPaymentUseCase.getByOrderNumber(order.number!!) - - return ResponseEntity.ok( - OrderToPayResponse( - order = order, - paymentInfo = payment.paymentInfo, - ), - ) - } - - override fun start(orderNumber: Long): ResponseEntity { - return ResponseEntity.ok(prepareOrderUseCase.startOrderPreparation(orderNumber)) - } - - override fun finish(orderNumber: Long): ResponseEntity { - return ResponseEntity.ok(prepareOrderUseCase.finishOrderPreparation(orderNumber)) - } - - override fun complete(orderNumber: Long): ResponseEntity { - return ResponseEntity.ok(completeOrderUseCase.completeOrder(orderNumber)) - } - - override fun cancel(orderNumber: Long): ResponseEntity { - return ResponseEntity.ok(cancelOrderStatusUseCase.cancelOrder(orderNumber)) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/PaymentController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/PaymentController.kt deleted file mode 100644 index d722938..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/PaymentController.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Payment -import com.fiap.selfordermanagement.driver.web.PaymentAPI -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import com.fiap.selfordermanagement.usecases.SyncPaymentUseCase -import org.slf4j.LoggerFactory -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.RestController - -@RestController -class PaymentController( - private val loadPaymentUseCase: LoadPaymentUseCase, - private val syncPaymentUseCase: SyncPaymentUseCase -) : PaymentAPI { - private val log = LoggerFactory.getLogger(javaClass) - - override fun findAll(): ResponseEntity> { - return ResponseEntity.ok(loadPaymentUseCase.findAll()) - } - - override fun getByOrderNumber(orderNumber: Long): ResponseEntity { - return ResponseEntity.ok(loadPaymentUseCase.getByOrderNumber(orderNumber)) - } - - /** - * The server response is important to flag the provider for retries - */ - override fun notify(orderNumber: Long, resourceId: String, topic: String): ResponseEntity { - // TODO: verify x-signature header by Mercado Pago - log.info("Notification received for order ${orderNumber}: type=${topic} externalId=${resourceId}") - - when (topic) { - IPNType.MERCHANT_ORDER.ipnType -> { - syncPaymentUseCase.syncPayment(orderNumber, resourceId) - return ResponseEntity.ok().build() - } - IPNType.PAYMENT.ipnType -> { - val payment = loadPaymentUseCase.getByOrderNumber(orderNumber) - payment.externalOrderGlobalId?.let { - syncPaymentUseCase.syncPayment(orderNumber, it) - return ResponseEntity.ok().build() - } - // returns server error because external order global ID was not previously saved, - // which does not conform with the usual application flow - return ResponseEntity.internalServerError().build() - } - else -> { - // returns bad request because application does not accept this kind of IPN types - return ResponseEntity.badRequest().build() - } - } - } - - enum class IPNType(val ipnType: String) { - MERCHANT_ORDER("merchant_order"), - PAYMENT("payment"), - CHARGEBACK("chargebacks"), - POINT_INTEGRATION_IPN("point_integration_ipn"), - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/ProductController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/ProductController.kt deleted file mode 100644 index 4ede669..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/ProductController.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import com.fiap.selfordermanagement.driver.web.ProductAPI -import com.fiap.selfordermanagement.driver.web.request.ProductComposeRequest -import com.fiap.selfordermanagement.driver.web.request.ProductRequest -import com.fiap.selfordermanagement.driver.web.response.ProductResponse -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.RestController - -@RestController -class ProductController( - private val assembleProductsUseCase: com.fiap.selfordermanagement.usecases.AssembleProductsUseCase, - private val loadProductUseCase: com.fiap.selfordermanagement.usecases.LoadProductUseCase, - private val searchProductUseCase: com.fiap.selfordermanagement.usecases.SearchProductUseCase, -) : ProductAPI { - override fun getByProductNumber(productNumber: Long): ResponseEntity { - return loadProductUseCase.getByProductNumber(productNumber).let(::createResponse) - } - - override fun findAll(): ResponseEntity> { - return loadProductUseCase.findAll().let(::respond) - } - - override fun findByCategory(category: String): ResponseEntity> { - return loadProductUseCase.findByCategory(ProductCategory.fromString(category)).let(::respond) - } - - override fun searchByName(name: String): ResponseEntity> { - return searchProductUseCase.searchByName(name).let(::respond) - } - - override fun create(productRequest: ProductRequest): ResponseEntity { - val result = - assembleProductsUseCase.create(productRequest.toDomain(), productRequest.components).let(::createResponse) - return result - } - - override fun update( - productNumber: Long, - productRequest: ProductRequest, - ): ResponseEntity { - val product = productRequest.toDomain().copy(number = productNumber) - return assembleProductsUseCase.update(product, productRequest.components).let(::createResponse) - } - - override fun delete(productNumber: Long): ResponseEntity { - return assembleProductsUseCase.delete(productNumber).let(::createResponse) - } - - override fun compose(productComposeRequest: ProductComposeRequest): ResponseEntity { - return assembleProductsUseCase.compose( - productComposeRequest.productNumber, - productComposeRequest.subItemsNumbers, - ).let(::createResponse) - } - - private fun createResponse(product: Product?): ResponseEntity { - return ResponseEntity.ok(product?.let { ProductResponse.fromDomain(product) }) - } - - private fun respond(products: List): ResponseEntity> { - return ResponseEntity.ok(products.map { ProductResponse.fromDomain(it) }) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/StockController.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/StockController.kt deleted file mode 100644 index 3a441b3..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/StockController.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller - -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.driver.web.StockAPI -import com.fiap.selfordermanagement.driver.web.request.QuantityRequest -import com.fiap.selfordermanagement.usecases.AdjustStockUseCase -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.RestController - -@RestController -class StockController( - private val adjustStockUseCase: AdjustStockUseCase, -) : StockAPI { - override fun increment( - componentNumber: Long, - quantityRequest: QuantityRequest, - ): ResponseEntity { - return ResponseEntity.ok(adjustStockUseCase.increment(componentNumber, quantityRequest.quantity)) - } - - override fun decrement( - componentNumber: Long, - quantityRequest: QuantityRequest, - ): ResponseEntity { - return ResponseEntity.ok(adjustStockUseCase.decrement(componentNumber, quantityRequest.quantity)) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/configuration/ControllerExceptionHandler.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/configuration/ControllerExceptionHandler.kt deleted file mode 100644 index 8c41168..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/configuration/ControllerExceptionHandler.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller.configuration - -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.ControllerAdvice -import org.springframework.web.bind.annotation.ExceptionHandler - -@ControllerAdvice -class ControllerExceptionHandler { - @ExceptionHandler(SelfOrderManagementException::class) - protected fun domainErrorHandler(domainException: SelfOrderManagementException): ResponseEntity { - val apiErrorResponseEntity: ApiErrorResponseEntity = - when (domainException.errorType) { - ErrorType.PRODUCT_ALREADY_EXISTS, - ErrorType.CUSTOMER_ALREADY_EXISTS, - ErrorType.STOCK_ALREADY_EXISTS, - ErrorType.PAYMENT_ALREADY_EXISTS, - ErrorType.INSUFFICIENT_STOCK, - -> - ApiErrorResponseEntity( - ApiError(domainException.errorType.name, domainException.message), - HttpStatus.UNPROCESSABLE_ENTITY, - ) - - ErrorType.CUSTOMER_NOT_FOUND, - ErrorType.PRODUCT_NOT_FOUND, - ErrorType.COMPONENT_NOT_FOUND, - ErrorType.STOCK_NOT_FOUND, - ErrorType.ORDER_NOT_FOUND, - ErrorType.PAYMENT_NOT_FOUND, - -> - ApiErrorResponseEntity( - ApiError(domainException.errorType.name, domainException.message), - HttpStatus.NOT_FOUND, - ) - - ErrorType.INVALID_ORDER_STATUS, - ErrorType.INVALID_ORDER_STATE_TRANSITION, - ErrorType.INVALID_PRODUCT_CATEGORY, - ErrorType.EMPTY_ORDER, - ErrorType.PRODUCT_NUMBER_IS_MANDATORY, - ErrorType.COMPONENT_NUMBER_IS_MANDATORY, - -> - ApiErrorResponseEntity( - ApiError(domainException.errorType.name, domainException.message), - HttpStatus.BAD_REQUEST, - ) - - ErrorType.PAYMENT_NOT_CONFIRMED, - ErrorType.PAYMENT_REQUEST_NOT_ALLOWED, - -> - ApiErrorResponseEntity( - ApiError(domainException.errorType.name, domainException.message), - HttpStatus.PAYMENT_REQUIRED, - ) - - else -> - ApiErrorResponseEntity( - ApiError(ErrorType.UNEXPECTED_ERROR.name, domainException.localizedMessage), - HttpStatus.INTERNAL_SERVER_ERROR, - ) - } - return ResponseEntity.status(apiErrorResponseEntity.status).body(apiErrorResponseEntity.body) - } - - data class ApiError(val error: String, val message: String?) - - data class ApiErrorResponseEntity(val body: ApiError, val status: HttpStatus) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/configuration/ServiceConfig.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/configuration/ServiceConfig.kt deleted file mode 100644 index e83175c..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/controller/configuration/ServiceConfig.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.fiap.selfordermanagement.adapter.controller.configuration - -import com.fiap.selfordermanagement.SelfOrderManagementApplication -import com.fiap.selfordermanagement.adapter.gateway.ComponentGateway -import com.fiap.selfordermanagement.adapter.gateway.CustomerGateway -import com.fiap.selfordermanagement.adapter.gateway.OrderGateway -import com.fiap.selfordermanagement.adapter.gateway.PaymentGateway -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.adapter.gateway.TransactionalGateway -import com.fiap.selfordermanagement.usecases.AdjustStockUseCase -import com.fiap.selfordermanagement.usecases.ConfirmOrderUseCase -import com.fiap.selfordermanagement.usecases.LoadComponentUseCase -import com.fiap.selfordermanagement.usecases.LoadCustomerUseCase -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import com.fiap.selfordermanagement.usecases.LoadProductUseCase -import com.fiap.selfordermanagement.usecases.ProvidePaymentRequestUseCase -import com.fiap.selfordermanagement.usecases.services.ComponentService -import com.fiap.selfordermanagement.usecases.services.CustomerService -import com.fiap.selfordermanagement.usecases.services.PaymentSyncService -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration -import services.OrderService -import services.PaymentService -import services.ProductService -import services.StockService - -@Configuration -@ComponentScan(basePackageClasses = [SelfOrderManagementApplication::class]) -class ServiceConfig { - @Bean - fun createCustomerService(customerRepository: CustomerGateway): CustomerService { - return CustomerService(customerRepository) - } - - @Bean - fun createProductService( - productRepository: ProductGateway, - loadComponentUseCase: LoadComponentUseCase, - ): ProductService { - return ProductService( - productRepository, - loadComponentUseCase, - ) - } - - @Bean - fun createComponentService( - componentRepository: ComponentGateway, - stockRepository: StockGateway, - productRepository: ProductGateway, - ): ComponentService { - return ComponentService( - componentRepository, - stockRepository, - productRepository, - ) - } - - @Bean - fun createStockService(stockRepository: StockGateway): StockService { - return StockService(stockRepository) - } - - @Bean - fun createOrderService( - orderRepository: OrderGateway, - loadCustomerUseCase: LoadCustomerUseCase, - loadProductsUseCase: LoadProductUseCase, - adjustInventoryUseCase: AdjustStockUseCase, - providePaymentRequestUseCase: ProvidePaymentRequestUseCase, - loadPaymentUseCase: LoadPaymentUseCase, - transactionalRepository: TransactionalGateway, - ): OrderService { - return OrderService( - orderRepository, - loadCustomerUseCase, - loadProductsUseCase, - adjustInventoryUseCase, - providePaymentRequestUseCase, - loadPaymentUseCase, - transactionalRepository, - ) - } - - @Bean - fun createPaymentService( - paymentRepository: PaymentGateway, - paymentProvider: PaymentProviderGateway, - ): PaymentService { - return PaymentService( - paymentRepository, - paymentProvider - ) - } - - @Bean - fun paymentSyncService( - confirmOrderUseCase: ConfirmOrderUseCase, - loadPaymentUseCase: LoadPaymentUseCase, - paymentGateway: PaymentGateway, - paymentProvider: PaymentProviderGateway, - ): PaymentSyncService { - return PaymentSyncService( - confirmOrderUseCase, - loadPaymentUseCase, - paymentGateway, - paymentProvider, - ) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/ComponentGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/ComponentGateway.kt deleted file mode 100644 index 565d034..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/ComponentGateway.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Component - -interface ComponentGateway { - fun findAll(): List - - fun findByComponentNumber(componentNumber: Long): Component? - - fun searchByName(componentName: String): List - - fun create(component: Component): Component - - fun update(component: Component): Component - - fun delete(component: Component): Component - - fun deleteAll() -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/CustomerGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/CustomerGateway.kt deleted file mode 100644 index 36e969a..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/CustomerGateway.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Customer -import java.util.* - -interface CustomerGateway { - fun findAll(): List - - fun findById(customerId: UUID): Customer? - - fun searchByName(name: String): List - - fun searchByEmail(email: String): Customer? - - fun searchByDocument(document: String): Customer? - - fun create(customer: Customer): Customer - - fun update(customer: Customer): Customer - - fun deleteById(customerId: UUID): Customer - - fun deleteAll() -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/OrderGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/OrderGateway.kt deleted file mode 100644 index 781d7f6..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/OrderGateway.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import java.util.* - -interface OrderGateway { - fun findAllActiveOrders(): List - - fun findByOrderNumber(number: Long): Order? - - fun findByStatus(status: OrderStatus): List - - fun findByCustomerId(customerId: UUID): List - - fun findByCustomerIdAndStatus( - customerId: UUID, - status: OrderStatus, - ): List - - fun upsert(order: Order): Order - - fun deleteAll() -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/PaymentGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/PaymentGateway.kt deleted file mode 100644 index 1e27488..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/PaymentGateway.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Payment - -interface PaymentGateway { - fun findByOrderNumber(orderNumber: Long): Payment? - - fun findAll(): List - - fun create(payment: Payment): Payment - - fun update(payment: Payment): Payment -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/PaymentProviderGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/PaymentProviderGateway.kt deleted file mode 100644 index 034adeb..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/PaymentProviderGateway.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.PaymentRequest -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus - -interface PaymentProviderGateway { - fun createExternalOrder(order: Order): PaymentRequest - - fun checkExternalOrderStatus(externalOrderGlobalId: String): PaymentStatus -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/ProductGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/ProductGateway.kt deleted file mode 100644 index 3baa2b4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/ProductGateway.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory - -interface ProductGateway { - fun findAll(): List - - fun findByProductNumber(productNumber: Long): Product? - - fun findByCategory(category: ProductCategory): List - - fun searchByName(name: String): List - - fun create(product: Product): Product - - fun update(product: Product): Product - - fun delete(productNumber: Long): Product - - fun deleteAll() -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/StockGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/StockGateway.kt deleted file mode 100644 index a6f7ca8..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/StockGateway.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -import com.fiap.selfordermanagement.domain.entities.Stock - -interface StockGateway { - fun findByComponentNumber(componentNumber: Long): Stock? - - fun create(stock: Stock): Stock - - fun update(stock: Stock): Stock -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/TransactionalGateway.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/TransactionalGateway.kt deleted file mode 100644 index 0f700fc..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/TransactionalGateway.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway - -interface TransactionalGateway { - fun transaction(code: () -> T): T -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/ComponentGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/ComponentGatewayImpl.kt deleted file mode 100644 index f6dae1f..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/ComponentGatewayImpl.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.ComponentGateway -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.driver.database.persistence.jpa.ComponentJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.mapper.ComponentMapper -import org.mapstruct.factory.Mappers - -class ComponentGatewayImpl( - private val componentJpaRepository: ComponentJpaRepository, -) : ComponentGateway { - private val mapper = Mappers.getMapper(ComponentMapper::class.java) - - override fun findByComponentNumber(componentNumber: Long): Component? { - return componentJpaRepository.findById(componentNumber) - .map(mapper::toDomain) - .orElse(null) - } - - override fun findAll(): List { - return componentJpaRepository.findAll().map(mapper::toDomain) - } - - override fun searchByName(componentName: String): List { - return componentJpaRepository.findByNameContainingIgnoreCase(componentName) - .map(mapper::toDomain) - } - - override fun create(component: Component): Component { - val newComponent = component.copy(number = null) - return persist(newComponent) - } - - override fun update(component: Component): Component { - val newItem = - component.number - ?.let { - findByComponentNumber(it) - ?.update(component) - ?: throw SelfOrderManagementException( - errorType = ErrorType.COMPONENT_NUMBER_IS_MANDATORY, - message = "Component ${component.name} not identified by number", - ) - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.COMPONENT_NOT_FOUND, - message = "Component [${component.name}] not found", - ) - return persist(newItem) - } - - override fun delete(component: Component): Component { - val number = - component.number ?: throw SelfOrderManagementException( - errorType = ErrorType.COMPONENT_NUMBER_IS_MANDATORY, - message = "Component ${component.name} not identified by number", - ) - val item = - findByComponentNumber(number) - ?: throw SelfOrderManagementException( - errorType = ErrorType.COMPONENT_NOT_FOUND, - message = "Component [${component.number}] not found", - ) - componentJpaRepository.deleteById(item.number!!) - return component - } - - override fun deleteAll() { - componentJpaRepository.deleteAll() - } - - private fun persist(component: Component): Component = - component - .let(mapper::toEntity) - .let(componentJpaRepository::save) - .let(mapper::toDomain) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/CustomerGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/CustomerGatewayImpl.kt deleted file mode 100644 index 019a7b6..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/CustomerGatewayImpl.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.CustomerGateway -import com.fiap.selfordermanagement.domain.entities.Customer -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.driver.database.persistence.jpa.CustomerJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.mapper.CustomerMapper -import org.mapstruct.factory.Mappers -import java.util.* - -class CustomerGatewayImpl( - private val customerJpaRepository: CustomerJpaRepository, -) : CustomerGateway { - private val mapper: CustomerMapper = Mappers.getMapper(CustomerMapper::class.java) - - override fun findAll(): List { - return customerJpaRepository.findAll() - .map(mapper::toDomain) - } - - override fun findById(customerId: UUID): Customer? { - return customerJpaRepository.findById(customerId.toString()) - .map(mapper::toDomain) - .orElse(null) - } - - override fun searchByName(name: String): List { - return customerJpaRepository.findByNameContainingIgnoreCase(name) - .map(mapper::toDomain) - } - - override fun searchByEmail(email: String): Customer? { - return customerJpaRepository.findByEmail(email) - .map(mapper::toDomain) - .orElse(null) - } - - override fun create(customer: Customer): Customer { - customer.email - ?.let { searchByEmail(it) } - ?.let { - throw SelfOrderManagementException( - errorType = ErrorType.CUSTOMER_ALREADY_EXISTS, - message = "Customer with email [${customer.email}] already exists", - ) - } - - customer.document - ?.let { searchByDocument(it) } - ?.let { - throw SelfOrderManagementException( - errorType = ErrorType.CUSTOMER_ALREADY_EXISTS, - message = "Customer with document [${customer.document}] already exists", - ) - } - - return persist(customer) - } - - override fun searchByDocument(document: String): Customer? { - return customerJpaRepository.findByDocument(document) - .map(mapper::toDomain) - .orElse(null) - } - - override fun update(customer: Customer): Customer { - val newItem = - findById(customer.id) - ?.update(customer) - ?: throw SelfOrderManagementException( - errorType = ErrorType.CUSTOMER_NOT_FOUND, - message = "Customer [${customer.document}] not found", - ) - return persist(newItem) - } - - override fun deleteById(customerId: UUID): Customer { - return findById(customerId) - ?.let { - customerJpaRepository.deleteById(customerId.toString()) - it - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.CUSTOMER_NOT_FOUND, - message = "Customer [$customerId] not found", - ) - } - - override fun deleteAll() { - customerJpaRepository.deleteAll() - } - - private fun persist(customer: Customer): Customer = - customer - .let(mapper::toEntity) - .let(customerJpaRepository::save) - .let(mapper::toDomain) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/OrderGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/OrderGatewayImpl.kt deleted file mode 100644 index e8dd709..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/OrderGatewayImpl.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.OrderGateway -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import com.fiap.selfordermanagement.driver.database.persistence.jpa.OrderJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.mapper.OrderMapper -import org.mapstruct.factory.Mappers -import java.util.* - -class OrderGatewayImpl( - private val orderJpaRepository: OrderJpaRepository, -) : OrderGateway { - private val mapper = Mappers.getMapper(OrderMapper::class.java) - - override fun findAllActiveOrders(): List { - return orderJpaRepository - .findAllByStatusInOrderByStatusDescNumberAsc( - setOf( - OrderStatus.CONFIRMED, - OrderStatus.PREPARING, - OrderStatus.COMPLETED, - ), - ) - .map(mapper::toDomain) - } - - override fun findByOrderNumber(number: Long): Order? { - return orderJpaRepository.findById(number) - .map(mapper::toDomain) - .orElse(null) - } - - override fun findByStatus(status: OrderStatus): List { - return orderJpaRepository.findByStatus(status) - .map(mapper::toDomain) - } - - override fun findByCustomerId(customerId: UUID): List { - return orderJpaRepository.findByCustomerId(customerId) - .map(mapper::toDomain) - } - - override fun findByCustomerIdAndStatus( - customerId: UUID, - status: OrderStatus, - ): List { - return orderJpaRepository.findByCustomerIdAndStatus(customerId, status) - .map(mapper::toDomain) - } - - override fun upsert(order: Order): Order { - val currentOrder = order.number?.let { findByOrderNumber(number = order.number) } ?: order.copy(number = null) - val orderUpdated = - currentOrder - .copy( - date = order.date, - status = order.status, - customer = order.customer, - items = order.items, - total = order.total, - ) - return orderUpdated - .let(mapper::toEntity) - .let(orderJpaRepository::save) - .let(mapper::toDomain) - } - - override fun deleteAll() { - orderJpaRepository.deleteAll() - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/PaymentGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/PaymentGatewayImpl.kt deleted file mode 100644 index 3e4384b..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/PaymentGatewayImpl.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.PaymentGateway -import com.fiap.selfordermanagement.domain.entities.Payment -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.driver.database.persistence.jpa.PaymentJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.mapper.PaymentMapper -import org.mapstruct.factory.Mappers - -class PaymentGatewayImpl( - private val paymentJpaRepository: PaymentJpaRepository, -) : PaymentGateway { - private val mapper = Mappers.getMapper(PaymentMapper::class.java) - - override fun findByOrderNumber(orderNumber: Long): Payment? { - return paymentJpaRepository.findById(orderNumber) - .map(mapper::toDomain) - .orElse(null) - } - - override fun findAll(): List { - return paymentJpaRepository.findAll() - .map(mapper::toDomain) - } - - override fun create(payment: Payment): Payment { - payment.orderNumber.let { - findByOrderNumber(it)?.let { - throw SelfOrderManagementException( - errorType = ErrorType.PAYMENT_ALREADY_EXISTS, - message = "Payment record for order [${payment.orderNumber}] already exists", - ) - } - } - return persist(payment) - } - - override fun update(payment: Payment): Payment { - val newItem = - payment.orderNumber.let { findByOrderNumber(it)?.update(payment) } - ?: throw SelfOrderManagementException( - errorType = ErrorType.PAYMENT_NOT_FOUND, - message = "Payment record for order [${payment.orderNumber}] not found", - ) - return persist(newItem) - } - - private fun persist(payment: Payment): Payment = - payment - .let(mapper::toEntity) - .let(paymentJpaRepository::save) - .let(mapper::toDomain) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/ProductGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/ProductGatewayImpl.kt deleted file mode 100644 index 59282ff..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/ProductGatewayImpl.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import com.fiap.selfordermanagement.driver.database.persistence.jpa.ProductJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.mapper.ProductMapper -import org.mapstruct.factory.Mappers - -class ProductGatewayImpl( - private val productJpaRepository: ProductJpaRepository, -) : ProductGateway { - private val mapper: ProductMapper = Mappers.getMapper(ProductMapper::class.java) - - override fun findAll(): List { - return productJpaRepository.findAll() - .map(mapper::toDomain) - } - - override fun findByProductNumber(productNumber: Long): Product? { - return productJpaRepository.findById(productNumber) - .map { mapper.toDomain(it) } - .orElse(null) - } - - override fun findByCategory(category: ProductCategory): List { - return productJpaRepository.findByCategoryIgnoreCase(category.toString()) - .map { mapper.toDomain(it) } - } - - override fun searchByName(name: String): List { - return productJpaRepository.findByNameContainingIgnoreCase(name) - .map(mapper::toDomain) - } - - override fun create(product: Product): Product { - return persist(product.copy(number = null)) - } - - override fun update(product: Product): Product { - val number = - product.number ?: throw SelfOrderManagementException( - errorType = ErrorType.PRODUCT_NUMBER_IS_MANDATORY, - message = "Product ${product.name} not identified by number", - ) - val newItem = - findByProductNumber(number)?.update(product) - ?: throw SelfOrderManagementException( - errorType = ErrorType.PRODUCT_NOT_FOUND, - message = "Product [${product.number}] not found", - ) - return persist(newItem) - } - - override fun delete(productNumber: Long): Product { - return findByProductNumber(productNumber)?.let { - productJpaRepository.deleteById(productNumber) - it - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.PRODUCT_NOT_FOUND, - message = "Product [$productNumber] not found", - ) - } - - override fun deleteAll() { - productJpaRepository.deleteAll() - } - - private fun persist(product: Product): Product = - product - .let(mapper::toEntity) - .let(productJpaRepository::save) - .let(mapper::toDomain) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/StockGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/StockGatewayImpl.kt deleted file mode 100644 index 4d388dd..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/StockGatewayImpl.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.driver.database.persistence.jpa.StockJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.mapper.StockMapper -import org.mapstruct.factory.Mappers - -class StockGatewayImpl( - private val stockJpaRepository: StockJpaRepository, -) : StockGateway { - private val mapper = Mappers.getMapper(StockMapper::class.java) - - override fun findByComponentNumber(componentNumber: Long): Stock? { - return stockJpaRepository.findById(componentNumber) - .map(mapper::toDomain) - .orElse(null) - } - - override fun create(stock: Stock): Stock { - findByComponentNumber(stock.componentNumber)?.let { - throw SelfOrderManagementException( - errorType = ErrorType.STOCK_ALREADY_EXISTS, - message = "Stock record for component [${stock.componentNumber}] already exists", - ) - } - return persist(stock) - } - - override fun update(stock: Stock): Stock { - val newItem = - findByComponentNumber(stock.componentNumber) - ?.update(stock) - ?: throw SelfOrderManagementException( - errorType = ErrorType.STOCK_NOT_FOUND, - message = "Stock [${stock.componentNumber}] not found", - ) - return persist(newItem) - } - - private fun persist(stock: Stock): Stock = - stock - .let(mapper::toEntity) - .let(stockJpaRepository::save) - .let(mapper::toDomain) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/TransactionalGatewayImpl.kt b/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/TransactionalGatewayImpl.kt deleted file mode 100644 index de099c4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/adapter/gateway/impl/TransactionalGatewayImpl.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fiap.selfordermanagement.adapter.gateway.impl - -import com.fiap.selfordermanagement.adapter.gateway.TransactionalGateway -import org.springframework.transaction.annotation.Transactional - -open class TransactionalGatewayImpl : TransactionalGateway { - @Transactional - override fun transaction(code: () -> T): T { - return code() - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/client/MercadoPagoClient.kt b/src/main/kotlin/com/fiap/selfordermanagement/client/MercadoPagoClient.kt deleted file mode 100644 index c518099..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/client/MercadoPagoClient.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.fiap.selfordermanagement.client - -import com.fasterxml.jackson.annotation.JsonProperty -import org.springframework.beans.factory.annotation.Value -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpMethod -import org.springframework.http.MediaType -import org.springframework.http.ResponseEntity -import org.springframework.stereotype.Component -import org.springframework.web.client.RestTemplate -import java.math.BigDecimal - -@Component -@ConditionalOnProperty("payment-provider.mock", havingValue = "false") -class MercadoPagoClient( - private val restTemplate: RestTemplate, - @Value("\${mercadopago.api.url}") private val apiUrl: String, - @Value("\${mercadopago.api.token}") private val apiToken: String, - @Value("\${mercadopago.api.userId}") private val userId: String, - @Value("\${mercadopago.integration.posId}") private val posId: String, -) { - - fun submitMerchantOrder(request: MercadoPagoQRCodeOrderRequest): MercadoPagoQRCodeOrderResponse { - val headers = createHeaders() - val entity = HttpEntity(request, headers) - val url = "$apiUrl/instore/orders/qr/seller/collectors/$userId/pos/$posId/qrs" - val response = executeRequest(url, HttpMethod.POST, entity, MercadoPagoQRCodeOrderResponse::class.java) - return response.body ?: throw IllegalStateException("No response from Mercado Pago") - } - - fun fetchMerchantOrder(externalOrderGlobalId: String): MercadoPagoMerchantOrderResponse { - val headers = createHeaders() - val entity = HttpEntity(headers) - val url = "$apiUrl/merchant_orders/$externalOrderGlobalId" - val response = executeRequest(url, HttpMethod.GET, entity, MercadoPagoMerchantOrderResponse::class.java) - return response.body ?: throw IllegalStateException("No response from Mercado Pago") - } - - private fun createHeaders(): HttpHeaders { - val headers = HttpHeaders() - headers.contentType = MediaType.APPLICATION_JSON - headers.setBearerAuth(apiToken) - return headers - } - - private fun executeRequest( - url: String, - method: HttpMethod, - entity: HttpEntity, - responseType: Class, - ): ResponseEntity { - return try { - restTemplate.exchange(url, method, entity, responseType) - } catch (e: Exception) { - throw IllegalStateException("Error while communicating with Mercado Pago API: ${e.message}", e) - } - } -} - -data class MercadoPagoQRCodeOrderRequest( - val title: String, - val description: String, - @JsonProperty(value = "external_reference") val externalReference: String, - @JsonProperty(value = "notification_url") val notificationUrl: String, - @JsonProperty(value = "total_amount") val totalAmount: BigDecimal, - val items: List, -) - -data class MercadoPagoQRCodeOrderRequestItem( - val title: String, - @JsonProperty(value = "unit_price") val unitPrice: BigDecimal, - val quantity: Long, - @JsonProperty(value = "unit_measure") val unitMeasure: String, - @JsonProperty(value = "total_amount") val totalAmount: BigDecimal, -) - -data class MercadoPagoQRCodeOrderResponse( - @JsonProperty(value = "qr_data") val qrData: String, - @JsonProperty(value = "in_store_order_id") val inStoreOrderId: String, -) - -data class MercadoPagoMerchantOrderResponse( - val id: String, - @JsonProperty(value = "external_reference") val externalReference: String, - @JsonProperty(value = "order_status") val orderStatus: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/config/JWTSecurityConfig.kt b/src/main/kotlin/com/fiap/selfordermanagement/config/JWTSecurityConfig.kt deleted file mode 100644 index 4d642fd..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/config/JWTSecurityConfig.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.fiap.selfordermanagement.config - -import io.swagger.v3.oas.annotations.enums.SecuritySchemeType -import io.swagger.v3.oas.annotations.security.SecurityScheme -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.http.HttpMethod -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.core.authority.SimpleGrantedAuthority -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter -import org.springframework.security.web.SecurityFilterChain - -@Configuration -@EnableWebSecurity -@SecurityScheme( - name = "Bearer Authentication", - type = SecuritySchemeType.HTTP, - bearerFormat = "JWT", - scheme = "bearer" -) -class JWTSecurityConfig { - @Bean - fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { - http - .csrf { csrf -> - csrf.disable() - } - .authorizeHttpRequests { authorize -> - authorize.requestMatchers(HttpMethod.POST, "/orders").permitAll() - authorize.anyRequest().permitAll() - } - .oauth2ResourceServer { oauth2 -> - oauth2.jwt { jwt -> - jwt.jwtAuthenticationConverter(grantedAuthoritiesExtractor()) - } - } - - return http.build() - } - - private fun grantedAuthoritiesExtractor(): JwtAuthenticationConverter { - val jwtAuthenticationConverter = JwtAuthenticationConverter() - - jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter { jwt -> - val list: List = jwt.claims.getOrDefault("cognito:groups", emptyList()) as List - - return@setJwtGrantedAuthoritiesConverter list - .map { obj: Any -> obj.toString() } - .map { role -> SimpleGrantedAuthority(role) } - } - - return jwtAuthenticationConverter - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/config/RestTemplateConfig.kt b/src/main/kotlin/com/fiap/selfordermanagement/config/RestTemplateConfig.kt deleted file mode 100644 index d25e87b..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/config/RestTemplateConfig.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.fiap.selfordermanagement.config - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.client.RestTemplate - -@Configuration -class RestTemplateConfig { - @Bean - fun restTemplate(): RestTemplate { - return RestTemplate() - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Component.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Component.kt deleted file mode 100644 index a16125d..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Component.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -data class Component( - val number: Long? = null, - val name: String, -) { - fun update(newComponent: Component): Component = - copy( - name = newComponent.name, - ) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Customer.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Customer.kt deleted file mode 100644 index 3327b9c..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Customer.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -import java.util.* - -data class Customer( - val id: UUID, - val document: String?, - val name: String?, - val email: String?, - val phone: String?, - val address: String?, -) { - fun update(newCustomer: Customer): Customer = - copy( - document = newCustomer.document, - name = newCustomer.name, - email = newCustomer.email, - phone = newCustomer.phone, - address = newCustomer.address, - ) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Order.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Order.kt deleted file mode 100644 index 8ff187a..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Order.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import java.math.BigDecimal -import java.time.LocalDate - -data class Order( - val number: Long? = null, - val date: LocalDate = LocalDate.now(), - val customer: Customer? = null, - val status: OrderStatus = OrderStatus.CREATED, - val items: List, - val total: BigDecimal, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/OrderItem.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/OrderItem.kt deleted file mode 100644 index ce86372..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/OrderItem.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -data class OrderItem( - val productNumber: Long, - val quantity: Long, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Payment.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Payment.kt deleted file mode 100644 index b51f1c4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Payment.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import java.time.LocalDateTime - -data class Payment( - val orderNumber: Long, - val externalOrderId: String, - val externalOrderGlobalId: String?, - val paymentInfo: String, - val createdAt: LocalDateTime, - val status: PaymentStatus, - val statusChangedAt: LocalDateTime, -) { - fun update(newPayment: Payment): Payment = - copy( - orderNumber = newPayment.orderNumber, - externalOrderId = newPayment.externalOrderId, - externalOrderGlobalId = newPayment.externalOrderGlobalId, - paymentInfo = newPayment.paymentInfo, - createdAt = newPayment.createdAt, - status = newPayment.status, - statusChangedAt = newPayment.statusChangedAt, - ) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/PaymentRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/PaymentRequest.kt deleted file mode 100644 index f0f42fc..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/PaymentRequest.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -class PaymentRequest( - val externalOrderId: String, - val externalOrderGlobalId: String?, - val paymentInfo: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Product.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Product.kt deleted file mode 100644 index 1104ab4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Product.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import java.math.BigDecimal - -data class Product( - val number: Long? = null, - val name: String, - val price: BigDecimal, - val description: String, - val category: ProductCategory, - val minSub: Int, - val maxSub: Int, - val subItems: List, - val components: List, -) { - fun update(newProduct: Product): Product = - copy( - name = newProduct.name, - price = newProduct.price, - description = newProduct.description, - category = newProduct.category, - subItems = newProduct.subItems, - maxSub = newProduct.maxSub, - minSub = newProduct.minSub, - components = newProduct.components, - ) - - fun isLogicalItem() = components.isEmpty() -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Stock.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Stock.kt deleted file mode 100644 index dfb87a5..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/entities/Stock.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.fiap.selfordermanagement.domain.entities - -data class Stock( - val componentNumber: Long, - val quantity: Long, -) { - fun update(newStock: Stock): Stock = - copy( - quantity = newStock.quantity, - ) - - fun hasSufficientInventory(quantity: Long) = quantity >= this.quantity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/errors/ErrorType.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/errors/ErrorType.kt deleted file mode 100644 index 3d8d14b..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/errors/ErrorType.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.fiap.selfordermanagement.domain.errors - -enum class ErrorType { - CUSTOMER_NOT_FOUND, - PRODUCT_NOT_FOUND, - COMPONENT_NOT_FOUND, - STOCK_NOT_FOUND, - ORDER_NOT_FOUND, - PAYMENT_NOT_FOUND, - - PRODUCT_NUMBER_IS_MANDATORY, - COMPONENT_NUMBER_IS_MANDATORY, - - CUSTOMER_ALREADY_EXISTS, - PRODUCT_ALREADY_EXISTS, - STOCK_ALREADY_EXISTS, - PAYMENT_ALREADY_EXISTS, - - EMPTY_ORDER, - INSUFFICIENT_STOCK, - - INVALID_PRODUCT_CATEGORY, - INVALID_ORDER_STATUS, - INVALID_ORDER_STATE_TRANSITION, - - PAYMENT_NOT_CONFIRMED, - PAYMENT_REQUEST_NOT_ALLOWED, - - UNEXPECTED_ERROR, -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/errors/SelfOrderManagementException.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/errors/SelfOrderManagementException.kt deleted file mode 100644 index a5fbe09..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/errors/SelfOrderManagementException.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.fiap.selfordermanagement.domain.errors - -data class SelfOrderManagementException(var errorType: ErrorType, override val cause: Throwable? = null, override val message: String?) : - RuntimeException(message, cause) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/CPF.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/CPF.kt deleted file mode 100644 index af2865d..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/CPF.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.fiap.selfordermanagement.domain.valueobjects - -class CPF( - private val number: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/Email.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/Email.kt deleted file mode 100644 index 65b0d85..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/Email.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.fiap.selfordermanagement.domain.valueobjects - -class Email( - private val emailAddress: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/OrderStatus.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/OrderStatus.kt deleted file mode 100644 index 2c9d963..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/OrderStatus.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.fiap.selfordermanagement.domain.valueobjects - -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException - -enum class OrderStatus { - CREATED, - PENDING, - CONFIRMED, - PREPARING, - COMPLETED, - DONE, - CANCELLED, - ; - - companion object { - fun fromString(status: String): OrderStatus { - return values().firstOrNull { it.name.equals(status.trim(), ignoreCase = true) } - ?: throw SelfOrderManagementException( - errorType = ErrorType.INVALID_ORDER_STATUS, - message = "Status $status is not valid", - ) - } - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/PaymentStatus.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/PaymentStatus.kt deleted file mode 100644 index cbd5c0c..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/PaymentStatus.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.domain.valueobjects - -enum class PaymentStatus { - PENDING, - EXPIRED, - FAILED, - CONFIRMED, -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/Phone.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/Phone.kt deleted file mode 100644 index d021d57..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/Phone.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.fiap.selfordermanagement.domain.valueobjects - -class Phone( - private val number: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/ProductCategory.kt b/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/ProductCategory.kt deleted file mode 100644 index b376c25..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/domain/valueobjects/ProductCategory.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fiap.selfordermanagement.domain.valueobjects - -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException - -enum class ProductCategory { - DRINK, - MAIN, - SIDE, - DESSERT, - ; - - companion object { - fun fromString(category: String): ProductCategory { - return ProductCategory.values().firstOrNull { it.name.equals(category.trim(), ignoreCase = true) } - ?: throw SelfOrderManagementException( - errorType = ErrorType.INVALID_PRODUCT_CATEGORY, - message = "Product category $category is not valid", - ) - } - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/configuration/GatewayConfig.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/configuration/GatewayConfig.kt deleted file mode 100644 index 2a6d8d3..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/configuration/GatewayConfig.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.configuration - -import com.fiap.selfordermanagement.SelfOrderManagementApplication -import com.fiap.selfordermanagement.adapter.gateway.ComponentGateway -import com.fiap.selfordermanagement.adapter.gateway.CustomerGateway -import com.fiap.selfordermanagement.adapter.gateway.OrderGateway -import com.fiap.selfordermanagement.adapter.gateway.PaymentGateway -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.adapter.gateway.TransactionalGateway -import com.fiap.selfordermanagement.adapter.gateway.impl.ComponentGatewayImpl -import com.fiap.selfordermanagement.adapter.gateway.impl.CustomerGatewayImpl -import com.fiap.selfordermanagement.adapter.gateway.impl.OrderGatewayImpl -import com.fiap.selfordermanagement.adapter.gateway.impl.PaymentGatewayImpl -import com.fiap.selfordermanagement.adapter.gateway.impl.ProductGatewayImpl -import com.fiap.selfordermanagement.adapter.gateway.impl.StockGatewayImpl -import com.fiap.selfordermanagement.adapter.gateway.impl.TransactionalGatewayImpl -import com.fiap.selfordermanagement.driver.database.persistence.jpa.ComponentJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.jpa.CustomerJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.jpa.OrderJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.jpa.PaymentJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.jpa.ProductJpaRepository -import com.fiap.selfordermanagement.driver.database.persistence.jpa.StockJpaRepository -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration - -@Configuration -@ComponentScan(basePackageClasses = [SelfOrderManagementApplication::class]) -class GatewayConfig { - @Bean("CustomerGateway") - fun createCustomerGateway(customerJpaRepository: CustomerJpaRepository): CustomerGateway { - return CustomerGatewayImpl(customerJpaRepository) - } - - @Bean("ComponentGateway") - fun createComponentGateway(componentJpaRepository: ComponentJpaRepository): ComponentGateway { - return ComponentGatewayImpl(componentJpaRepository) - } - - @Bean("StockGateway") - fun createStockGateway(stockJpaRepository: StockJpaRepository): StockGateway { - return StockGatewayImpl(stockJpaRepository) - } - - @Bean("ProductGateway") - fun createProductGateway(productJpaRepository: ProductJpaRepository): ProductGateway { - return ProductGatewayImpl(productJpaRepository) - } - - @Bean("OrderGateway") - fun createOrderGateway(orderJpaRepository: OrderJpaRepository): OrderGateway { - return OrderGatewayImpl(orderJpaRepository) - } - - @Bean("PaymentGateway") - fun createPaymentGateway(paymentJpaRepository: PaymentJpaRepository): PaymentGateway { - return PaymentGatewayImpl(paymentJpaRepository) - } - - @Bean("TransactionalGateway") - fun createTransactionalGateway(): TransactionalGateway { - return TransactionalGatewayImpl() - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/configuration/PaymentGatewayConfig.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/configuration/PaymentGatewayConfig.kt deleted file mode 100644 index 9eaa4fd..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/configuration/PaymentGatewayConfig.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.configuration - -import com.fiap.selfordermanagement.SelfOrderManagementApplication -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.client.MercadoPagoClient -import com.fiap.selfordermanagement.driver.database.provider.MercadoPagoPaymentProvider -import com.fiap.selfordermanagement.driver.database.provider.PaymentProviderGatewayMock -import org.springframework.beans.factory.annotation.Value -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration - -@Configuration -@ComponentScan(basePackageClasses = [SelfOrderManagementApplication::class]) -class PaymentGatewayConfig { - @Bean("PaymentProvider") - @ConditionalOnProperty("payment-provider.mock", havingValue = "false") - fun createPaymentProvider( - mercadoPagoClient: MercadoPagoClient, - @Value("\${mercadopago.integration.webhookBaseUrl}") webhookBaseUrl: String, - ): PaymentProviderGateway { - return MercadoPagoPaymentProvider( - mercadoPagoClient, - webhookBaseUrl, - ) - } - - @Bean("PaymentProvider") - @ConditionalOnProperty("payment-provider.mock", havingValue = "true") - fun createPaymentProviderMock(): PaymentProviderGateway { - return PaymentProviderGatewayMock() - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/ComponentEntity.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/ComponentEntity.kt deleted file mode 100644 index 0f326fc..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/ComponentEntity.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.entities - -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.Table - -@Entity -@Table(name = "component") -class ComponentEntity( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "component_number") - val number: Long?, - @Column(name = "component_name") - val name: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/CustomerEntity.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/CustomerEntity.kt deleted file mode 100644 index 9fe4c7c..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/CustomerEntity.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.entities - -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Id -import jakarta.persistence.Table -import java.util.UUID - -@Entity -@Table(name = "customer") -class CustomerEntity( - @Id - @Column(name = "customer_id") - val id: String, - @Column(name = "customer_document") - val document: String?, - @Column(name = "customer_name") - val name: String?, - @Column(name = "customer_email") - val email: String?, - @Column(name = "customer_phone") - val phone: String?, - @Column(name = "customer_address") - val address: String?, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/OrderEntity.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/OrderEntity.kt deleted file mode 100644 index 0c93403..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/OrderEntity.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.entities - -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.EnumType -import jakarta.persistence.Enumerated -import jakarta.persistence.FetchType -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.JoinTable -import jakarta.persistence.ManyToMany -import jakarta.persistence.ManyToOne -import jakarta.persistence.Table -import java.math.BigDecimal -import java.time.LocalDate - -@Entity -@Table(name = "order") -class OrderEntity( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "order_number") - val number: Long, - @Column(name = "order_date") - val date: LocalDate, - @ManyToOne(fetch = FetchType.EAGER) - @JoinColumn(name = "order_customer_id") - val customer: CustomerEntity? = null, - @Enumerated(EnumType.STRING) - @Column(name = "order_status") - val status: OrderStatus, - @ManyToMany(fetch = FetchType.EAGER) - @JoinTable( - name = "order_item", - joinColumns = [JoinColumn(name = "order_item_order_number")], - inverseJoinColumns = [JoinColumn(name = "order_item_product_number")], - ) - val items: List, - @Column(name = "order_total") - val total: BigDecimal, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/PaymentEntity.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/PaymentEntity.kt deleted file mode 100644 index 81cabb8..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/PaymentEntity.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.entities - -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.EnumType -import jakarta.persistence.Enumerated -import jakarta.persistence.Id -import jakarta.persistence.Table -import java.time.LocalDateTime - -@Entity -@Table(name = "payment") -class PaymentEntity( - @Id - @Column(name = "payment_order_number") - val orderNumber: Long, - @Column(name = "payment_external_order_id") - val externalOrderId: String, - @Column(name = "payment_external_order_global_id") - val externalOrderGlobalId: String?, - @Column(name = "payment_payment_info") - val paymentInfo: String, - @Column(name = "payment_created_at") - val createdAt: LocalDateTime, - @Enumerated(EnumType.STRING) - @Column(name = "payment_status") - val status: PaymentStatus, - @Column(name = "payment_status_changed_at") - val statusChangedAt: LocalDateTime, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/ProductEntity.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/ProductEntity.kt deleted file mode 100644 index 01bf4e7..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/ProductEntity.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.entities - -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.JoinTable -import jakarta.persistence.ManyToMany -import jakarta.persistence.Table -import java.math.BigDecimal - -@Entity -@Table(name = "product") -class ProductEntity( - @Id - @Column(name = "product_number") - @GeneratedValue(strategy = GenerationType.IDENTITY) - val number: Long?, - @Column(name = "product_name") - val name: String, - @Column(name = "product_category") - val category: String, - @Column(name = "product_price") - val price: BigDecimal, - @Column(name = "product_description") - val description: String? = null, - @ManyToMany - @JoinTable( - name = "product_component", - joinColumns = [JoinColumn(name = "product_component_product_number")], - inverseJoinColumns = [JoinColumn(name = "product_component_component_number")], - ) - val components: List, - @ManyToMany - @JoinTable( - name = "product_sub_item", - joinColumns = [JoinColumn(name = "product_sub_item_product_id_sub")], - inverseJoinColumns = [JoinColumn(name = "product_sub_item_product_id_parent")], - ) - val subItems: List, - @Column(name = "product_min_sub_item") - val minSub: Int, - @Column(name = "product_max_sub_item") - val maxSub: Int, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/StockEntity.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/StockEntity.kt deleted file mode 100644 index 54f5235..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/entities/StockEntity.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.entities - -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.OneToOne -import jakarta.persistence.Table - -@Entity -@Table(name = "stock") -class StockEntity( - @Id - @Column(name = "stock_component_number") - val componentNumber: Long, - @Column(name = "stock_quantity") - val quantity: Long, - @OneToOne - @JoinColumn( - name = "stock_component_number", - referencedColumnName = "component_number", - insertable = false, - updatable = false, - ) - val component: ComponentEntity?, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/ComponentJpaRepository.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/ComponentJpaRepository.kt deleted file mode 100644 index ebb4ece..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/ComponentJpaRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.jpa - -import com.fiap.selfordermanagement.driver.database.persistence.entities.ComponentEntity -import org.springframework.data.repository.CrudRepository - -interface ComponentJpaRepository : CrudRepository { - fun findByNameContainingIgnoreCase(componentName: String): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/CustomerJpaRepository.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/CustomerJpaRepository.kt deleted file mode 100644 index 7e6f107..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/CustomerJpaRepository.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.jpa - -import com.fiap.selfordermanagement.driver.database.persistence.entities.CustomerEntity -import org.springframework.data.repository.CrudRepository -import java.util.* - -interface CustomerJpaRepository : CrudRepository { - fun findByEmail(email: String): Optional - - fun findByDocument(document: String): Optional - - fun findByNameContainingIgnoreCase(customerName: String): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/OrderJpaRepository.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/OrderJpaRepository.kt deleted file mode 100644 index d2865eb..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/OrderJpaRepository.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.jpa - -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import com.fiap.selfordermanagement.driver.database.persistence.entities.OrderEntity -import org.springframework.data.repository.CrudRepository -import java.util.* - -interface OrderJpaRepository : CrudRepository { - fun findByStatus(status: OrderStatus): List - - fun findByCustomerId(customerId: UUID): List - - fun findByCustomerIdAndStatus( - customerId: UUID, - status: OrderStatus, - ): List - - fun findAllByStatusInOrderByStatusDescNumberAsc(status: Set): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/PaymentJpaRepository.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/PaymentJpaRepository.kt deleted file mode 100644 index 5f39ce7..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/PaymentJpaRepository.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.jpa - -import com.fiap.selfordermanagement.driver.database.persistence.entities.PaymentEntity -import org.springframework.data.repository.CrudRepository - -interface PaymentJpaRepository : CrudRepository diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/ProductJpaRepository.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/ProductJpaRepository.kt deleted file mode 100644 index e00c4d2..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/ProductJpaRepository.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.jpa - -import com.fiap.selfordermanagement.driver.database.persistence.entities.ProductEntity -import org.springframework.data.repository.CrudRepository - -interface ProductJpaRepository : CrudRepository { - fun findByNameContainingIgnoreCase(productName: String): List - - fun findByCategoryIgnoreCase(category: String): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/StockJpaRepository.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/StockJpaRepository.kt deleted file mode 100644 index 8ca5773..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/jpa/StockJpaRepository.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.jpa - -import com.fiap.selfordermanagement.driver.database.persistence.entities.StockEntity -import org.springframework.data.repository.CrudRepository - -interface StockJpaRepository : CrudRepository diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/ComponentMapper.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/ComponentMapper.kt deleted file mode 100644 index 27b13f4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/ComponentMapper.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.mapper - -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.driver.database.persistence.entities.ComponentEntity -import org.mapstruct.Mapper - -@Mapper -interface ComponentMapper { - fun toDomain(entity: ComponentEntity): Component - - fun toEntity(domain: Component): ComponentEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/CustomerMapper.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/CustomerMapper.kt deleted file mode 100644 index 3f8929e..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/CustomerMapper.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.mapper - -import com.fiap.selfordermanagement.domain.entities.Customer -import com.fiap.selfordermanagement.driver.database.persistence.entities.CustomerEntity -import org.mapstruct.Mapper - -@Mapper -interface CustomerMapper { - fun toDomain(entity: CustomerEntity): Customer - - fun toEntity(domain: Customer): CustomerEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/OrderMapper.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/OrderMapper.kt deleted file mode 100644 index f64a225..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/OrderMapper.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.mapper - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.driver.database.persistence.entities.OrderEntity -import org.mapstruct.Mapper - -@Mapper -interface OrderMapper { - fun toDomain(entity: OrderEntity): Order - - fun toEntity(domain: Order): OrderEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/PaymentMapper.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/PaymentMapper.kt deleted file mode 100644 index 159947b..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/PaymentMapper.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.mapper - -import com.fiap.selfordermanagement.domain.entities.Payment -import com.fiap.selfordermanagement.driver.database.persistence.entities.PaymentEntity -import org.mapstruct.Mapper - -@Mapper -interface PaymentMapper { - fun toDomain(entity: PaymentEntity): Payment - - fun toEntity(domain: Payment): PaymentEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/ProductMapper.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/ProductMapper.kt deleted file mode 100644 index 04be721..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/ProductMapper.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.mapper - -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.driver.database.persistence.entities.ProductEntity -import org.mapstruct.Mapper -import org.mapstruct.Mapping -import org.mapstruct.NullValuePropertyMappingStrategy - -@Mapper -interface ProductMapper { - @Mapping( - source = "subItems", - target = "subItems", - nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT, - ) - fun toDomain(entity: ProductEntity): Product - - @Mapping( - source = "subItems", - target = "subItems", - nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_NULL, - ) - fun toEntity(domain: Product): ProductEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/StockMapper.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/StockMapper.kt deleted file mode 100644 index 9588365..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/persistence/mapper/StockMapper.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.persistence.mapper - -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.driver.database.persistence.entities.StockEntity -import org.mapstruct.Mapper - -@Mapper -interface StockMapper { - fun toDomain(entity: StockEntity): Stock - - fun toEntity(domain: Stock): StockEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/provider/MercadoPagoPaymentProvider.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/provider/MercadoPagoPaymentProvider.kt deleted file mode 100644 index 4c9867f..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/provider/MercadoPagoPaymentProvider.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.provider - -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.client.MercadoPagoClient -import com.fiap.selfordermanagement.client.MercadoPagoQRCodeOrderRequest -import com.fiap.selfordermanagement.client.MercadoPagoQRCodeOrderRequestItem -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.PaymentRequest -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus - -class MercadoPagoPaymentProvider( - private val mercadoPagoClient: MercadoPagoClient, - private val webhookBaseUrl: String, -) : PaymentProviderGateway { - - override fun createExternalOrder(order: Order): PaymentRequest { - // source_news=ipn indicates application will receive only Instant Payment Notifications (IPNs), not webhooks - val notificationUrl = "${webhookBaseUrl}/payments/notifications/${order.number}?source_news=ipn" - - val response = - mercadoPagoClient.submitMerchantOrder( - MercadoPagoQRCodeOrderRequest( - title = "Order ${order.number}", - description = "Ordered at ${order.date} by ${ order.customer?.name ?: order.customer?.document ?: "anonymous" }", - externalReference = order.number.toString(), - notificationUrl = notificationUrl, - totalAmount = order.total, - items = - order.items.map { product -> - MercadoPagoQRCodeOrderRequestItem( - title = product.name, - unitPrice = product.price, - quantity = 1, // TODO: fix to use order lines with persisted quantities per product - unitMeasure = MercadoPagoMeasureUnit.UNIT.measureUnit, - totalAmount = product.price, - ) - }, - ), - ) - - return PaymentRequest( - externalOrderId = response.inStoreOrderId, - externalOrderGlobalId = null, - paymentInfo = response.qrData, - ) - } - - override fun checkExternalOrderStatus(externalOrderGlobalId: String): PaymentStatus { - val response = mercadoPagoClient.fetchMerchantOrder(externalOrderGlobalId) - - return when (response.orderStatus) { - MercadoPagoOrderStatus.PAID.orderStatus -> { - PaymentStatus.CONFIRMED - } - MercadoPagoOrderStatus.EXPIRED.orderStatus -> { - PaymentStatus.EXPIRED - } - MercadoPagoOrderStatus.PAYMENT_IN_PROCESS.orderStatus, - MercadoPagoOrderStatus.PAYMENT_REQUIRED.orderStatus -> { - PaymentStatus.PENDING - } - else -> { - PaymentStatus.FAILED - } - } - } - - enum class MercadoPagoMeasureUnit(val measureUnit: String) { - UNIT("unit"), - } - - /** - * Not exhaustive list of order statuses. - */ - enum class MercadoPagoOrderStatus(val orderStatus: String) { - PAID("paid"), - EXPIRED("expired"), - PAYMENT_IN_PROCESS("payment_in_process"), - PAYMENT_REQUIRED("payment_required"), - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/provider/PaymentProviderGatewayMock.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/database/provider/PaymentProviderGatewayMock.kt deleted file mode 100644 index 8011ca4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/database/provider/PaymentProviderGatewayMock.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.fiap.selfordermanagement.driver.database.provider - -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.PaymentRequest -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import java.util.* - -class PaymentProviderGatewayMock: PaymentProviderGateway { - - override fun createExternalOrder(order: Order): PaymentRequest { - return PaymentRequest( - externalOrderId = UUID.randomUUID().toString(), - externalOrderGlobalId = null, - paymentInfo = "mocked" - ) - } - - override fun checkExternalOrderStatus(externalOrderGlobalId: String): PaymentStatus { - // always confirming - return PaymentStatus.CONFIRMED - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/ComponentAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/ComponentAPI.kt deleted file mode 100644 index 4cf9c8d..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/ComponentAPI.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.driver.web.request.ComponentRequest -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.enums.ParameterIn -import io.swagger.v3.oas.annotations.media.Schema -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.* - -@Tag(name = "composição", description = "API de componentes") -@RequestMapping("/admin/components") -interface ComponentAPI { - @Operation( - summary = "Retorna todos os componentes", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping - fun findAll(): ResponseEntity> - - @Operation( - summary = "Retorna componentes do produto", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Produto não encontrado"), - ], - ) - @GetMapping("/{productNumber}") - fun findByProductNumber( - @Parameter(description = "Número do produto") @PathVariable productNumber: Long, - ): ResponseEntity> - - @Operation( - summary = "Cadastra componente", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "422", description = "Quantidade inválida"), - ], - ) - @PostMapping - fun create( - @Parameter(description = "Cadastro de componente") @RequestBody componentRequest: ComponentRequest, - ): ResponseEntity - - @Operation( - summary = "Pesquisa componente por nome", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping("/search") - fun searchByName( - @Parameter(description = "Nome do componente") @RequestParam("name") name: String, - ): ResponseEntity> -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/CustomersAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/CustomersAPI.kt deleted file mode 100644 index 786d382..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/CustomersAPI.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.domain.entities.Customer -import com.fiap.selfordermanagement.driver.web.request.CustomerRequest -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.* - -@Tag(name = "cliente", description = "API de clientes") -@RequestMapping("/customers") -interface CustomersAPI { - @Operation(summary = "Retorna todos os clientes") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping - fun findAll(): ResponseEntity> - - @Operation(summary = "Retorna cliente pelo documento") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Cliente não encontrado"), - ], - ) - @GetMapping("/{customerId}") - fun getById( - @Parameter(description = "Identificador do cliente") @PathVariable("customerId") customerId: String, - ): ResponseEntity - - @Operation(summary = "Pesquisa clientes por nome") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping("/search") - fun searchByName( - @Parameter(description = "Nome do cliente") @RequestParam("name") name: String, - ): ResponseEntity> - - @Operation(summary = "Cadastra cliente") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "422", description = "Cadastro inválido"), - ], - ) - @PostMapping() - fun create( - @Parameter(description = "Cadastro de cliente") @RequestBody customerRequest: CustomerRequest, - ): ResponseEntity - - @Operation(summary = "Atualiza cadastro de cliente") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Cliente não encontrado"), - ], - ) - @PutMapping("/{customerId}") - fun update( - @Parameter(description = "Identificador do cliente") @PathVariable("customerId") customerId: String, - @Parameter(description = "Cadastro de cliente") @RequestBody customerRequest: CustomerRequest, - ): ResponseEntity - - @Operation(summary = "Remove cadastro de cliente") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Cliente não encontrado"), - ApiResponse(responseCode = "402", description = "Pagamento necessário"), - ], - ) - @DeleteMapping("/{customerId}") - fun remove( - @Parameter(description = "Identificador do cliente") @PathVariable("customerId") customerId: String, - ): ResponseEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/MenuAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/MenuAPI.kt deleted file mode 100644 index 5008cff..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/MenuAPI.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.domain.entities.Product -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag -import jakarta.websocket.server.PathParam -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.RequestMapping - -@Tag(name = "menu", description = "API de menu") -@RequestMapping("/menu") -interface MenuAPI { - @Operation(summary = "Retorna todos os produtos") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping - fun findAll(): ResponseEntity> - - @Operation(summary = "Retorna produtos por categoria") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "400", description = "Categoria inválida"), - ], - ) - @GetMapping("/category/{category}") - fun findByCategory( - @Parameter(description = "Categoria") @PathVariable category: String, - ): ResponseEntity> - - @Operation(summary = "Pesquisa produto por nome") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping("/search") - fun searchByName( - @Parameter(description = "Nome do produto") @PathParam("name") name: String, - ): ResponseEntity> -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/OrdersAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/OrdersAPI.kt deleted file mode 100644 index 57f4cf6..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/OrdersAPI.kt +++ /dev/null @@ -1,146 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.driver.web.request.OrderRequest -import com.fiap.selfordermanagement.driver.web.response.OrderToPayResponse -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.security.SecurityRequirement -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestParam - -@Tag(name = "pedido", description = "API de pedidos") -@RequestMapping("/orders") -interface OrdersAPI { - @Operation(summary = "Retorna todos os pedidos") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping - fun findAll(): ResponseEntity> - - @Operation(summary = "Retorna pedido pelo número") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Pedido não encontrado"), - ], - ) - @GetMapping("/{orderNumber}") - fun getByOrderNumber( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - ): ResponseEntity - - @Operation(summary = "Retorna pedidos por status") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "400", description = "Status inválido"), - ], - ) - @GetMapping("/status/{status}") - fun getByStatus( - @Parameter(description = "Status do pedido") @PathVariable status: String, - ): ResponseEntity> - - @Operation(summary = "Retorna pedidos de cliente por status") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "400", description = "Status inválido"), - ], - ) - @GetMapping("/status/{status}/customer") - fun getByStatusAndCustomerId( - @Parameter(description = "Status do pedido") @PathVariable status: String, - @Parameter(description = "Apelido do cliente") @RequestParam(required = false) customerId: String, - ): ResponseEntity> - - @Operation(summary = "Retorna pedidos de cliente") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping("customer") - fun getByCustomerId( - @Parameter(description = "Apelido do cliente") @RequestParam(required = false) customerId: String, - ): ResponseEntity> - - @Operation(summary = "Cria pedido") - @SecurityRequirement(name = "Bearer Authentication") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Produto não encontrado"), - ApiResponse(responseCode = "404", description = "Cliente não encontrado (quando informado documento)"), - ApiResponse(responseCode = "422", description = "Pedido sem itens"), - ], - ) - @PostMapping - fun create( - @Parameter(description = "Cadastro de pedido") @RequestBody orderRequest: OrderRequest, - ): ResponseEntity - - @Operation(summary = "Atualiza status de pedido em preparo") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Pedido não encontrado"), - ApiResponse(responseCode = "400", description = "Pedido não pode ser iniciado"), - ], - ) - @PostMapping("/{orderNumber}/start") - fun start( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - ): ResponseEntity - - @Operation(summary = "Atualiza status de pedido pronto") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Pedido não encontrado"), - ApiResponse(responseCode = "400", description = "Pedido não pode ser marcado como preparado"), - ], - ) - @PostMapping("/{orderNumber}/finish") - fun finish( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - ): ResponseEntity - - @Operation(summary = "Atualiza status de pedido para finalizado") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Pedido não encontrado"), - ApiResponse(responseCode = "400", description = "Pedido não pode ser finalizado"), - ], - ) - @PostMapping("/{orderNumber}/complete") - fun complete( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - ): ResponseEntity - - @Operation(summary = "Cancela pedido") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Pedido não encontrado"), - ApiResponse(responseCode = "400", description = "Pedido não pode ser cancelado"), - ], - ) - @PostMapping("/{orderNumber}/cancel") - fun cancel( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - ): ResponseEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/PaymentAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/PaymentAPI.kt deleted file mode 100644 index 4582825..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/PaymentAPI.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.domain.entities.Payment -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.enums.ParameterIn -import io.swagger.v3.oas.annotations.media.Schema -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestParam - -@Tag(name = "pagamento", description = "API de pagamentos") -@RequestMapping("/payments") -interface PaymentAPI { - @Operation(summary = "Retorna todos os pagamentos") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping - fun findAll(): ResponseEntity> - - @Operation(summary = "Retorna pagamento do pedido") - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Pedido não encontrado"), - ], - ) - @GetMapping("/{orderNumber}") - fun getByOrderNumber( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - ): ResponseEntity - - @Operation( - summary = "Notificações de pagamento", - parameters = [ - Parameter( - name = "x-signature", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema( - type = "string", - defaultValue = "ts=1704908010,v1=618c85345248dd820d5fd456117c2ab2ef8eda45a0282ff693eac24131a5e839" - ), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @PostMapping("/notifications/{orderNumber}") - fun notify( - @Parameter(description = "Número do pedido") @PathVariable orderNumber: Long, - @RequestParam(value = "id") resourceId: String, - @RequestParam topic: String, - ): ResponseEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/ProductAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/ProductAPI.kt deleted file mode 100644 index d26d4fa..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/ProductAPI.kt +++ /dev/null @@ -1,199 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.driver.web.request.ProductComposeRequest -import com.fiap.selfordermanagement.driver.web.request.ProductRequest -import com.fiap.selfordermanagement.driver.web.response.ProductResponse -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.enums.ParameterIn -import io.swagger.v3.oas.annotations.media.Schema -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag -import jakarta.websocket.server.PathParam -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.DeleteMapping -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.PutMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping - -@Tag(name = "produto", description = "API de produtos") -@RequestMapping("/admin/products") -interface ProductAPI { - @Operation( - summary = "Retorna todos os produtos", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping - fun findAll(): ResponseEntity> - - @Operation( - summary = "Retorna produtos por categoria", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "400", description = "Categoria inválida"), - ], - ) - @GetMapping("/category/{category}") - fun findByCategory( - @Parameter(description = "Categoria") @PathVariable category: String, - ): ResponseEntity> - - @Operation( - summary = "Retorna produto pelo número", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Produto não encontrado"), - ], - ) - @GetMapping("/{productNumber}") - fun getByProductNumber( - @Parameter(description = "Número do produto") @PathVariable("productNumber") productNumber: Long, - ): ResponseEntity - - @Operation( - summary = "Pesquisa produto por nome", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @GetMapping("/search") - fun searchByName( - @Parameter(description = "Nome do produto") @PathParam("name") name: String, - ): ResponseEntity> - - @Operation( - summary = "Cadastra produto", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "422", description = "Produto inválido"), - ], - ) - @PostMapping() - fun create( - @Parameter(description = "Cadastro do produto") @RequestBody productRequest: ProductRequest, - ): ResponseEntity - - @Operation( - summary = "Atualiza produto", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Produto não encontrado"), - ApiResponse(responseCode = "422", description = "Produto inválido"), - ], - ) - @PutMapping("/{productNumber}") - fun update( - @Parameter(description = "Número do produto") @PathVariable productNumber: Long, - @Parameter(description = "Cadastro do produto") @RequestBody productRequest: ProductRequest, - ): ResponseEntity - - @Operation( - summary = "Remove produto", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Produto não encontrado"), - ], - ) - @DeleteMapping("/{productNumber}") - fun delete( - @Parameter(description = "Número do produto") @PathVariable("productNumber") productNumber: Long, - ): ResponseEntity - - @Operation( - summary = "Atribui subitems ao produto", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Produto não encontrado"), - ], - ) - @PostMapping("/compose") - fun compose( - @Parameter(description = "Montagem do produto") @RequestBody productComposeRequest: ProductComposeRequest, - ): ResponseEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/StockAPI.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/StockAPI.kt deleted file mode 100644 index 2269d1b..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/StockAPI.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.fiap.selfordermanagement.driver.web - -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.driver.web.request.QuantityRequest -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter -import io.swagger.v3.oas.annotations.enums.ParameterIn -import io.swagger.v3.oas.annotations.media.Schema -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping - -@Tag(name = "estoque", description = "API de estoque de componentes") -@RequestMapping("/admin/stock") -interface StockAPI { - @Operation( - summary = "Acrescenta quantidade do componente em estoque", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Item de estoque não encontrado"), - ApiResponse(responseCode = "422", description = "Quantidade inválida"), - ], - ) - @PostMapping("/{componentNumber}/increment") - fun increment( - @Parameter(description = "Número do item em estoque") @PathVariable componentNumber: Long, - @Parameter(description = "Quantidade a acrescentar") @RequestBody quantityRequest: QuantityRequest, - ): ResponseEntity - - @Operation( - summary = "Reduz quantidade do componente em estoque", - parameters = [ - Parameter( - name = "x-admin-token", - required = true, - `in` = ParameterIn.HEADER, - schema = Schema(type = "string", defaultValue = "token"), - ), - ], - ) - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ApiResponse(responseCode = "404", description = "Item de estoque não encontrado"), - ApiResponse(responseCode = "422", description = "Quantidade inválida"), - ], - ) - @PostMapping("/{componentNumber}/decrement") - fun decrement( - @Parameter(description = "Número do componente") @PathVariable componentNumber: Long, - @Parameter(description = "Quantidade a reduzir") @RequestBody quantityRequest: QuantityRequest, - ): ResponseEntity -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ComponentRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ComponentRequest.kt deleted file mode 100644 index a8d61e0..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ComponentRequest.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import com.fiap.selfordermanagement.domain.entities.Component -import io.swagger.v3.oas.annotations.media.Schema - -data class ComponentRequest( - @Schema(title = "Nome do componente", example = "Hambúrguer", required = true) - val name: String, - @Schema(title = "Quantidade inicial", example = "100", required = true) - val initialQuantity: Long, -) { - fun toComponent(): Component { - return Component(name = name) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/CustomerRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/CustomerRequest.kt deleted file mode 100644 index 996f709..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/CustomerRequest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import com.fasterxml.jackson.annotation.JsonIgnore -import com.fiap.selfordermanagement.domain.entities.Customer -import io.swagger.v3.oas.annotations.media.Schema -import java.util.* - -data class CustomerRequest( - @Schema(title = "Documento", example = "444.555.666-77", required = false) - val document: String?, - @Schema(title = "Nome do cliente", example = "Fulano de Tal", required = false) - val name: String?, - @Schema(title = "E-mail", example = "fulano@email.com", required = false) - val email: String?, - @Schema(title = "Telefone", example = "+5511999999999", required = false) - val phone: String?, - @Schema(title = "Endereço", example = "Av. Paulista, 1106, 01310-100, São Paulo", required = false) - val address: String?, -) { - fun toDomain(): Customer { - return Customer( - id = UUID.randomUUID(), - document = document, - name = name, - email = email, - phone = phone, - address = address, - ) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/OrderItemRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/OrderItemRequest.kt deleted file mode 100644 index 186018f..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/OrderItemRequest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import io.swagger.v3.oas.annotations.media.Schema - -data class OrderItemRequest( - @Schema(title = "Número de produto", example = "1", required = true) - val productNumber: Long, - @Schema(title = "Quantidade", example = "1", required = true) - val quantity: Long, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/OrderRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/OrderRequest.kt deleted file mode 100644 index 08c9054..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/OrderRequest.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import com.fiap.selfordermanagement.domain.entities.OrderItem -import io.swagger.v3.oas.annotations.media.ArraySchema -import io.swagger.v3.oas.annotations.media.Schema - -data class OrderRequest( - @ArraySchema( - schema = Schema(implementation = OrderItemRequest::class, required = true), - minItems = 1, - ) - val items: List, -) { - fun toOrderItemDomain() = items.map { OrderItem(productNumber = it.productNumber, quantity = it.quantity) } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ProductComposeRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ProductComposeRequest.kt deleted file mode 100644 index 6fa85ed..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ProductComposeRequest.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import io.swagger.v3.oas.annotations.media.Schema - -data class ProductComposeRequest( - @Schema(title = "Número de produto", example = "1", required = true) - val productNumber: Long, - @Schema( - title = "Números dos produtos subitens", - type = "array", - example = "[\"1\", \"2\", \"3\"]", - required = true, - minLength = 1, - ) - val subItemsNumbers: List, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ProductRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ProductRequest.kt deleted file mode 100644 index 8b9aeb1..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/ProductRequest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import com.fasterxml.jackson.annotation.JsonFormat -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import io.swagger.v3.oas.annotations.media.Schema -import java.math.BigDecimal - -data class ProductRequest( - @Schema(title = "Nome do produto", example = "Big Mac", required = true) - val name: String, - @Schema( - title = "Categoria", - example = "MAIN", - allowableValues = ["DRINK", "MAIN", "SIDE", "DESSERT"], - required = true, - ) - val category: String, - @JsonFormat(shape = JsonFormat.Shape.STRING) - @Schema(title = "Preço", example = "10.00", required = true) - val price: BigDecimal, - @Schema( - title = "Descrição", - example = "Dois hambúrgueres, alface, queijo, molho especial, cebola, picles, num pão com gergelim", - required = true, - ) - val description: String, - @Schema(title = "Número mínimo de subitens", example = "1", minimum = "0", required = true) - val minSub: Int = 0, - @Schema(title = "Número máximo de subitens", example = "3", minimum = "0", required = true) - val maxSub: Int = Int.MAX_VALUE, - @Schema( - title = "Componentes do produto", - type = "array", - example = "[\"1\", \"2\", \"3\"]", - minLength = 1, - required = true, - ) - val components: List, -) { - fun toDomain(): Product { - return Product( - name = name, - category = ProductCategory.valueOf(category), - price = price, - description = description, - minSub = minSub, - maxSub = maxSub, - subItems = arrayListOf(), - components = arrayListOf(), - ) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/QuantityRequest.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/QuantityRequest.kt deleted file mode 100644 index beae243..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/request/QuantityRequest.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.request - -import io.swagger.v3.oas.annotations.media.Schema - -data class QuantityRequest( - @Schema(title = "Quantidade", example = "1", required = true) - val quantity: Long, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/response/OrderToPayResponse.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/response/OrderToPayResponse.kt deleted file mode 100644 index d08a300..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/response/OrderToPayResponse.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.response - -import com.fiap.selfordermanagement.domain.entities.Order - -data class OrderToPayResponse( - val order: Order, - val paymentInfo: String, -) diff --git a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/response/ProductResponse.kt b/src/main/kotlin/com/fiap/selfordermanagement/driver/web/response/ProductResponse.kt deleted file mode 100644 index df29b01..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/driver/web/response/ProductResponse.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.fiap.selfordermanagement.driver.web.response - -import com.fasterxml.jackson.annotation.JsonFormat -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.domain.entities.Product -import io.swagger.v3.oas.annotations.media.Schema -import java.math.BigDecimal - -data class ProductResponse( - @Schema(title = "Número", example = "1", required = true) - val number: Long, - @Schema(title = "Nome do produto", example = "Big Mac", required = true) - val name: String, - @Schema( - title = "Categoria", - example = "MAIN", - allowableValues = ["DRINK", "MAIN", "SIDE", "DESSERT"], - required = true, - ) - val category: String, - @JsonFormat(shape = JsonFormat.Shape.STRING) - @Schema(title = "Preço", example = "10.00", required = true) - val price: BigDecimal, - @Schema( - title = "Descrição", - example = "Dois hambúrgueres, alface, queijo, molho especial, cebola, picles, num pão com gergelim", - required = true, - ) - val description: String, - @Schema(title = "Número mínimo de subitens", example = "1", minimum = "0", required = true) - val minSub: Int = 0, - @Schema(title = "Número máximo de subitens", example = "3", minimum = "0", required = true) - val maxSub: Int = Int.MAX_VALUE, - @Schema(title = "Subitens", type = "array", minLength = 1, required = true) - val subItems: List, - @Schema(title = "Componentes", type = "array", minLength = 1, required = true) - val components: List, -) { - companion object { - fun fromDomain(product: Product): ProductResponse { - return ProductResponse( - number = product.number!!, - name = product.name, - category = product.category.toString(), - price = product.price, - description = product.description, - minSub = product.minSub, - maxSub = product.maxSub, - subItems = product.subItems, - components = product.components, - ) - } - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/AdjustStockUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/AdjustStockUseCase.kt deleted file mode 100644 index afd8cf2..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/AdjustStockUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Stock - -interface AdjustStockUseCase { - fun increment( - componentNumber: Long, - quantity: Long, - ): Stock - - fun decrement( - componentNumber: Long, - quantity: Long, - ): Stock -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/AssembleProductsUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/AssembleProductsUseCase.kt deleted file mode 100644 index ce0a1c4..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/AssembleProductsUseCase.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Product - -interface AssembleProductsUseCase { - fun compose( - productNumber: Long, - subItemsNumbers: List, - ): Product? - - fun create( - product: Product, - components: List, - ): Product - - fun update( - product: Product, - components: List, - ): Product - - fun delete(productNumber: Long): Product -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CancelOrderStatusUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/CancelOrderStatusUseCase.kt deleted file mode 100644 index a27197e..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CancelOrderStatusUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order - -interface CancelOrderStatusUseCase { - fun cancelOrder(orderNumber: Long): Order -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CompleteOrderUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/CompleteOrderUseCase.kt deleted file mode 100644 index ba7b467..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CompleteOrderUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order - -interface CompleteOrderUseCase { - fun completeOrder(orderNumber: Long): Order -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/ConfirmOrderUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/ConfirmOrderUseCase.kt deleted file mode 100644 index 3ca0bbc..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/ConfirmOrderUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order - -interface ConfirmOrderUseCase { - fun confirmOrder(orderNumber: Long): Order -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CreateComponentUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/CreateComponentUseCase.kt deleted file mode 100644 index 6a5c786..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CreateComponentUseCase.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Component - -interface CreateComponentUseCase { - fun create( - component: Component, - initialQuantity: Long, - ): Component -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CreateCustomerUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/CreateCustomerUseCase.kt deleted file mode 100644 index 5410109..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/CreateCustomerUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Customer - -interface CreateCustomerUseCase { - fun create(customer: Customer): Customer -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadComponentUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadComponentUseCase.kt deleted file mode 100644 index ef841d1..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadComponentUseCase.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Component - -interface LoadComponentUseCase { - fun getByComponentNumber(componentNumber: Long): Component - - fun findByProductNumber(productNumber: Long): List - - fun findAll(): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadCustomerUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadCustomerUseCase.kt deleted file mode 100644 index df28fd1..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadCustomerUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Customer -import java.util.* - -interface LoadCustomerUseCase { - fun getById(customerId: UUID): Customer - - fun findAll(): List - - fun findById(customerId: UUID): Customer? -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadOrderUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadOrderUseCase.kt deleted file mode 100644 index 6e4b43d..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadOrderUseCase.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import java.util.* - -interface LoadOrderUseCase { - fun getByOrderNumber(orderNumber: Long): Order - - fun findAll(): List - - fun findByStatus(status: OrderStatus): List - - fun findByCustomerId(customerId: UUID): List - - fun findByCustomerIdAndStatus( - customerId: UUID, - status: OrderStatus, - ): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadPaymentUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadPaymentUseCase.kt deleted file mode 100644 index 142d0d2..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadPaymentUseCase.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Payment - -interface LoadPaymentUseCase { - fun getByOrderNumber(orderNumber: Long): Payment - - fun findAll(): List - - fun findByOrderNumber(orderNumber: Long): Payment? -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadProductUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadProductUseCase.kt deleted file mode 100644 index 7166f71..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadProductUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory - -interface LoadProductUseCase { - fun getByProductNumber(productNumber: Long): Product - - fun findAll(): List - - fun findByCategory(category: ProductCategory): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadStockUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadStockUseCase.kt deleted file mode 100644 index 9f6a665..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/LoadStockUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Stock - -interface LoadStockUseCase { - fun getByComponentNumber(componentNumber: Long): Stock -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/PlaceOrderUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/PlaceOrderUseCase.kt deleted file mode 100644 index c90ba25..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/PlaceOrderUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.OrderItem -import java.util.* - -interface PlaceOrderUseCase { - fun create( - customerId: UUID?, - items: List, - ): Order -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/PrepareOrderUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/PrepareOrderUseCase.kt deleted file mode 100644 index d0a7df9..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/PrepareOrderUseCase.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order - -interface PrepareOrderUseCase { - fun startOrderPreparation(orderNumber: Long): Order - - fun finishOrderPreparation(orderNumber: Long): Order -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/ProvidePaymentRequestUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/ProvidePaymentRequestUseCase.kt deleted file mode 100644 index 95eded6..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/ProvidePaymentRequestUseCase.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.PaymentRequest - -interface ProvidePaymentRequestUseCase { - fun providePaymentRequest(order: Order): PaymentRequest -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/RemoveCustomerUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/RemoveCustomerUseCase.kt deleted file mode 100644 index d9d0638..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/RemoveCustomerUseCase.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Customer -import java.util.* - -interface RemoveCustomerUseCase { - fun remove(customerId: UUID): Customer -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/RemoveProductUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/RemoveProductUseCase.kt deleted file mode 100644 index e256551..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/RemoveProductUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Product - -interface RemoveProductUseCase { - fun delete(productNumber: Long): Product -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchComponentUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchComponentUseCase.kt deleted file mode 100644 index 72faabf..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchComponentUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Component - -interface SearchComponentUseCase { - fun searchByName(componentName: String): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchCustomerUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchCustomerUseCase.kt deleted file mode 100644 index 2f1e93d..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchCustomerUseCase.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Customer - -interface SearchCustomerUseCase { - fun searchByName(name: String): List - fun searchByEmail(email: String): Customer? -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchProductUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchProductUseCase.kt deleted file mode 100644 index 68495fd..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SearchProductUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Product - -interface SearchProductUseCase { - fun searchByName(productName: String): List -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SyncPaymentUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/SyncPaymentUseCase.kt deleted file mode 100644 index 9193b5d..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/SyncPaymentUseCase.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -interface SyncPaymentUseCase { - - fun syncPayment(orderNumber: Long, externalOrderGlobalId: String) -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/UpdateCustomerUseCase.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/UpdateCustomerUseCase.kt deleted file mode 100644 index 29f8d2b..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/UpdateCustomerUseCase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.fiap.selfordermanagement.usecases - -import com.fiap.selfordermanagement.domain.entities.Customer - -interface UpdateCustomerUseCase { - fun update(customer: Customer): Customer -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/ComponentService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/ComponentService.kt deleted file mode 100644 index 6d3b6be..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/ComponentService.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.fiap.selfordermanagement.usecases.services - -import com.fiap.selfordermanagement.adapter.gateway.ComponentGateway -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.usecases.CreateComponentUseCase -import com.fiap.selfordermanagement.usecases.LoadComponentUseCase -import com.fiap.selfordermanagement.usecases.SearchComponentUseCase - -class ComponentService( - private val componentRepository: ComponentGateway, - private val stockRepository: StockGateway, - private val productRepository: ProductGateway, -) : LoadComponentUseCase, - SearchComponentUseCase, - CreateComponentUseCase { - override fun getByComponentNumber(componentNumber: Long): Component { - return componentRepository.findByComponentNumber(componentNumber) - ?: throw SelfOrderManagementException( - errorType = ErrorType.COMPONENT_NOT_FOUND, - message = "Component [$componentNumber] not found", - ) - } - - override fun findByProductNumber(productNumber: Long): List { - return productRepository.findByProductNumber(productNumber) - ?.components - ?: throw SelfOrderManagementException( - errorType = ErrorType.PRODUCT_NOT_FOUND, - message = "Product [$productNumber] not found", - ) - } - - override fun searchByName(componentName: String): List { - return componentRepository.searchByName(componentName) - } - - override fun findAll(): List { - return componentRepository.findAll() - } - - override fun create( - component: Component, - initialQuantity: Long, - ): Component { - val savedComponent = componentRepository.create(component) - val stock = Stock(componentNumber = savedComponent.number!!, quantity = initialQuantity) - stockRepository.create(stock) - return savedComponent - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/CustomerService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/CustomerService.kt deleted file mode 100644 index 73e1b10..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/CustomerService.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.fiap.selfordermanagement.usecases.services - -import com.fiap.selfordermanagement.adapter.gateway.CustomerGateway -import com.fiap.selfordermanagement.domain.entities.Customer -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.usecases.* -import java.util.* - -class CustomerService( - private val repository: CustomerGateway, -) : LoadCustomerUseCase, - SearchCustomerUseCase, - CreateCustomerUseCase, - UpdateCustomerUseCase, - RemoveCustomerUseCase { - override fun getById(customerId: UUID): Customer { - return repository.findById(customerId) - ?: throw SelfOrderManagementException( - errorType = ErrorType.CUSTOMER_NOT_FOUND, - message = "Customer [$customerId] not found", - ) - } - - override fun findAll(): List { - return repository.findAll() - } - - override fun findById(customerId: UUID): Customer? { - return repository.findById(customerId) - } - - override fun searchByName(name: String): List { - return repository.searchByName(name.trim()) - } - - override fun searchByEmail(email: String): Customer? { - return repository.searchByEmail(email.trim()) - } - - override fun create(customer: Customer): Customer { - return repository.create(customer.copy(id = UUID.randomUUID())) - } - - override fun update(customer: Customer): Customer { - return repository.update(customer) - } - - override fun remove(customerId: UUID): Customer { - return repository.deleteById(customerId) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/OrderService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/OrderService.kt deleted file mode 100644 index d2ddaff..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/OrderService.kt +++ /dev/null @@ -1,186 +0,0 @@ -package services - -import com.fiap.selfordermanagement.adapter.gateway.OrderGateway -import com.fiap.selfordermanagement.adapter.gateway.TransactionalGateway -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.OrderItem -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import com.fiap.selfordermanagement.usecases.AdjustStockUseCase -import com.fiap.selfordermanagement.usecases.CancelOrderStatusUseCase -import com.fiap.selfordermanagement.usecases.CompleteOrderUseCase -import com.fiap.selfordermanagement.usecases.ConfirmOrderUseCase -import com.fiap.selfordermanagement.usecases.LoadCustomerUseCase -import com.fiap.selfordermanagement.usecases.LoadOrderUseCase -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import com.fiap.selfordermanagement.usecases.LoadProductUseCase -import com.fiap.selfordermanagement.usecases.PlaceOrderUseCase -import com.fiap.selfordermanagement.usecases.PrepareOrderUseCase -import com.fiap.selfordermanagement.usecases.ProvidePaymentRequestUseCase -import java.time.LocalDate -import java.util.* - -open class OrderService( - private val orderRepository: OrderGateway, - private val getCustomersUseCase: LoadCustomerUseCase, - private val getProductUseCase: LoadProductUseCase, - private val adjustInventoryUseCase: AdjustStockUseCase, - private val providePaymentRequestUseCase: ProvidePaymentRequestUseCase, - private val loadPaymentUseCase: LoadPaymentUseCase, - private val transactionalRepository: TransactionalGateway, -) : LoadOrderUseCase, - PlaceOrderUseCase, - ConfirmOrderUseCase, - PrepareOrderUseCase, - CompleteOrderUseCase, - CancelOrderStatusUseCase { - override fun getByOrderNumber(orderNumber: Long): Order { - return orderRepository.findByOrderNumber(orderNumber) - ?: throw SelfOrderManagementException( - errorType = ErrorType.ORDER_NOT_FOUND, - message = "Order [$orderNumber] not found", - ) - } - - override fun findAll(): List { - return orderRepository.findAllActiveOrders() - } - - override fun findByStatus(status: OrderStatus): List { - return orderRepository.findByStatus(status) - } - - override fun findByCustomerId(customerId: UUID): List { - return orderRepository.findByCustomerId(customerId) - } - - override fun findByCustomerIdAndStatus(customerId: UUID, status: OrderStatus): List { - return orderRepository.findByCustomerIdAndStatus(customerId, status) - } - - override fun create( - customerId: UUID?, - items: List, - ): Order { - return transactionalRepository.transaction { - if (items.isEmpty()) { - throw SelfOrderManagementException( - errorType = ErrorType.EMPTY_ORDER, - message = "Empty order", - ) - } - - val products = - items.flatMap { - val product = getProductUseCase.getByProductNumber(it.productNumber) - if (!product.isLogicalItem()) { - product.components.mapNotNull { p -> p.number }.forEach { componentNumber -> - adjustInventoryUseCase.decrement(componentNumber, it.quantity) - } - } - MutableList(it.quantity.toInt()) { product } - } - - val order = orderRepository.upsert( - Order( - number = null, - date = LocalDate.now(), - customer = customerId?.let { getCustomersUseCase.findById(customerId) }, - status = OrderStatus.CREATED, - items = products, - total = products.sumOf { it.price }, - ) - ) - - providePaymentRequestUseCase.providePaymentRequest(order) - - orderRepository.upsert(order.copy(status = OrderStatus.PENDING)) - } - } - - override fun confirmOrder(orderNumber: Long): Order { - return transactionalRepository.transaction { - val order = getByOrderNumber(orderNumber) - - val payment = loadPaymentUseCase.getByOrderNumber(orderNumber) - - if (payment.status != PaymentStatus.CONFIRMED) { - orderRepository.upsert(order.copy(status = OrderStatus.PENDING)) - throw SelfOrderManagementException( - errorType = ErrorType.PAYMENT_NOT_CONFIRMED, - message = "Last payment not confirmed for order $orderNumber", - ) - } - - when (order.status) { - OrderStatus.PENDING -> { - orderRepository.upsert(order.copy(status = OrderStatus.CONFIRMED)) - } - else -> { - throw SelfOrderManagementException( - errorType = ErrorType.INVALID_ORDER_STATE_TRANSITION, - message = "Confirmation is only allowed for orders that are in a pending state", - ) - } - } - } - } - - override fun startOrderPreparation(orderNumber: Long): Order { - return getByOrderNumber(orderNumber) - .takeIf { it.status == OrderStatus.CONFIRMED } - ?.run { - orderRepository.upsert(copy(status = OrderStatus.PREPARING)) - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.INVALID_ORDER_STATE_TRANSITION, - message = "Preparation of the order cannot begin until it has been confirmed", - ) - } - - override fun completeOrder(orderNumber: Long): Order { - return getByOrderNumber(orderNumber) - .takeIf { it.status == OrderStatus.PREPARING } - ?.run { - orderRepository.upsert(copy(status = OrderStatus.COMPLETED)) - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.INVALID_ORDER_STATE_TRANSITION, - message = "Order cannot be completed until it has been prepared", - ) - } - - override fun finishOrderPreparation(orderNumber: Long): Order { - return getByOrderNumber(orderNumber) - .takeIf { it.status == OrderStatus.COMPLETED } - ?.run { - orderRepository.upsert(copy(status = OrderStatus.DONE)) - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.INVALID_ORDER_STATE_TRANSITION, - message = "Order cannot be finished until it has been completed (delivered)", - ) - } - - override fun cancelOrder(orderNumber: Long): Order { - return transactionalRepository.transaction { - getByOrderNumber(orderNumber) - .takeIf { it.status != OrderStatus.COMPLETED && it.status != OrderStatus.DONE } - ?.run { - if (status == OrderStatus.CREATED || status == OrderStatus.CONFIRMED) { - // in this case, make reserved products available again - items.forEach { - it.number?.let { number -> adjustInventoryUseCase.increment(number, 1) } - } - } - orderRepository.upsert(copy(status = OrderStatus.CANCELLED)) - } - ?: throw SelfOrderManagementException( - errorType = ErrorType.INVALID_ORDER_STATE_TRANSITION, - message = "This order has already been marked as completed", - ) - } - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/PaymentService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/PaymentService.kt deleted file mode 100644 index 2dab3a1..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/PaymentService.kt +++ /dev/null @@ -1,54 +0,0 @@ -package services - -import com.fiap.selfordermanagement.adapter.gateway.PaymentGateway -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.Payment -import com.fiap.selfordermanagement.domain.entities.PaymentRequest -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import com.fiap.selfordermanagement.usecases.ProvidePaymentRequestUseCase -import java.time.LocalDateTime - -class PaymentService( - private val paymentRepository: PaymentGateway, - private val paymentProvider: PaymentProviderGateway, -) : - LoadPaymentUseCase, - ProvidePaymentRequestUseCase { - override fun getByOrderNumber(orderNumber: Long): Payment { - return paymentRepository.findByOrderNumber(orderNumber) - ?: throw SelfOrderManagementException( - errorType = ErrorType.PAYMENT_NOT_FOUND, - message = "Payment not found for order [$orderNumber]", - ) - } - - override fun findByOrderNumber(orderNumber: Long): Payment? { - return paymentRepository.findByOrderNumber(orderNumber) - } - - override fun findAll(): List { - return paymentRepository.findAll() - } - - override fun providePaymentRequest(order: Order): PaymentRequest { - val paymentRequest = paymentProvider.createExternalOrder(order) - val payment = - Payment( - orderNumber = order.number!!, - externalOrderId = paymentRequest.externalOrderId, - externalOrderGlobalId = null, - paymentInfo = paymentRequest.paymentInfo, - createdAt = LocalDateTime.now(), - status = PaymentStatus.PENDING, - statusChangedAt = LocalDateTime.now(), - ) - - paymentRepository.create(payment) - - return paymentRequest - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/PaymentSyncService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/PaymentSyncService.kt deleted file mode 100644 index 867cf34..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/PaymentSyncService.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.fiap.selfordermanagement.usecases.services - -import com.fiap.selfordermanagement.adapter.gateway.PaymentGateway -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import com.fiap.selfordermanagement.usecases.ConfirmOrderUseCase -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import com.fiap.selfordermanagement.usecases.SyncPaymentUseCase -import java.time.LocalDateTime - -class PaymentSyncService( - private val confirmOrderUseCase: ConfirmOrderUseCase, - private val loadPaymentUseCase: LoadPaymentUseCase, - private val paymentGateway: PaymentGateway, - private val paymentProviderGateway: PaymentProviderGateway, -): SyncPaymentUseCase { - - override fun syncPayment(orderNumber: Long, externalOrderGlobalId: String) { - val payment = loadPaymentUseCase.getByOrderNumber(orderNumber) - - if (payment.externalOrderGlobalId == null) { - paymentGateway.update(payment.copy(externalOrderGlobalId = externalOrderGlobalId)) - } - - val newStatus = paymentProviderGateway.checkExternalOrderStatus(externalOrderGlobalId) - - if (payment.status != newStatus) { - paymentGateway.update( - payment.copy( - status = newStatus, - statusChangedAt = LocalDateTime.now(), - ) - ) - - if (newStatus == PaymentStatus.CONFIRMED) { - confirmOrderUseCase.confirmOrder(orderNumber) - } - } - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/ProductService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/ProductService.kt deleted file mode 100644 index 864688a..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/ProductService.kt +++ /dev/null @@ -1,67 +0,0 @@ -package services - -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import com.fiap.selfordermanagement.usecases.* - -class ProductService( - private val productRepository: ProductGateway, - private val loadComponentUseCase: LoadComponentUseCase, -) : - LoadProductUseCase, - SearchProductUseCase, - AssembleProductsUseCase, - RemoveProductUseCase { - override fun getByProductNumber(productNumber: Long): Product { - return productRepository.findByProductNumber(productNumber) - ?: throw SelfOrderManagementException( - errorType = ErrorType.PRODUCT_NOT_FOUND, - message = "Product [$productNumber] not found", - ) - } - - override fun findAll(): List { - return productRepository.findAll() - } - - override fun findByCategory(category: ProductCategory): List { - return productRepository.findByCategory(category) - } - - override fun searchByName(productName: String): List { - return productRepository.searchByName(productName.trim()) - } - - override fun create( - product: Product, - components: List, - ): Product { - val newProduct = product.copy(components = components.map(loadComponentUseCase::getByComponentNumber)) - return productRepository.create(newProduct) - } - - override fun update( - product: Product, - components: List, - ): Product { - val newProduct = product.copy(components = components.map(loadComponentUseCase::getByComponentNumber)) - return productRepository.update(newProduct) - } - - override fun delete(productNumber: Long): Product { - return productRepository.delete(productNumber) - } - - override fun compose( - productNumber: Long, - subItemsNumbers: List, - ): Product { - val product = getByProductNumber(productNumber) - val subItems = subItemsNumbers.map(::getByProductNumber) - val newProduct = product.copy(subItems = subItems) - return productRepository.update(newProduct) - } -} diff --git a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/StockService.kt b/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/StockService.kt deleted file mode 100644 index 4ddb04f..0000000 --- a/src/main/kotlin/com/fiap/selfordermanagement/usecases/services/StockService.kt +++ /dev/null @@ -1,43 +0,0 @@ -package services - -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.usecases.AdjustStockUseCase -import com.fiap.selfordermanagement.usecases.LoadStockUseCase - -class StockService( - private val stockRepository: StockGateway, -) : LoadStockUseCase, - AdjustStockUseCase { - override fun getByComponentNumber(componentNumber: Long): Stock { - return stockRepository.findByComponentNumber(componentNumber) - ?: throw SelfOrderManagementException( - errorType = ErrorType.STOCK_NOT_FOUND, - message = "Stock not found for component [$componentNumber]", - ) - } - - override fun increment( - componentNumber: Long, - quantity: Long, - ): Stock { - val stock = getByComponentNumber(componentNumber) - return stockRepository.update(stock.copy(quantity = stock.quantity + quantity)) - } - - override fun decrement( - componentNumber: Long, - quantity: Long, - ): Stock { - val stock = getByComponentNumber(componentNumber) - if (stock.hasSufficientInventory(quantity)) { - throw SelfOrderManagementException( - errorType = ErrorType.INSUFFICIENT_STOCK, - message = "Insufficient stock for component $componentNumber", - ) - } - return stockRepository.update(stock.copy(quantity = stock.quantity - quantity)) - } -} diff --git a/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/src/main/resources/META-INF/additional-spring-configuration-metadata.json deleted file mode 100644 index b3a87de..0000000 --- a/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "properties": [ - { - "name": "admin.access-token", - "type": "java.lang.String", - "description": "Description for admin-access-token." - }, - { - "name": "payment-provider.mock", - "type": "java.lang.String", - "description": "Description for payment-provider.mock." - }, - { - "name": "mercadopago.api.url", - "type": "java.lang.String", - "description": "Description for mercadopago.api.url." - }, - { - "name": "mercadopago.api.token", - "type": "java.lang.String", - "description": "Description for mercadopago.api.token." - }, - { - "name": "mercadopago.api.userId", - "type": "java.lang.String", - "description": "Description for mercadopago.api.userId." - }, - { - "name": "mercadopago.integration.posId", - "type": "java.lang.String", - "description": "Description for mercadopago.integration.posId." - }, - { - "name": "mercadopago.integration.webhookBaseUrl", - "type": "java.lang.String", - "description": "Description for mercadopago.integration.webhookBaseUrl." - } - ] -} diff --git a/src/main/resources/application-openapi.yml b/src/main/resources/application-openapi.yml deleted file mode 100644 index a9d944e..0000000 --- a/src/main/resources/application-openapi.yml +++ /dev/null @@ -1,15 +0,0 @@ -spring: - datasource: - url: jdbc:h2:mem:db - username: master - password: - driver-class-name: org.h2.Driver - flyway: - enabled: false - jpa: - properties: - hibernate: - dialect: org.hibernate.dialect.H2Dialect - -payment-provider: - mock: true diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml deleted file mode 100644 index 89b6211..0000000 --- a/src/main/resources/application-test.yml +++ /dev/null @@ -1,5 +0,0 @@ -admin: - access-token: token - -payment-provider: - mock: true diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index 9fa5fa7..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,40 +0,0 @@ -spring: - application: - name: self-order-management - datasource: - url: jdbc:postgresql://${DB_ENDPOINT}/${DB_NAME} - username: ${DB_USERNAME} - password: ${DB_PASSWORD} - flyway: - baseline-on-migrate: true - jpa: - properties: - hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect - enable_lazy_load_no_trans: true - jdbc: - lob: - non_contextual_creation: true - ddl-auto: validate - globally_quoted_identifiers: true - security: - oauth2: - resourceserver: - jwt: - issuer-uri: https://cognito-idp.us-east-1.amazonaws.com/us-east-1_ygM5FRn7D - jwk-set-uri: https://cognito-idp.us-east-1.amazonaws.com/us-east-1_ygM5FRn7D/.well-known/jwks.json - -admin: - access-token: ${ADMIN_ACCESS_TOKEN} - -payment-provider: - mock: ${MOCK_PAYMENT_PROVIDER} - -mercadopago: - api: - url: https://api.mercadopago.com - token: ${MP_TOKEN} - userId: ${MP_USER_ID} - integration: - posId: ${MP_POS_ID} - webhookBaseUrl: ${MP_WEBHOOK_BASE_URL} diff --git a/src/main/resources/db/migration/V1__initial_schema.sql b/src/main/resources/db/migration/V1__initial_schema.sql deleted file mode 100644 index e0a1650..0000000 --- a/src/main/resources/db/migration/V1__initial_schema.sql +++ /dev/null @@ -1,80 +0,0 @@ -CREATE TABLE IF NOT EXISTS product -( - product_number SERIAL NOT NULL PRIMARY KEY, - product_name VARCHAR(255) NOT NULL, - product_category VARCHAR(255) NOT NULL, - product_price NUMERIC(15,2) NOT NULL, - product_description VARCHAR(255), - product_min_sub_item INTEGER NOT NULL, - product_max_sub_item INTEGER NOT NULL -); - -CREATE TABLE IF NOT EXISTS component ( - component_number SERIAL NOT NULL PRIMARY KEY, - component_name VARCHAR(2000) NOT NULL -); - -CREATE TABLE IF NOT EXISTS product_component ( - product_component_product_number SERIAL NOT NULL, - product_component_component_number SERIAL NOT NULL, - CONSTRAINT pk_product_component PRIMARY KEY(product_component_product_number, product_component_component_number), - CONSTRAINT fk_product_component_product_number FOREIGN KEY(product_component_product_number) REFERENCES product(product_number) ON DELETE CASCADE, - CONSTRAINT fk_product_component_component_number FOREIGN KEY(product_component_component_number) REFERENCES component(component_number) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS stock -( - stock_component_number SERIAL NOT NULL PRIMARY KEY, - stock_quantity BIGINT NOT NULL, - CONSTRAINT fk_stock_component_number FOREIGN KEY(stock_component_number) REFERENCES component(component_number) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS product_sub_item -( - product_sub_item_id SERIAL PRIMARY KEY, - product_sub_item_product_id_parent INTEGER NOT NULL, - product_sub_item_product_id_sub INTEGER NOT NULL, - CONSTRAINT fk_product_sub_item_product_id_parent FOREIGN KEY(product_sub_item_product_id_parent) REFERENCES product(product_number), - CONSTRAINT fk_product_sub_item_product_id_sub FOREIGN KEY(product_sub_item_product_id_sub) REFERENCES product(product_number) -); - -CREATE TABLE IF NOT EXISTS customer -( - customer_id VARCHAR(36) PRIMARY KEY, - customer_document VARCHAR(20), - customer_name VARCHAR(255), - customer_email VARCHAR(255), - customer_phone VARCHAR(255), - customer_address VARCHAR(1000) -); - -CREATE TABLE IF NOT EXISTS "order" -( - order_number SERIAL PRIMARY KEY, - order_date DATE NOT NULL, - order_customer_id CHAR(36), - order_status TEXT NOT NULL, - order_total NUMERIC(15,2) NOT NULL, - CONSTRAINT fk_order_customer_id FOREIGN KEY(order_customer_id) REFERENCES customer(customer_id) -); - -CREATE TABLE IF NOT EXISTS order_item -( - order_item_id SERIAL PRIMARY KEY, - order_item_product_number INTEGER NOT NULL, - order_item_order_number SERIAL NOT NULL, - CONSTRAINT fk_order_item_product_id FOREIGN KEY(order_item_product_number) REFERENCES product(product_number), - CONSTRAINT fk_order_item_order_id FOREIGN KEY(order_item_order_number) REFERENCES "order"(order_number) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS payment -( - payment_order_number SERIAL PRIMARY KEY, - payment_external_order_id TEXT NOT NULL, - payment_external_order_global_id TEXT, - payment_payment_info TEXT NOT NULL, - payment_created_at TIMESTAMP NOT NULL, - payment_status TEXT NOT NULL, - payment_status_changed_at TIMESTAMP NOT NULL, - CONSTRAINT fk_payment_order_id FOREIGN KEY(payment_order_number) REFERENCES "order"(order_number) -); diff --git a/src/test/kotlin/IntegrationTestFixtures.kt b/src/test/kotlin/IntegrationTestFixtures.kt deleted file mode 100644 index 5dc8da6..0000000 --- a/src/test/kotlin/IntegrationTestFixtures.kt +++ /dev/null @@ -1,52 +0,0 @@ -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import com.fiap.selfordermanagement.driver.web.request.ComponentRequest -import com.fiap.selfordermanagement.driver.web.request.CustomerRequest -import com.fiap.selfordermanagement.driver.web.request.ProductRequest -import java.math.BigDecimal -import java.util.* - -fun createCustomerRequest( - document: String = "444.555.666-77", - name: String = "Fulano de Tal", - email: String = "fulano@detal.com", - phone: String = "5511999999999", - address: String = "São Paulo", -) = CustomerRequest( - document = document, - name = name, - email = email, - phone = phone, - address = address, -) - -fun createProductRequest( - name: String = "Big Mac", - category: String = ProductCategory.MAIN.name, - price: BigDecimal = BigDecimal("10.00"), - description: String = "Dois hambúrgueres, alface, queijo, molho especial, cebola, picles, num pão com gergelim", - minSub: Int = 3, - maxSub: Int = 3, - components: List = listOf(1, 2, 3, 4, 5, 6, 7), -): ProductRequest { - return ProductRequest( - name = name, - category = category, - price = price, - description = description, - minSub = minSub, - maxSub = maxSub, - components = components, - ) -} - -fun createNewInputRequests(): List { - return listOf( - ComponentRequest("Hambúrguer", 100), - ComponentRequest("Alface", 100), - ComponentRequest("Queijo", 100), - ComponentRequest("Molho especial", 100), - ComponentRequest("Cebola", 100), - ComponentRequest("Picles", 100), - ComponentRequest("Pão com gergelim", 100), - ) -} diff --git a/src/test/kotlin/PostgreSQLContainerInitializer.kt b/src/test/kotlin/PostgreSQLContainerInitializer.kt deleted file mode 100644 index b9eee55..0000000 --- a/src/test/kotlin/PostgreSQLContainerInitializer.kt +++ /dev/null @@ -1,27 +0,0 @@ -import org.springframework.boot.test.util.TestPropertyValues -import org.springframework.context.ApplicationContextInitializer -import org.springframework.context.ConfigurableApplicationContext -import org.testcontainers.containers.PostgreSQLContainer -import org.testcontainers.containers.wait.strategy.Wait.forListeningPort - -class PostgreSQLContainerInitializer : - ApplicationContextInitializer, - PostgreSQLContainer("postgres:15.4") { - companion object { - private val instance: PostgreSQLContainerInitializer = - PostgreSQLContainerInitializer() - .withDatabaseName("selforder") - .withUsername("selforder") - .withPassword("self@Order123!") - .waitingFor(forListeningPort()) - } - - override fun initialize(configurableApplicationContext: ConfigurableApplicationContext) { - instance.start() - TestPropertyValues.of( - "spring.datasource.url=${instance.jdbcUrl}", - "spring.datasource.username=${instance.username}", - "spring.datasource.password=${instance.password}", - ).applyTo(configurableApplicationContext) - } -} diff --git a/src/test/kotlin/TestAnnotations.kt b/src/test/kotlin/TestAnnotations.kt deleted file mode 100644 index 3f44809..0000000 --- a/src/test/kotlin/TestAnnotations.kt +++ /dev/null @@ -1,14 +0,0 @@ -import org.junit.jupiter.api.Tag -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase -import org.springframework.test.context.ActiveProfiles -import org.springframework.test.context.ContextConfiguration - -@Tag("IntegrationTest") -@ActiveProfiles("test") -@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) -annotation class IntegrationTest - -@ContextConfiguration(initializers = [PostgreSQLContainerInitializer::class]) -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) -annotation class WithPostgreSQL diff --git a/src/test/kotlin/TestFixtures.kt b/src/test/kotlin/TestFixtures.kt deleted file mode 100644 index d6bf2b1..0000000 --- a/src/test/kotlin/TestFixtures.kt +++ /dev/null @@ -1,121 +0,0 @@ -import com.fiap.selfordermanagement.domain.entities.Component -import com.fiap.selfordermanagement.domain.entities.Customer -import com.fiap.selfordermanagement.domain.entities.Order -import com.fiap.selfordermanagement.domain.entities.OrderItem -import com.fiap.selfordermanagement.domain.entities.Payment -import com.fiap.selfordermanagement.domain.entities.PaymentRequest -import com.fiap.selfordermanagement.domain.entities.Product -import com.fiap.selfordermanagement.domain.entities.Stock -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import com.fiap.selfordermanagement.domain.valueobjects.ProductCategory -import java.math.BigDecimal -import java.time.LocalDate -import java.time.LocalDateTime -import java.util.* - -fun createCustomer( - id : UUID = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"), - document: String = "444.555.666-77", - name: String = "Fulano de Tal", - email: String = "fulano@detal.com", - phone: String = "5511999999999", - address: String = "São Paulo", -) = Customer( - id = id, - document = document, - name = name, - email = email, - phone = phone, - address = address, -) - -fun createProduct( - number: Long = 123, - name: String = "Big Mac", - category: ProductCategory = ProductCategory.MAIN, - price: BigDecimal = BigDecimal("10.00"), - description: String = "Dois hambúrgueres, alface, queijo, molho especial, cebola, picles, num pão com gergelim", - minSub: Int = 3, - maxSub: Int = 3, - subitems: List = listOf(), - components: List = listOf(), -) = Product( - number = number, - name = name, - category = category, - price = price, - description = description, - minSub = minSub, - maxSub = maxSub, - subItems = subitems, - components = components, -) - -fun createStock( - productNumber: Long = 123, - quantity: Long = 100, -) = Stock( - componentNumber = productNumber, - quantity = quantity, -) - -fun createComponent( - componentNumber: Long = 9870001, - name: String = "Lata refrigerante coca-cola 355ml", -) = Component( - number = componentNumber, - name = name, -) - -fun createOrder( - number: Long? = 98765, - date: LocalDate = LocalDate.parse("2023-10-01"), - customer: Customer? = null, - status: OrderStatus = OrderStatus.CREATED, - items: List = listOf(createProduct()), - total: BigDecimal = BigDecimal("50.00"), -) = Order( - number = number, - date = date, - customer = customer, - status = status, - items = items, - total = total, -) - -fun createOrderItem( - productNumber: Long = 123, - quantity: Long = 1, -) = OrderItem( - productNumber = productNumber, - quantity = quantity, -) - -fun createPayment( - orderNumber: Long = 98765, - externalOrderId: String = "66b0f5f7-9997-4f49-a203-3dab2d936b50", - externalOrderGlobalId: String? = null, - paymentInfo: String = "00020101021243650016COM.MERCADOLIBRE...", - createdAt: LocalDateTime = LocalDateTime.parse("2023-10-01T18:00:00"), - status: PaymentStatus = PaymentStatus.PENDING, - statusChangedAt: LocalDateTime = LocalDateTime.parse("2023-10-01T18:00:00"), -) = Payment( - orderNumber = orderNumber, - externalOrderId = externalOrderId, - externalOrderGlobalId = externalOrderGlobalId, - paymentInfo = paymentInfo, - createdAt = createdAt, - status = status, - statusChangedAt, -) - -fun createPaymentRequest( - externalOrderId: String = "66b0f5f7-9997-4f49-a203-3dab2d936b50", - externalOrderGlobalId: String? = null, - paymentInfo: String = "00020101021243650016COM.MERCADOLIBRE...", -) = PaymentRequest( - externalOrderId = externalOrderId, - externalOrderGlobalId = externalOrderGlobalId, - paymentInfo = paymentInfo, -) diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/ComponentServiceTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/ComponentServiceTest.kt deleted file mode 100644 index 8e79f2b..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/ComponentServiceTest.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import com.fiap.selfordermanagement.adapter.gateway.ComponentGateway -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.usecases.services.ComponentService -import createComponent -import createProduct -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test - -class ComponentServiceTest { - private val componentRepository = mockk() - private val stockRepository = mockk() - private val productRepository = mockk() - - private val componentService = - ComponentService( - componentRepository, - stockRepository, - productRepository, - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Nested - inner class GetByComponentNumberTest { - @Test - fun `getByComponentNumber should return a Component when it exists`() { - val component = createComponent() - - every { componentRepository.findByComponentNumber(component.number!!) } returns component - - val result = componentService.getByComponentNumber(component.number!!) - - assertThat(result).isEqualTo(component) - } - - @Test - fun `getByComponentNumber should throw an exception when the component is not found`() { - val componentNumber = 123L - - every { componentRepository.findByComponentNumber(componentNumber) } returns null - - assertThatThrownBy { componentService.getByComponentNumber(componentNumber) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.COMPONENT_NOT_FOUND) - } - } - - @Nested - inner class FindByProductNumberTest { - @Test - fun `findByProductNumber should return a list of components when it exists`() { - val components = listOf(createComponent()) - val product = createProduct(components = components) - - every { productRepository.findByProductNumber(product.number!!) } returns product - - val result = componentService.findByProductNumber(product.number!!) - - assertThat(result).isEqualTo(components) - } - - @Test - fun `findByProductNumber should throw an exception when the product is not found`() { - val productNumber = 123L - - every { productRepository.findByProductNumber(productNumber) } returns null - - assertThatThrownBy { componentService.findByProductNumber(productNumber) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.PRODUCT_NOT_FOUND) - } - } -} diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/CustomerIntegrationTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/CustomerIntegrationTest.kt deleted file mode 100644 index 1ff181d..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/CustomerIntegrationTest.kt +++ /dev/null @@ -1,189 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import IntegrationTest -import WithPostgreSQL -import com.fiap.selfordermanagement.adapter.gateway.CustomerGateway -import com.fiap.selfordermanagement.domain.errors.ErrorType -import createCustomerRequest -import io.restassured.RestAssured -import io.restassured.RestAssured.given -import io.restassured.http.ContentType -import org.assertj.core.api.Assertions.assertThat -import org.hamcrest.Matchers.equalTo -import org.hamcrest.Matchers.hasSize -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.web.server.LocalServerPort -import org.springframework.http.HttpStatus - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@IntegrationTest -@WithPostgreSQL -@Disabled -class CustomerIntegrationTest { - @LocalServerPort - private val port: Int? = null - - @Autowired - private lateinit var customerRepository: CustomerGateway - - @BeforeEach - fun setUp() { - customerRepository.deleteAll() - - RestAssured.baseURI = "http://localhost:$port" - RestAssured.enableLoggingOfRequestAndResponseIfValidationFails() - } - - @Test - fun `should succeed to manage and search customers in the happy path`() { - val customerRequest = - createCustomerRequest( - name = "John Doe", - ) - - // create - given() - .contentType(ContentType.JSON) - .body(customerRequest) - .`when`() - .post("/customers") - .then() - .statusCode(HttpStatus.OK.value()) - .body( - "document", equalTo(customerRequest.document), - "name", equalTo(customerRequest.name), - "email", equalTo(customerRequest.email), - "phone", equalTo(customerRequest.phone), - "address", equalTo(customerRequest.address), - ) - - val customer = customerRepository.findAll()[0] - - // list all - given() - .contentType(ContentType.JSON) - .`when`() - .get("/customers") - .then() - .statusCode(HttpStatus.OK.value()) - .body( - ".", - hasSize(1), - "[0].document", - equalTo(customer.document), - ) - - // get - given() - .contentType(ContentType.JSON) - .`when`() - .get("/customers/${customer.document}") - .then() - .statusCode(HttpStatus.OK.value()) - .body( - "document", - equalTo(customer.document), - ) - - // search - given() - .contentType(ContentType.JSON) - .param("name", " john ") - .`when`() - .get("/customers/search") - .then() - .statusCode(HttpStatus.OK.value()) - .body( - ".", - hasSize(1), - "[0].document", - equalTo(customer.document), - ) - - // update - val changed = customerRequest.copy(email = "changed@newemail.com") - given() - .contentType(ContentType.JSON) - .body(changed) - .`when`() - .put("/customers/${customer.id}") - .then() - .statusCode(HttpStatus.OK.value()) - .body( - "email", - equalTo(changed.email), - ) - - assertThat(customerRepository.findById(customer.id)?.email).isEqualTo(changed.email) - - // remove - given() - .contentType(ContentType.JSON) - .`when`() - .delete("/customers/${customerRequest.document}") - .then() - .statusCode(HttpStatus.OK.value()) - - assertThat(customerRepository.findAll()).isEmpty() - } - - @Test - fun `should handle corner cases accordingly`() { - val customer = createCustomerRequest() - - // create - given() - .contentType(ContentType.JSON) - .body(customer) - .`when`() - .post("/customers") - .then() - .statusCode(HttpStatus.OK.value()) - - // try to create with same identifier - given() - .contentType(ContentType.JSON) - .body(customer) - .`when`() - .post("/customers") - .then() - .statusCode(HttpStatus.UNPROCESSABLE_ENTITY.value()) - .body( - "error", - equalTo(ErrorType.CUSTOMER_ALREADY_EXISTS.name), - ) - - assertThat(customerRepository.findAll()).hasSize(1) - - val nonExistentCustomer = createCustomerRequest(document = "11122233344") - - // try to update non-existent - given() - .contentType(ContentType.JSON) - .body(nonExistentCustomer) - .`when`() - .put("/customers/${nonExistentCustomer.document}") - .then() - .statusCode(HttpStatus.NOT_FOUND.value()) - .body( - "error", - equalTo(ErrorType.CUSTOMER_NOT_FOUND.name), - ) - - // try to delete non-existent - given() - .contentType(ContentType.JSON) - .`when`() - .delete("/customers/${nonExistentCustomer.document}") - .then() - .statusCode(HttpStatus.NOT_FOUND.value()) - .body( - "error", - equalTo(ErrorType.CUSTOMER_NOT_FOUND.name), - ) - } -} diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/CustomerServiceTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/CustomerServiceTest.kt deleted file mode 100644 index 1f6f5ca..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/CustomerServiceTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import com.fiap.selfordermanagement.adapter.gateway.CustomerGateway -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.usecases.services.CustomerService -import createCustomer -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import java.util.* - -class CustomerServiceTest { - private val customerRepository = mockk() - - private val customerService = - CustomerService( - customerRepository, - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Nested - inner class GetByDocumentTest { - @Test - fun `getByDocument should return a Customer when it exists`() { - val customer = createCustomer() - - every { customerRepository.findById(customer.id) } returns customer - - val result = customerService.getById(customer.id) - - assertThat(result).isEqualTo(customer) - } - - @Test - fun `getById should throw an exception when the customer is not found`() { - val document = UUID.randomUUID() - - every { customerRepository.findById(document) } returns null - - assertThatThrownBy { customerService.getById(document) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.CUSTOMER_NOT_FOUND) - } - } -} diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/OrderServiceTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/OrderServiceTest.kt deleted file mode 100644 index a5ee709..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/OrderServiceTest.kt +++ /dev/null @@ -1,303 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import com.fiap.selfordermanagement.adapter.gateway.OrderGateway -import com.fiap.selfordermanagement.adapter.gateway.impl.TransactionalGatewayImpl -import com.fiap.selfordermanagement.domain.entities.OrderItem -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import com.fiap.selfordermanagement.domain.valueobjects.OrderStatus -import com.fiap.selfordermanagement.domain.valueobjects.PaymentStatus -import com.fiap.selfordermanagement.usecases.AdjustStockUseCase -import com.fiap.selfordermanagement.usecases.LoadCustomerUseCase -import com.fiap.selfordermanagement.usecases.LoadPaymentUseCase -import com.fiap.selfordermanagement.usecases.LoadProductUseCase -import com.fiap.selfordermanagement.usecases.ProvidePaymentRequestUseCase -import createCustomer -import createOrder -import createOrderItem -import createPayment -import createPaymentRequest -import createProduct -import createStock -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.EnumSource -import services.OrderService -import java.math.BigDecimal -import java.util.* - -class OrderServiceTest { - private val orderRepository = mockk() - private val getCustomersUseCase = mockk() - private val getProductUseCase = mockk() - private val adjustInventoryUseCase = mockk() - private val loadPaymentUseCase = mockk() - private val providePaymentRequestUseCase = mockk() - private val transactionalRepository = TransactionalGatewayImpl() - - private val orderService = - OrderService( - orderRepository, - getCustomersUseCase, - getProductUseCase, - adjustInventoryUseCase, - providePaymentRequestUseCase, - loadPaymentUseCase, - transactionalRepository, - ) - - @BeforeEach - fun setUp() { - every { getCustomersUseCase.getById(any()) } returns createCustomer() - every { getProductUseCase.getByProductNumber(any()) } returns createProduct() - every { providePaymentRequestUseCase.providePaymentRequest(any()) } returns createPaymentRequest() - } - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Nested - inner class GetByOrderNumberTest { - @Test - fun `getByOrderNumber should return an Order when it exists`() { - val order = createOrder() - - every { orderRepository.findByOrderNumber(order.number!!) } returns order - - val result = orderService.getByOrderNumber(order.number!!) - - assertThat(result).isEqualTo(order) - } - - @Test - fun `getByOrderNumber should throw an exception when the order is not found`() { - val orderNumber = 67890L - - every { orderRepository.findByOrderNumber(orderNumber) } returns null - - assertThatThrownBy { orderService.getByOrderNumber(orderNumber) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.ORDER_NOT_FOUND) - } - } - - @Nested - inner class CreateTest { - @Test - fun `create should return a valid Order when items are provided`() { - val items = listOf(createOrderItem()) - - every { adjustInventoryUseCase.decrement(any(), any()) } returns createStock() - every { orderRepository.upsert(any()) } returns createOrder(status = OrderStatus.CREATED) - - val result = orderService.create(null, items) - - assertThat(result).isNotNull() - assertThat(result.number).isNotNull() - assertThat(result.items).hasSize(1) - assertThat(result.total).isEqualTo(BigDecimal("50.00")) - } - - @Test - fun `create should throw an exception when items are empty`() { - val items = emptyList() - - assertThatThrownBy { orderService.create(null, items) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.EMPTY_ORDER) - } - } - - @Nested - inner class ConfirmOrderTest { - @Test - fun `should confirm a pending order with a confirmed payment`() { - val order = createOrder(status = OrderStatus.PENDING) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { loadPaymentUseCase.getByOrderNumber(any()) } returns createPayment(status = PaymentStatus.CONFIRMED) - every { orderRepository.upsert(any()) } answers { firstArg() } - - val result = orderService.confirmOrder(order.number!!) - - assertThat(result).isNotNull() - assertThat(result.status).isEqualTo(OrderStatus.CONFIRMED) - } - - @Test - fun `should not confirm an order when payment is not found`() { - val order = createOrder(status = OrderStatus.PENDING) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { loadPaymentUseCase.getByOrderNumber(any()) } throws( - SelfOrderManagementException(ErrorType.PAYMENT_NOT_FOUND, message = "") - ) - - assertThatThrownBy { orderService.confirmOrder(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.PAYMENT_NOT_FOUND) - } - - @Test - fun `should not confirm an order when payment is not confirmed`() { - val order = createOrder(status = OrderStatus.PENDING) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(order) } returns order - every { loadPaymentUseCase.getByOrderNumber(any()) } returns createPayment(status = PaymentStatus.PENDING) - every { orderRepository.upsert(any()) } answers { firstArg() } - - assertThatThrownBy { orderService.confirmOrder(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.PAYMENT_NOT_CONFIRMED) - } - - @ParameterizedTest - @EnumSource(OrderStatus::class, names = ["CREATED", "CONFIRMED", "PREPARING", "COMPLETED", "DONE", "CANCELLED"]) - fun `should not confirm an order which is not pending`(orderStatus: OrderStatus) { - val order = createOrder(status = orderStatus) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(order) } answers { firstArg() } - every { loadPaymentUseCase.getByOrderNumber(any()) } returns createPayment(status = PaymentStatus.CONFIRMED) - - assertThatThrownBy { orderService.confirmOrder(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.INVALID_ORDER_STATE_TRANSITION) - } - } - - @Nested - inner class StartOrderPreparationTest { - @Test - fun `startOrderPreparation should start preparation for a CONFIRMED order`() { - val order = createOrder(status = OrderStatus.CONFIRMED) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(any()) } answers { firstArg() } - - val result = orderService.startOrderPreparation(order.number!!) - - assertThat(result).isNotNull() - assertThat(result.status).isEqualTo(OrderStatus.PREPARING) - } - - @Test - fun `startOrderPreparation should throw an exception for a non-CONFIRMED order`() { - val order = createOrder(status = OrderStatus.CREATED) - - every { orderRepository.findByOrderNumber(any()) } returns order - - assertThatThrownBy { orderService.startOrderPreparation(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.INVALID_ORDER_STATE_TRANSITION) - } - } - - @Nested - inner class FinishOrderPreparationTest { - @Test - fun `finishOrderPreparation should finish a COMPLETED order when it is delivered`() { - val order = createOrder(status = OrderStatus.COMPLETED) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(any()) } answers { firstArg() } - - val result = orderService.finishOrderPreparation(order.number!!) - - assertThat(result).isNotNull() - assertThat(result.status).isEqualTo(OrderStatus.DONE) - } - - @Test - fun `finishOrderPreparation should throw an exception for a non-PREPARING order`() { - val order = createOrder(status = OrderStatus.CREATED) - - every { orderRepository.findByOrderNumber(any()) } returns order - - assertThatThrownBy { orderService.finishOrderPreparation(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.INVALID_ORDER_STATE_TRANSITION) - } - } - - @Nested - inner class CompleteOrderTest { - @Test - fun `completeOrder should complete an order that is not yet completed (status is not DONE)`() { - val order = createOrder(status = OrderStatus.PREPARING) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(any()) } answers { firstArg() } - - val result = orderService.completeOrder(order.number!!) - - assertThat(result).isNotNull() - assertThat(result.status).isEqualTo(OrderStatus.COMPLETED) - } - - @Test - fun `completeOrder should throw an exception for an already completed order (status is DONE)`() { - val order = createOrder(status = OrderStatus.DONE) - - every { orderRepository.findByOrderNumber(any()) } returns order - - assertThatThrownBy { orderService.completeOrder(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.INVALID_ORDER_STATE_TRANSITION) - .hasMessage("Order cannot be completed until it has been prepared") - } - } - - @Nested - inner class CancelOrderTest { - @Test - fun `cancelOrder should cancel a CREATED order and make reserved products available`() { - val order = createOrder(status = OrderStatus.CREATED) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(any()) } answers { firstArg() } - every { adjustInventoryUseCase.increment(any(), any()) } returns createStock() - - val result = orderService.cancelOrder(order.number!!) - - assertThat(result).isNotNull() - assertThat(result.status).isEqualTo(OrderStatus.CANCELLED) - } - - @Test - fun `cancelOrder should cancel a CONFIRMED order and make reserved products available`() { - val order = createOrder(status = OrderStatus.CONFIRMED) - - every { orderRepository.findByOrderNumber(any()) } returns order - every { orderRepository.upsert(any()) } answers { firstArg() } - every { adjustInventoryUseCase.increment(any(), any()) } returns createStock() - - val result = orderService.cancelOrder(order.number!!) - - assertThat(result).isNotNull() - assertThat(result.status).isEqualTo(OrderStatus.CANCELLED) - } - - @Test - fun `cancelOrder should throw an exception for a COMPLETED order`() { - val order = createOrder(status = OrderStatus.COMPLETED) - - every { orderRepository.findByOrderNumber(any()) } returns order - - assertThatThrownBy { orderService.cancelOrder(order.number!!) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.INVALID_ORDER_STATE_TRANSITION) - } - } -} diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/PaymentServiceTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/PaymentServiceTest.kt deleted file mode 100644 index 21b3d90..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/PaymentServiceTest.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import com.fiap.selfordermanagement.adapter.gateway.PaymentGateway -import com.fiap.selfordermanagement.adapter.gateway.PaymentProviderGateway -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import createOrder -import createPayment -import createPaymentRequest -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import io.mockk.verify -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import services.PaymentService - -class PaymentServiceTest { - private val paymentRepository = mockk() - private val paymentProvider = mockk() - - private val paymentService = - PaymentService( - paymentRepository, - paymentProvider, - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Nested - inner class GetByOrderNumberTest { - @Test - fun `getByOrderNumberTest should return a Payment when it exists`() { - val payment = createPayment() - - every { paymentRepository.findByOrderNumber(payment.orderNumber) } returns payment - - val result = paymentService.getByOrderNumber(payment.orderNumber) - - assertThat(result).isEqualTo(payment) - } - - @Test - fun `getByOrderNumberTest should throw an exception when the payment is not found`() { - val orderNumber = 98765L - - every { paymentRepository.findByOrderNumber(orderNumber) } returns null - - assertThatThrownBy { paymentService.getByOrderNumber(orderNumber) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.PAYMENT_NOT_FOUND) - } - } - - @Nested - inner class ProvidePaymentRequestTest { - @Test - fun `providePaymentRequest should create a new PaymentRequest and a corresponding Payment`() { - val order = createOrder() - - val paymentRequest = createPaymentRequest() - - every { paymentProvider.createExternalOrder(order) } returns paymentRequest - every { paymentRepository.create(any()) } answers { firstArg() } - - val result = paymentService.providePaymentRequest(order) - - assertThat(result).isNotNull() - assertThat(result.externalOrderId).isEqualTo(paymentRequest.externalOrderId) - assertThat(result.paymentInfo).isEqualTo(paymentRequest.paymentInfo) - - verify { paymentRepository.create(any()) } - } - } -} diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/ProductServiceTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/ProductServiceTest.kt deleted file mode 100644 index 30e20ff..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/ProductServiceTest.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import com.fiap.selfordermanagement.adapter.gateway.ProductGateway -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import createProduct -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import services.ProductService - -class ProductServiceTest { - private val productRepository = mockk() - private val loadInputUseCase = mockk() - - private val productService = - ProductService( - productRepository, - loadInputUseCase, - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Nested - inner class GetByProductNumberTest { - @Test - fun `getByProductNumber should return a Product when it exists`() { - val product = createProduct() - - every { productRepository.findByProductNumber(product.number!!) } returns product - - val result = productService.getByProductNumber(product.number!!) - - assertThat(result).isEqualTo(product) - } - - @Test - fun `getByProductNumber should throw an exception when the product is not found`() { - val productNumber = 123L - - every { productRepository.findByProductNumber(productNumber) } returns null - - assertThatThrownBy { productService.getByProductNumber(productNumber) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.PRODUCT_NOT_FOUND) - } - } -} diff --git a/src/test/kotlin/com/fiap/selfordermanagement/application/services/StockServiceTest.kt b/src/test/kotlin/com/fiap/selfordermanagement/application/services/StockServiceTest.kt deleted file mode 100644 index e92a5f5..0000000 --- a/src/test/kotlin/com/fiap/selfordermanagement/application/services/StockServiceTest.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.fiap.selfordermanagement.application.services - -import com.fiap.selfordermanagement.adapter.gateway.StockGateway -import com.fiap.selfordermanagement.domain.errors.ErrorType -import com.fiap.selfordermanagement.domain.errors.SelfOrderManagementException -import createStock -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import services.StockService - -class StockServiceTest { - private val stockRepository = mockk() - - private val stockService = - StockService( - stockRepository, - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Nested - inner class GetByComponentNumberTest { - @Test - fun `getByComponentNumber should return a Stock when it exists`() { - val stock = createStock() - - every { stockRepository.findByComponentNumber(stock.componentNumber) } returns stock - - val result = stockService.getByComponentNumber(stock.componentNumber) - - assertThat(result).isEqualTo(stock) - } - - @Test - fun `getByComponentNumber should throw an exception when the stock is not found`() { - val inputNumber = 123L - - every { stockRepository.findByComponentNumber(inputNumber) } returns null - - assertThatThrownBy { stockService.getByComponentNumber(inputNumber) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.STOCK_NOT_FOUND) - } - } - - @Nested - inner class IncrementTest { - @Test - fun `increment should increase the stock quantity for a given product number`() { - val initialQuantity = 100L - val incrementQuantity = 100L - val stock = createStock(quantity = initialQuantity) - - every { stockRepository.findByComponentNumber(stock.componentNumber) } returns stock - every { stockRepository.update(any()) } answers { firstArg() } - - val result = stockService.increment(stock.componentNumber, incrementQuantity) - - assertThat(result).isNotNull - assertThat(result.componentNumber).isEqualTo(stock.componentNumber) - assertThat(result.quantity).isEqualTo(initialQuantity + incrementQuantity) - } - } - - @Nested - inner class DecrementTest { - @Test - fun `decrement should reduce the stock quantity for a given product number`() { - val initialQuantity = 100L - val decrementQuantity = 50L - val stock = createStock(quantity = initialQuantity) - - every { stockRepository.findByComponentNumber(stock.componentNumber) } returns stock - every { stockRepository.update(any()) } answers { firstArg() } - - val result = stockService.decrement(stock.componentNumber, decrementQuantity) - - assertThat(result).isNotNull - assertThat(result.componentNumber).isEqualTo(stock.componentNumber) - assertThat(result.quantity).isEqualTo(initialQuantity - decrementQuantity) - } - - @Test - fun `decrement should throw an exception for insufficient stock`() { - val initialQuantity = 100L - val decrementQuantity = 100L - val stock = createStock(quantity = initialQuantity) - - every { stockRepository.findByComponentNumber(stock.componentNumber) } returns stock - - assertThatThrownBy { stockService.decrement(stock.componentNumber, decrementQuantity) } - .isInstanceOf(SelfOrderManagementException::class.java) - .hasFieldOrPropertyWithValue("errorType", ErrorType.INSUFFICIENT_STOCK) - } - } -}