Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package com.orderflow.ecommerce.controllers;

import com.orderflow.ecommerce.dtos.ErrorResponse;
import com.orderflow.ecommerce.controllers.docs.CategoryControllerDocs;
import com.orderflow.ecommerce.entities.Category;
import com.orderflow.ecommerce.repositories.CategoryRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
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.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
Expand All @@ -21,82 +13,46 @@

@RestController
@RequestMapping(value = "/categories")
@Tag(name = "Categorias", description = "CRUD de categorias de produtos")
public class CategoryController {
public class CategoryController implements CategoryControllerDocs {

@Autowired
private CategoryRepository repository;

@Override
@GetMapping
@Operation(summary = "Lista todas as categorias")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Lista obtida com sucesso",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = Category.class))))
})
public ResponseEntity<List<Category>> findAll() {
return ResponseEntity.ok().body(repository.findAll());
}

@Override
@GetMapping(value = "/{id}")
@Operation(summary = "Obtém categoria por id")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Categoria encontrada",
content = @Content(schema = @Schema(implementation = Category.class))),
@ApiResponse(responseCode = "404", description = "Categoria inexistente",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<Category> findById(
@Parameter(description = "Identificador numérico da categoria", required = true, example = "1")
@PathVariable Long id) {
public ResponseEntity<Category> findById(@PathVariable Long id) {
Category obj = repository.findById(id)
.orElseThrow(() -> new NoSuchElementException("Categoria não encontrada com o ID: " + id));
.orElseThrow(() -> new NoSuchElementException("Categoria não encontrada com o ID: " + id));
return ResponseEntity.ok().body(obj);
}

@Override
@PostMapping
@Operation(summary = "Cria uma categoria")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Categoria criada e persistida",
content = @Content(schema = @Schema(implementation = Category.class))),
@ApiResponse(responseCode = "400", description = "Corpo inválido ou falha de validação",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<Category> insert(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Dados da categoria (campo id pode ser omitido)", required = true)
@Valid @RequestBody Category obj) {
public ResponseEntity<Category> insert(@Valid @RequestBody Category obj) {
return ResponseEntity.ok().body(repository.save(obj));
}

@Override
@DeleteMapping(value = "/{id}")
@Operation(summary = "Remove categoria por id")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "Exclusão processada (idempotente se o registro não existir)")
})
public ResponseEntity<Void> delete(
@Parameter(description = "Identificador da categoria a remover", required = true, example = "1")
@PathVariable Long id) {
public ResponseEntity<Void> delete(@PathVariable Long id) {
repository.deleteById(id);
return ResponseEntity.noContent().build();
}

@Override
@PutMapping(value = "/{id}")
@Operation(summary = "Atualiza o nome de uma categoria")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Categoria atualizada",
content = @Content(schema = @Schema(implementation = Category.class))),
@ApiResponse(responseCode = "400", description = "Corpo inválido ou falha de validação",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "404", description = "Categoria inexistente",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<Category> update(
@Parameter(description = "Identificador da categoria", required = true, example = "1")
@PathVariable Long id,
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Novos dados (normalmente apenas name)", required = true)
@Valid @RequestBody Category obj) {
@PathVariable Long id,
@Valid @RequestBody Category obj
) {
Category entity = repository.findById(id)
.orElseThrow(() -> new NoSuchElementException("Categoria não encontrada para atualizar"));

.orElseThrow(() -> new NoSuchElementException("Categoria não encontrada para atualizar"));
entity.setName(obj.getName());
return ResponseEntity.ok().body(repository.save(entity));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package com.orderflow.ecommerce.controllers;

import com.orderflow.ecommerce.dtos.ErrorResponse;
import com.orderflow.ecommerce.controllers.docs.ProductControllerDocs;
import com.orderflow.ecommerce.entities.Product;
import com.orderflow.ecommerce.repositories.ProductRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
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.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
Expand All @@ -21,79 +13,41 @@

@RestController
@RequestMapping(value = "/products")
@Tag(name = "Produtos", description = "CRUD de produtos do catálogo")
public class ProductController {
public class ProductController implements ProductControllerDocs {

@Autowired
private ProductRepository repository;

@Override
@GetMapping
@Operation(summary = "Lista todos os produtos")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Lista obtida com sucesso",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = Product.class))))
})
public ResponseEntity<List<Product>> findAll() {
return ResponseEntity.ok().body(repository.findAll());
}

@Override
@GetMapping(value = "/{id}")
@Operation(summary = "Obtém produto por id")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Produto encontrado",
content = @Content(schema = @Schema(implementation = Product.class))),
@ApiResponse(responseCode = "404", description = "Produto inexistente",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<Product> findById(
@Parameter(description = "Identificador numérico do produto", required = true, example = "10")
@PathVariable Long id) {
public ResponseEntity<Product> findById(@PathVariable Long id) {
Product obj = repository.findById(id)
.orElseThrow(() -> new NoSuchElementException("Produto não encontrado"));
return ResponseEntity.ok().body(obj);
}

@Override
@PostMapping
@Operation(summary = "Cria um produto")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Produto criado e persistido",
content = @Content(schema = @Schema(implementation = Product.class))),
@ApiResponse(responseCode = "400", description = "Corpo inválido ou falha de validação",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<Product> insert(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Dados do produto; id pode ser omitido; category pode ser {\"id\": n}", required = true)
@Valid @RequestBody Product obj) {
public ResponseEntity<Product> insert(@Valid @RequestBody Product obj) {
return ResponseEntity.ok().body(repository.save(obj));
}

@Override
@DeleteMapping(value = "/{id}")
@Operation(summary = "Remove produto por id")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "Exclusão processada (idempotente se o registro não existir)")
})
public ResponseEntity<Void> delete(
@Parameter(description = "Identificador do produto a remover", required = true, example = "10")
@PathVariable Long id) {
public ResponseEntity<Void> delete(@PathVariable Long id) {
repository.deleteById(id);
return ResponseEntity.noContent().build();
}

@Override
@PutMapping(value = "/{id}")
@Operation(summary = "Atualiza um produto")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Produto atualizado",
content = @Content(schema = @Schema(implementation = Product.class))),
@ApiResponse(responseCode = "400", description = "Corpo inválido ou falha de validação",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "404", description = "Produto inexistente",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity<Product> update(
@Parameter(description = "Identificador do produto", required = true, example = "10")
@PathVariable Long id,
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Campos a atualizar; category pode ser referência por id", required = true)
@Valid @RequestBody Product obj) {
public ResponseEntity<Product> update(@PathVariable Long id, @Valid @RequestBody Product obj) {
Product entity = repository.findById(id)
.orElseThrow(() -> new NoSuchElementException("Produto não encontrado para atualizar"));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
package com.orderflow.ecommerce.controllers;

import com.orderflow.ecommerce.dtos.ErrorResponse;
import com.orderflow.ecommerce.controllers.docs.TestControllerDocs;
import com.orderflow.ecommerce.dtos.OrderItemDto;
import com.orderflow.ecommerce.dtos.PingResponse;
import com.orderflow.ecommerce.dtos.PublishSampleOrderResponse;
import com.orderflow.ecommerce.entities.enums.OrderStatus;
import com.orderflow.ecommerce.messaging.events.OrderCreatedEvent;
import com.orderflow.ecommerce.messaging.publisher.OrderEventPublisher;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -24,8 +18,7 @@

@RestController
@RequestMapping("/test")
@Tag(name = "Testes e integração", description = "Endpoints auxiliares para health check e publicação de eventos de exemplo no RabbitMQ")
public class TestController {
public class TestController implements TestControllerDocs {

private static final long DEFAULT_START_ORDER_ID = 1000L;
private final OrderEventPublisher orderEventPublisher;
Expand All @@ -35,12 +28,8 @@ public TestController(OrderEventPublisher orderEventPublisher) {
this.orderEventPublisher = orderEventPublisher;
}

@Override
@GetMapping("/ping")
@Operation(summary = "Verifica se a API está respondendo")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "API ativa",
content = @Content(schema = @Schema(implementation = PingResponse.class)))
})
public PingResponse ping() {
return new PingResponse(
"ok",
Expand All @@ -49,15 +38,8 @@ public PingResponse ping() {
);
}

@Override
@GetMapping("/publish-sample-order")
@Operation(summary = "Publica um evento OrderCreated de exemplo no RabbitMQ",
description = "Útil para validar filas e consumidores (EmailConsumer, InventoryConsumer) sem fluxo real de pedido.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Evento enfileirado",
content = @Content(schema = @Schema(implementation = PublishSampleOrderResponse.class))),
@ApiResponse(responseCode = "500", description = "Erro interno ao publicar",
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public PublishSampleOrderResponse publishSampleOrder() {
long nextOrderId = nextSampleOrderId();
var event = new OrderCreatedEvent(
Expand Down
Loading