Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
65ae809
feat(categoria): add category dtos (request/response)
maxzdosreis May 20, 2026
f9798ad
feat(produto): add product dtos (request/response)
maxzdosreis May 20, 2026
23a96a5
chore: add mapstruct dependency
maxzdosreis May 20, 2026
011988c
feat(produto): add mapper to product
maxzdosreis May 20, 2026
4a68573
feat(categoria): add mapper to category
maxzdosreis May 20, 2026
c16f565
FEAT(categoria): add methods in repository
maxzdosreis May 23, 2026
3452153
feat(infra): add IllegalArgumentException handler for bad request res…
maxzdosreis May 23, 2026
30c132c
feat(categoria): add CategoryService with CRUD, pagination and name v…
maxzdosreis May 23, 2026
a73f28c
chore: add dependency mapstruct-processor and plugins of maven-compil…
maxzdosreis May 23, 2026
748b9b2
fix(produto): correct mapping of product fileds
maxzdosreis May 23, 2026
4eb2867
docs(categoria): update CategoryControllerDocs to reflect new DTOs an…
maxzdosreis May 23, 2026
6f74aa0
refactor(categoria): refactor CategoryController to use service, DTOs…
maxzdosreis May 23, 2026
e5fc305
feat(produto): add method findByName in repository
maxzdosreis May 24, 2026
bfd81b3
fix(produto): fix existsByName method name in ProductRepository
maxzdosreis May 24, 2026
b69b19a
feat(produto): add ProductService with CRUD and pagination
maxzdosreis May 24, 2026
1c44f66
refactor(produto): refactor ProductController to use service and dtos
maxzdosreis May 24, 2026
82182ab
docs(produto): update ProductControllerDocs to reflect new dtos and e…
maxzdosreis May 24, 2026
ae68279
feat(produto): add dynamic product filtering with Specification
maxzdosreis May 24, 2026
b366ba9
test(categoria): add unit tests for CategoryService
maxzdosreis May 26, 2026
fc70490
test(produto): add unit tests for ProductService
maxzdosreis May 26, 2026
0e84251
test(categoria): add unit testes for CategoryController
maxzdosreis May 27, 2026
efee13d
test(produto): add unit tests for ProductController
maxzdosreis May 27, 2026
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
31 changes: 31 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.6.3</version>
</dependency>

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand All @@ -97,6 +110,24 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -1,59 +1,62 @@
package com.orderflow.ecommerce.controllers;

import com.orderflow.ecommerce.controllers.docs.CategoryControllerDocs;
import com.orderflow.ecommerce.entities.Category;
import com.orderflow.ecommerce.repositories.CategoryRepository;
import com.orderflow.ecommerce.dtos.CategoryRequest;
import com.orderflow.ecommerce.dtos.CategoryResponse;
import com.orderflow.ecommerce.services.CategoryService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.NoSuchElementException;

@RestController
@RequestMapping(value = "/categories")
public class CategoryController implements CategoryControllerDocs {

@Autowired
private CategoryRepository repository;
private CategoryService categoryService;

@Override
@GetMapping
public ResponseEntity<List<Category>> findAll() {
return ResponseEntity.ok().body(repository.findAll());
public ResponseEntity<Page<CategoryResponse>> findAll(
@RequestParam(required = false) String name,
Pageable pageable
) {
if (name != null && !name.isBlank()) {
return ResponseEntity.ok(categoryService.findByName(name, pageable));
}
return ResponseEntity.ok(categoryService.findAll(pageable));
}

@Override
@GetMapping(value = "/{id}")
public ResponseEntity<Category> findById(@PathVariable Long id) {
Category obj = repository.findById(id)
.orElseThrow(() -> new NoSuchElementException("Categoria não encontrada com o ID: " + id));
return ResponseEntity.ok().body(obj);
public ResponseEntity<CategoryResponse> findById(@PathVariable Long id) {
return ResponseEntity.ok(categoryService.findById(id));
}

@Override
@PostMapping
public ResponseEntity<Category> insert(@Valid @RequestBody Category obj) {
return ResponseEntity.ok().body(repository.save(obj));
public ResponseEntity<CategoryResponse> create(@Valid @RequestBody CategoryRequest request) {
CategoryResponse response = categoryService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

@Override
@DeleteMapping(value = "/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
repository.deleteById(id);
return ResponseEntity.noContent().build();
@PutMapping(value = "/{id}")
public ResponseEntity<CategoryResponse> update(
@PathVariable Long id,
@Valid @RequestBody CategoryRequest request
) {
return ResponseEntity.ok(categoryService.update(id, request));
}

@Override
@PutMapping(value = "/{id}")
public ResponseEntity<Category> update(
@PathVariable Long id,
@Valid @RequestBody Category obj
) {
Category entity = repository.findById(id)
.orElseThrow(() -> new NoSuchElementException("Categoria não encontrada para atualizar"));
entity.setName(obj.getName());
return ResponseEntity.ok().body(repository.save(entity));
@DeleteMapping(value = "/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
categoryService.delete(id);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.orderflow.ecommerce.controllers;

import com.orderflow.ecommerce.controllers.docs.ProductControllerDocs;
import com.orderflow.ecommerce.dtos.ProductFilter;
import com.orderflow.ecommerce.dtos.ProductRequest;
import com.orderflow.ecommerce.dtos.ProductResponse;
import com.orderflow.ecommerce.entities.Product;
import com.orderflow.ecommerce.repositories.ProductRepository;
import com.orderflow.ecommerce.services.ProductService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

Expand All @@ -16,47 +23,43 @@
public class ProductController implements ProductControllerDocs {

@Autowired
private ProductRepository repository;
private ProductService productService;

@Override
@GetMapping
public ResponseEntity<List<Product>> findAll() {
return ResponseEntity.ok().body(repository.findAll());
public ResponseEntity<Page<ProductResponse>> findAll(
@ModelAttribute ProductFilter filter,
Pageable pageable
) {
return ResponseEntity.ok(productService.findAll(filter, pageable));
}

@Override
@GetMapping(value = "/{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);
public ResponseEntity<ProductResponse> findById(@PathVariable Long id) {
return ResponseEntity.ok(productService.findById(id));
}

@Override
@PostMapping
public ResponseEntity<Product> insert(@Valid @RequestBody Product obj) {
return ResponseEntity.ok().body(repository.save(obj));
public ResponseEntity<ProductResponse> create(@Valid @RequestBody ProductRequest request) {
ProductResponse response = productService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

@Override
@DeleteMapping(value = "/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
repository.deleteById(id);
return ResponseEntity.noContent().build();
@PutMapping(value = "/{id}")
public ResponseEntity<ProductResponse> update(
@PathVariable Long id,
@Valid @RequestBody ProductRequest request
) {
return ResponseEntity.ok(productService.update(request, id));
}

@Override
@PutMapping(value = "/{id}")
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"));

entity.setName(obj.getName());
entity.setDescription(obj.getDescription());
entity.setPrice(obj.getPrice());
entity.setStockQuantity(obj.getStockQuantity());
entity.setCategory(obj.getCategory());

return ResponseEntity.ok().body(repository.save(entity));
@DeleteMapping(value = "/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
productService.delete(id);
return ResponseEntity.noContent().build();
}
}
Loading