diff --git a/app/src/main/java/com/zyzf/coffeepreorder/database/model/Coffee.kt b/app/src/main/java/com/zyzf/coffeepreorder/database/model/Coffee.kt index 584a02b..1ce3b55 100644 --- a/app/src/main/java/com/zyzf/coffeepreorder/database/model/Coffee.kt +++ b/app/src/main/java/com/zyzf/coffeepreorder/database/model/Coffee.kt @@ -21,9 +21,7 @@ data class Coffee( constructor( name: String, cost: Double, - ingredients: String, - cartId: Int?, - count: Int? + ingredients: String ) : this(0, name, cost, ingredients) companion object { diff --git a/backend/build.gradle b/backend/build.gradle index 76dd18f..f86170e 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -14,16 +14,13 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-devtools' - implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'com.h2database:h2' implementation 'org.hibernate.validator:hibernate-validator' - - //implementation 'org.springdoc:springdoc-openapi-ui' + implementation 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeController.java b/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeController.java new file mode 100644 index 0000000..faba5f0 --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeController.java @@ -0,0 +1,45 @@ +package com.kalyshev.yan.coffee.controller; + +import com.kalyshev.yan.WebConfiguration; +import com.kalyshev.yan.coffee.service.CoffeeService; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping(WebConfiguration.REST_API + "/coffee") +public class CoffeeController { + private final CoffeeService coffeeService; + public CoffeeController(CoffeeService coffeeService) { + this.coffeeService = coffeeService; + } + @GetMapping("/{id}") + public CoffeeDto getCoffee(@PathVariable Long id) { + return new CoffeeDto(coffeeService.findCoffee(id)); + } + @GetMapping("/") + public CoffeeResponse getAllCoffees( + @RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo, + @RequestParam(value = "pageSize", defaultValue = "10", required = false) int pageSize, + @RequestParam(value = "sortBy", defaultValue = "id", required = false) String sortBy, + @RequestParam(value = "sortDir", defaultValue = "asc", required = false) String sortDir + ){ + return coffeeService.findAllCoffees(pageNo, pageSize, sortBy, sortDir); + } + @PostMapping("/") + public CoffeeDto createCoffee(@RequestBody @Valid CoffeeDto coffeeDto) { + return new CoffeeDto(coffeeService.addCoffee(coffeeDto.getName(), coffeeDto.getCost(), coffeeDto.getIngredients())); + } + @PutMapping("/{id}") + public CoffeeDto updateCoffee(@PathVariable Long id, + @RequestBody @Valid CoffeeDto coffeeDto) { + return new CoffeeDto(coffeeService.updateCoffee(id, coffeeDto.getName(), coffeeDto.getCost(), coffeeDto.getIngredients())); + } + @DeleteMapping("/{id}") + public CoffeeDto deleteCoffee(@PathVariable Long id) { + return new CoffeeDto(coffeeService.deleteCoffee(id)); + } + @DeleteMapping("/") + public void deleteAllCoffees() { + coffeeService.deleteAllCoffees(); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeDto.java b/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeDto.java new file mode 100644 index 0000000..9a0dbea --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeDto.java @@ -0,0 +1,25 @@ +package com.kalyshev.yan.coffee.controller; + +import com.kalyshev.yan.coffee.model.Coffee; + +public class CoffeeDto { + private Long id; + private String name; + private Double cost; + private String ingredients; + public CoffeeDto() {} + public CoffeeDto(Coffee coffee) { + this.id = coffee.getId(); + this.name = coffee.getName(); + this.cost = coffee.getCost(); + this.ingredients = coffee.getIngredients(); + } + public Long getId() { return this.id; } + public void setId(Long id) { this.id = id; } + public String getName() { return this.name; } + public void setName(String name) { this.name = name; } + public Double getCost() { return this.cost; } + public void setCost(Double cost) { this.cost = cost; } + public String getIngredients() { return this.ingredients; } + public void setIngredients(String ingredients) { this.ingredients = ingredients; } +} diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeResponse.java b/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeResponse.java new file mode 100644 index 0000000..db6b141 --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/controller/CoffeeResponse.java @@ -0,0 +1,19 @@ +package com.kalyshev.yan.coffee.controller; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CoffeeResponse { + private List content; + private int pageNo; + private int pageSize; + private long totalElements; + private int totalPages; + private boolean last; +} \ No newline at end of file diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/model/Coffee.java b/backend/src/main/java/com/kalyshev/yan/coffee/model/Coffee.java new file mode 100644 index 0000000..df9be3e --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/model/Coffee.java @@ -0,0 +1,73 @@ +package com.kalyshev.yan.coffee.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import java.util.Objects; + +@Entity +@Table(name = "coffee") +public class Coffee { + @Id + @GeneratedValue + private Long id; + private String name; + private Double cost; + private String ingredients; + public Coffee() { + } + public Coffee(String name, Double cost, String ingredients) { + this.name = name; + this.cost = cost; + this.ingredients = ingredients; + } + public Long getId() { + return id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public Double getCost() { + return cost; + } + public void setCost(Double cost) { + this.cost = cost; + } + public String getIngredients() { + return ingredients; + } + public void setIngredients(String ingredients) { + this.ingredients = ingredients; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Coffee)) + return false; + Coffee coffee = (Coffee) o; + return Objects.equals(id, coffee.id) && + Objects.equals(this.name, coffee.name) && + Objects.equals(this.cost, coffee.cost) && + Objects.equals(this.ingredients, coffee.ingredients); + } + @Override + public int hashCode() { + return Objects.hash(id); + } + @Override + public String toString() { + return "Coffee{" + + "id=" + id + + ", name='" + name + '\'' + + ", cost='" + cost + '\'' + + ", ingredients='" + ingredients + '\'' + + '}'; + } +} diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/repository/CoffeeNotFoundException.java b/backend/src/main/java/com/kalyshev/yan/coffee/repository/CoffeeNotFoundException.java new file mode 100644 index 0000000..8d7d85b --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/repository/CoffeeNotFoundException.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.coffee.repository; + +public class CoffeeNotFoundException extends RuntimeException { + public CoffeeNotFoundException(Long id) { + super(String.format("Coffee with id [%s] is not found", id)); + } +} diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/repository/CoffeeRepository.java b/backend/src/main/java/com/kalyshev/yan/coffee/repository/CoffeeRepository.java new file mode 100644 index 0000000..b634c65 --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/repository/CoffeeRepository.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.coffee.repository; + +import com.kalyshev.yan.coffee.model.Coffee; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CoffeeRepository extends JpaRepository { +} \ No newline at end of file diff --git a/backend/src/main/java/com/kalyshev/yan/coffee/service/CoffeeService.java b/backend/src/main/java/com/kalyshev/yan/coffee/service/CoffeeService.java new file mode 100644 index 0000000..52b0280 --- /dev/null +++ b/backend/src/main/java/com/kalyshev/yan/coffee/service/CoffeeService.java @@ -0,0 +1,98 @@ +package com.kalyshev.yan.coffee.service; + +import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException; +import com.kalyshev.yan.coffee.controller.CoffeeDto; +import com.kalyshev.yan.coffee.controller.CoffeeResponse; +import com.kalyshev.yan.coffee.model.Coffee; +import com.kalyshev.yan.coffee.repository.CoffeeRepository; +import com.kalyshev.yan.util.validation.ValidatorUtil; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.util.List; +import java.util.Optional; + +@Service +public class CoffeeService { + private final CoffeeRepository coffeeRepository; + private final ValidatorUtil validatorUtil; + public CoffeeService(CoffeeRepository coffeeRepository, + ValidatorUtil validatorUtil) { + this.coffeeRepository = coffeeRepository; + this.validatorUtil = validatorUtil; + } + @Transactional + public Coffee addCoffee(String name, Double cost, String ingredients) { + if (!StringUtils.hasText(name)) { + throw new IllegalArgumentException("Coffee name is null or empty"); + } + if (cost <= 0.0) { + throw new IllegalArgumentException("Coffee cost is null or empty or negative"); + } + final Coffee coffee = new Coffee(name, cost, ingredients); + validatorUtil.validate(coffee); + return coffeeRepository.save(coffee); + } + @Transactional(readOnly = true) + public Coffee findCoffee(Long id) { + final Optional coffee = coffeeRepository.findById(id); + return coffee.orElseThrow(() -> new CabinetNotFoundException(id)); + } + @Transactional(readOnly = true) + public CoffeeResponse findAllCoffees(int pageNo, int pageSize, String sortBy, String sortDir) { + Sort sort = sortDir.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortBy).ascending() + : Sort.by(sortBy).descending(); + + // create Pageable instance + Pageable pageable = PageRequest.of(pageNo, pageSize, sort); + + Page coffees = coffeeRepository.findAll(pageable); + + // get content for page object + List listOfCoffees = coffees.getContent(); + + List content = listOfCoffees.stream() + .map(CoffeeDto::new) + .toList(); + + CoffeeResponse coffeeResponse = new CoffeeResponse(); + coffeeResponse.setContent(content); + coffeeResponse.setPageNo(coffees.getNumber()); + coffeeResponse.setPageSize(coffees.getSize()); + coffeeResponse.setTotalElements(coffees.getTotalElements()); + coffeeResponse.setTotalPages(coffees.getTotalPages()); + coffeeResponse.setLast(coffees.isLast()); + + return coffeeResponse; + } + @Transactional + public Coffee updateCoffee(Long id, String name, Double cost, String ingredients) { + final Coffee currentCoffee = findCoffee(id); + if (StringUtils.hasText(name)) { + currentCoffee.setName(name); + } + if (cost > 0.0) { + currentCoffee.setCost(cost); + } + if (StringUtils.hasText(ingredients)) { + currentCoffee.setIngredients(ingredients); + } + validatorUtil.validate(currentCoffee); + return coffeeRepository.save(currentCoffee); + } + @Transactional + public Coffee deleteCoffee(Long id) { + final Coffee currentCoffee = findCoffee(id); + coffeeRepository.delete(currentCoffee); + return currentCoffee; + } + @Transactional + public void deleteAllCoffees() { + coffeeRepository.deleteAll(); + } +} \ No newline at end of file