Skip to content

Commit f868738

Browse files
Merge pull request #52 from AnswerConsulting/BENCH-153
BENCH-153 Implement soft deletions
2 parents 660674d + 0f87217 commit f868738

File tree

18 files changed

+184
-91
lines changed

18 files changed

+184
-91
lines changed

init_scripts/schema.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ CREATE TABLE IF NOT EXISTS product (
22
id BIGINT NOT NULL AUTO_INCREMENT,
33
name VARCHAR(255) NOT NULL,
44
description VARCHAR(255) NOT NULL,
5-
available BIT(1) NOT NULL,
5+
retired BIT(1) NOT NULL,
66
price DECIMAL(12,2) NOT NULL,
77

88
PRIMARY KEY (id)
9-
);
9+
);
1010

1111
CREATE TABLE IF NOT EXISTS category (
1212
id BIGINT NOT NULL AUTO_INCREMENT,
1313
name VARCHAR(255),
1414
description VARCHAR(255) NOT NULL,
15+
retired BIT(1) NOT NULL,
1516

1617
PRIMARY KEY (id)
1718
);

src/main/java/com/answerdigital/academy/answerking/controller/CategoryController.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ public ResponseEntity<Category> updateCategory(@Valid @RequestBody final UpdateC
8080
}
8181

8282
@DeleteMapping("/{categoryId}")
83-
public ResponseEntity<HttpStatus> deleteCategory(@PathVariable @NotNull final Long categoryId) {
84-
categoryService.deleteCategoryById(categoryId);
85-
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
83+
public ResponseEntity<Category> retireCategory(@PathVariable @NotNull final Long categoryId) {
84+
return new ResponseEntity<>(categoryService.retireCategory(categoryId), HttpStatus.OK);
8685
}
8786
}

src/main/java/com/answerdigital/academy/answerking/controller/ProductController.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
import org.springframework.http.ResponseEntity;
1010
import org.springframework.validation.Errors;
1111
import org.springframework.validation.annotation.Validated;
12+
import org.springframework.web.bind.annotation.DeleteMapping;
1213
import org.springframework.web.bind.annotation.GetMapping;
14+
import org.springframework.web.bind.annotation.PathVariable;
1315
import org.springframework.web.bind.annotation.PostMapping;
1416
import org.springframework.web.bind.annotation.PutMapping;
15-
import org.springframework.web.bind.annotation.PathVariable;
16-
import org.springframework.web.bind.annotation.RequestMapping;
1717
import org.springframework.web.bind.annotation.RequestBody;
18+
import org.springframework.web.bind.annotation.RequestMapping;
1819
import org.springframework.web.bind.annotation.RestController;
1920

2021
import javax.validation.Valid;
@@ -57,4 +58,9 @@ public ResponseEntity<Product> updateProduct(@PathVariable @NotNull final long i
5758
return new ResponseEntity<>(productService.updateProduct(id, productRequest),
5859
errors.hasErrors() ? HttpStatus.BAD_REQUEST : HttpStatus.OK);
5960
}
61+
62+
@DeleteMapping("/{id}")
63+
public ResponseEntity<Product> retireProduct(@PathVariable @NotNull final long id) {
64+
return new ResponseEntity<>(productService.retireProduct(id), HttpStatus.OK);
65+
}
6066
}

src/main/java/com/answerdigital/academy/answerking/exception/custom/ProductUnavailableException.java renamed to src/main/java/com/answerdigital/academy/answerking/exception/custom/RetirementException.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@
66
import java.util.Collection;
77
import java.util.List;
88

9-
public class ProductUnavailableException extends AnswerKingException {
9+
public class RetirementException extends AnswerKingException {
1010

1111
private static final String TYPE = "https://www.rfc-editor.org/rfc/rfc7231";
1212

13-
private static final String TITLE = "Product Unavailable Exception";
13+
private static final String TITLE = "Retirement Exception";
1414

15-
private static final HttpStatus STATUS = HttpStatus.BAD_REQUEST;
15+
private static final HttpStatus STATUS = HttpStatus.GONE;
1616

1717
private static final String DETAIL = null;
1818

19-
public ProductUnavailableException(final Collection<String> errors) {
19+
public RetirementException(final Collection<String> errors) {
2020
super(TYPE, TITLE, STATUS, DETAIL, errors);
2121
}
2222

23-
public ProductUnavailableException(final String error) {
23+
public RetirementException(final String error) {
2424
this(List.of(error));
2525
}
2626
}

src/main/java/com/answerdigital/academy/answerking/mapper/ProductMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import com.answerdigital.academy.answerking.model.Product;
44
import com.answerdigital.academy.answerking.request.ProductRequest;
55
import org.mapstruct.Mapper;
6+
import org.mapstruct.Mapping;
67
import org.mapstruct.MappingTarget;
78

89
@Mapper(componentModel = "spring")
910
public interface ProductMapper {
11+
@Mapping(target = "retired", constant = "false")
1012
Product addRequestToProduct(ProductRequest productRequest);
1113

1214
Product updateRequestToProduct(@MappingTarget Product product, ProductRequest productRequest);

src/main/java/com/answerdigital/academy/answerking/model/Category.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public class Category {
4444
message = "Category description can only contain letters, numbers, spaces and !?-.,' punctuation")
4545
private String description;
4646

47+
private boolean retired;
48+
4749
@ManyToMany(fetch = FetchType.LAZY)
4850
@JoinTable(
4951
name = "product_category",
@@ -55,6 +57,13 @@ public class Category {
5557
public Category(final AddCategoryRequest categoryRequest) {
5658
this.name = categoryRequest.name();
5759
this.description = categoryRequest.description();
60+
this.retired = false;
61+
}
62+
63+
public Category(final String name, final String description) {
64+
this.name = name;
65+
this.description = description;
66+
this.retired = false;
5867
}
5968

6069
public void addProduct(final Product product) {
@@ -65,11 +74,6 @@ public void removeProduct(final Product product) {
6574
products.remove(product);
6675
}
6776

68-
public Category(final String name, final String description) {
69-
this.name = name;
70-
this.description = description;
71-
}
72-
7377
@Override
7478
public boolean equals(final Object o) {
7579
if (this == o) return true;

src/main/java/com/answerdigital/academy/answerking/model/Product.java

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class Product {
4747
@Column(precision = 12, scale = 2)
4848
private BigDecimal price;
4949

50-
private Boolean available;
50+
private boolean retired;
5151

5252
@JsonIgnore
5353
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "products")
@@ -57,34 +57,24 @@ public class Product {
5757
@JsonIgnore
5858
private Set<LineItem> lineItems = new HashSet<>();
5959

60-
public void setPrice(final BigDecimal price) {
61-
this.price = price;
62-
}
63-
64-
public void setAvailable(final Boolean available) {
65-
this.available = available;
66-
}
67-
6860
public Product(final ProductRequest productRequest){
6961
this.name = productRequest.name();
7062
this.description = productRequest.description();
7163
this.price = productRequest.price();
72-
this.available = productRequest.available();
64+
this.retired = false;
7365
}
7466

75-
public Product(final String name, final String description, final BigDecimal price, final boolean isAvailable) {
67+
public Product(final String name, final String description, final BigDecimal price, final boolean isRetired) {
7668
this.name = name;
7769
this.description = description;
7870
this.price = price;
7971
this.categories = new HashSet<>();
80-
this.available = isAvailable;
72+
this.retired = isRetired;
8173
}
8274

8375
@PreRemove
8476
private void removeProductsFromCategories() {
85-
for (Category category : categories) {
86-
category.removeProduct(this);
87-
}
77+
categories.forEach(category -> category.removeProduct(this));
8878
}
8979

9080
public BigDecimal getPrice() {
@@ -111,7 +101,7 @@ public String toString() {
111101
", name='" + name + '\'' +
112102
", description='" + description + '\'' +
113103
", price=" + price +
114-
", available=" + available +
104+
", retired=" + retired +
115105
'}';
116106
}
117107
}

src/main/java/com/answerdigital/academy/answerking/repository/OrderRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import com.answerdigital.academy.answerking.model.Order;
44
import org.springframework.data.repository.PagingAndSortingRepository;
5+
import org.springframework.stereotype.Repository;
56

67
import java.util.List;
78

9+
@Repository
810
public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
911
List<Order> findAll();
1012
}

src/main/java/com/answerdigital/academy/answerking/request/ProductRequest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ public record ProductRequest(
2222
@Digits(integer = 12, fraction = 2, message = "Product price is invalid")
2323
@DecimalMin(value = "0.0", inclusive = false, message = "Product price is invalid")
2424
@NotNull
25-
BigDecimal price,
26-
@NotNull
27-
boolean available
25+
BigDecimal price
2826
) {
2927
@Builder
3028
public ProductRequest {

src/main/java/com/answerdigital/academy/answerking/service/CategoryService.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.answerdigital.academy.answerking.service;
22

3+
import com.answerdigital.academy.answerking.exception.custom.RetirementException;
34
import com.answerdigital.academy.answerking.exception.generic.ConflictException;
45
import com.answerdigital.academy.answerking.exception.generic.NotFoundException;
56
import com.answerdigital.academy.answerking.mapper.CategoryMapper;
@@ -84,8 +85,12 @@ public Category removeProductFromCategory(final Long categoryId, final Long prod
8485
return categoryRepository.save(category);
8586
}
8687

87-
public void deleteCategoryById(final Long categoryId) {
88-
findById(categoryId);
89-
categoryRepository.deleteById(categoryId);
88+
public Category retireCategory(final Long categoryId) {
89+
final Category category = findById(categoryId);
90+
if(category.isRetired()) {
91+
throw new RetirementException(String.format("The category with ID %d is already retired", categoryId));
92+
}
93+
category.setRetired(true);
94+
return categoryRepository.save(category);
9095
}
9196
}

0 commit comments

Comments
 (0)