diff --git a/src/main/java/ip_2/lab1/APIController.java b/src/main/java/ip_2/lab1/APIController.java deleted file mode 100644 index 8613cbf..0000000 --- a/src/main/java/ip_2/lab1/APIController.java +++ /dev/null @@ -1,44 +0,0 @@ -package ip_2.lab1; - -import org.springframework.web.bind.annotation.*; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - -@RestController -@RequestMapping("/type") -public class APIController { - - private final List types = new ArrayList<>(); - - @GetMapping - public List getTypes() { - return types; - } - - @GetMapping("/{id}") - public TypesDto getTypeById(@PathVariable(name="id") int id) { - return types.get(id); - } - - @PostMapping - public TypesDto postType(@RequestBody TypesDto newType) { - types.add(newType); - return newType; - } - - @PutMapping("/{id}") - public TypesDto putType(@PathVariable(name="id") int id, @RequestBody TypesDto updateType) { - types.remove(id); - types.add(id, updateType); - return updateType; - } - - @DeleteMapping("/{id}") - public TypesDto deleteType(@PathVariable(name="id") int id) { - TypesDto tmp = types.get(id); - types.remove(id); - return tmp; - } -} diff --git a/src/main/java/ip_2/lab1/Lab1Application.java b/src/main/java/ip_2/lab1/Lab1Application.java index 69ec8b0..a95f738 100644 --- a/src/main/java/ip_2/lab1/Lab1Application.java +++ b/src/main/java/ip_2/lab1/Lab1Application.java @@ -1,13 +1,49 @@ package ip_2.lab1; +import ip_2.lab1.items.model.ItemEntity; +import ip_2.lab1.items.service.ItemService; +import ip_2.lab1.types.model.TypeEntity; +import ip_2.lab1.types.service.TypeService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import java.util.Objects; + @SpringBootApplication -public class Lab1Application { +public class Lab1Application implements CommandLineRunner { + private final Logger log = LoggerFactory.getLogger(Lab1Application.class); + + private final TypeService typeService; + private final ItemService itemService; + + public Lab1Application(TypeService typeService, ItemService itemService) { + this.typeService = typeService; + this.itemService = itemService; + } public static void main(String[] args) { SpringApplication.run(Lab1Application.class, args); } + @Override + public void run(String... args) throws Exception { + if (args.length > 0 && Objects.equals("--populate", args[0])) { + log.info("Create default types values"); + final var type1 = typeService.create(new TypeEntity(null, "Асфальт", 2000)); + final var type2 = typeService.create(new TypeEntity(null, "Грунт", 3000)); + final var type3 = typeService.create(new TypeEntity(null, "Асфальт + грунт", 3500)); + + log.info("Create default items values"); + itemService.create(new ItemEntity(null, type1, 49999, 20)); + itemService.create(new ItemEntity(null, type1, 129999, 3)); + itemService.create(new ItemEntity(null, type2, 15450, 30)); + itemService.create(new ItemEntity(null, type2, 69900, 10)); + itemService.create(new ItemEntity(null, type2, 150000, 6)); + itemService.create(new ItemEntity(null, type3, 75000, 6)); + itemService.create(new ItemEntity(null, type3, 67800, 3)); + } + } } diff --git a/src/main/java/ip_2/lab1/TypesDto.java b/src/main/java/ip_2/lab1/TypesDto.java deleted file mode 100644 index fe75801..0000000 --- a/src/main/java/ip_2/lab1/TypesDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package ip_2.lab1; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class TypesDto { - private String name; - - @JsonCreator - public TypesDto( - @JsonProperty(value = "name") String name) { - this.name = name; - } - - public String getName() { - return name; - } -} diff --git a/src/main/java/ip_2/lab1/items/api/ItemController.java b/src/main/java/ip_2/lab1/items/api/ItemController.java new file mode 100644 index 0000000..bf8f6a9 --- /dev/null +++ b/src/main/java/ip_2/lab1/items/api/ItemController.java @@ -0,0 +1,64 @@ +package ip_2.lab1.items.api; + +import ip_2.lab1.core.configuration.Constants; +import ip_2.lab1.items.model.ItemEntity; +import ip_2.lab1.items.service.ItemService; +import ip_2.lab1.types.service.TypeService; +import jakarta.validation.Valid; +import org.modelmapper.ModelMapper; +import org.springframework.web.bind.annotation.*; +import org.yaml.snakeyaml.nodes.CollectionNode; + +import java.util.List; + +@RestController +@RequestMapping(Constants.API_URL + "/item") +public class ItemController { + private final TypeService typeService; + private final ItemService itemService; + private final ModelMapper modelMapper; + + public ItemController(TypeService typeService, ItemService itemService, ModelMapper modelMapper) { + this.itemService = itemService; + this.typeService = typeService; + this.modelMapper = modelMapper; + } + + private ItemDto toDto(ItemEntity entity) { + final ItemDto dto = modelMapper.map(entity, ItemDto.class); + double ben = (entity.getType().getBasePrice() - entity.getPrice()) * entity.getCount(); + dto.setBenefit(ben); + return dto; + } + + private ItemEntity toEntity(ItemDto dto) { + final ItemEntity entity = modelMapper.map(dto, ItemEntity.class); + entity.setType(typeService.get(dto.getTypeId())); + return entity; + } + + @GetMapping + public List getAll(@RequestParam(name = "typeId", defaultValue = "0") Long typeId) { + return itemService.getAll(typeId).stream().map(this::toDto).toList(); + } + + @GetMapping("/{id}") + public ItemDto get(@PathVariable(name = "id") Long id) { + return toDto(itemService.get(id)); + } + + @PostMapping + public ItemDto create(@RequestBody ItemDto dto) { + return toDto(itemService.create(toEntity(dto))); + } + + @PutMapping("/{id}") + public ItemDto update(@PathVariable(name = "id") Long id, @RequestBody ItemDto dto) { + return toDto(itemService.update(id, toEntity(dto))); + } + + @DeleteMapping("/{id}") + public ItemDto delete(@PathVariable(name = "id") Long id) { + return toDto(itemService.delete(id)); + } +} diff --git a/src/main/java/ip_2/lab1/items/api/ItemDto.java b/src/main/java/ip_2/lab1/items/api/ItemDto.java new file mode 100644 index 0000000..8376abc --- /dev/null +++ b/src/main/java/ip_2/lab1/items/api/ItemDto.java @@ -0,0 +1,71 @@ +package ip_2.lab1.items.api; + +import com.fasterxml.jackson.annotation.JsonProperty; +import ip_2.lab1.types.repository.TypeRepository; +import ip_2.lab1.types.service.TypeService; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; + +import java.util.Objects; + +public class ItemDto { + private Long id; + @NotNull + @Min(1) + private Long typeId; + @NotNull + @Min(1) + private Double price; + @NotNull + @Min(1) + private Integer count; + + private Double benefit; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getTypeId() { + return typeId; + } + + public void setTypeId(Long typeId) { + this.typeId = typeId; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public Double getSum() { + return price * count; + } + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public Double getBenefit() { + return benefit; + } + + public void setBenefit(double benefit) { + this.benefit = benefit; + } +} diff --git a/src/main/java/ip_2/lab1/items/model/ItemEntity.java b/src/main/java/ip_2/lab1/items/model/ItemEntity.java new file mode 100644 index 0000000..10991d9 --- /dev/null +++ b/src/main/java/ip_2/lab1/items/model/ItemEntity.java @@ -0,0 +1,61 @@ +package ip_2.lab1.items.model; + +import io.swagger.v3.oas.models.security.SecurityScheme; +import ip_2.lab1.core.model.BaseEntity; +import ip_2.lab1.types.model.TypeEntity; + +import java.util.Objects; + +public class ItemEntity extends BaseEntity { + private TypeEntity type; + private Integer price; + private Integer count; + + public ItemEntity() { + super(); + } + + public ItemEntity(Long id, TypeEntity type, Integer price, Integer count) { + super(id); + this.type = type; + this.price = price; + this.count = count; + } + + public TypeEntity getType() { + return type; + } + public void setType(TypeEntity type) { + this.type = type; + } + + public Integer getPrice() { + return price; + } + public void setPrice(Integer price) { + this.price = price; + } + + public Integer getCount() { + return count; + } + public void setCount(Integer count) { + this.count = count; + } + + @Override + public int hashCode() { return Objects.hash(id, type, price, count); } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + final ItemEntity other = (ItemEntity) obj; + return Objects.equals(other.getId(), id) + && Objects.equals(other.getType(), type) + && Objects.equals(other.getPrice(), price) + && Objects.equals(other.getCount(), count); + } +} diff --git a/src/main/java/ip_2/lab1/items/repository/ItemRepository.java b/src/main/java/ip_2/lab1/items/repository/ItemRepository.java new file mode 100644 index 0000000..4b5eab3 --- /dev/null +++ b/src/main/java/ip_2/lab1/items/repository/ItemRepository.java @@ -0,0 +1,9 @@ +package ip_2.lab1.items.repository; + +import ip_2.lab1.core.repository.MapRepository; +import ip_2.lab1.items.model.ItemEntity; +import org.springframework.stereotype.Repository; + +@Repository +public class ItemRepository extends MapRepository { +} diff --git a/src/main/java/ip_2/lab1/items/service/ItemService.java b/src/main/java/ip_2/lab1/items/service/ItemService.java new file mode 100644 index 0000000..577f302 --- /dev/null +++ b/src/main/java/ip_2/lab1/items/service/ItemService.java @@ -0,0 +1,49 @@ +package ip_2.lab1.items.service; + +import ip_2.lab1.core.error.NotFoundException; +import ip_2.lab1.items.model.ItemEntity; +import ip_2.lab1.items.repository.ItemRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Service +public class ItemService { + private final ItemRepository repository; + + public ItemService(ItemRepository repository) { + this.repository = repository; + } + + public List getAll(Long typeId) { + if (Objects.equals(typeId, 0L)) { + return repository.getAll(); + } + return repository.getAll().stream() + .filter(item -> item.getType().getId().equals(typeId)).toList(); + } + + public ItemEntity get(Long id) { + return Optional.ofNullable(repository.get(id)) + .orElseThrow(() -> new NotFoundException(id)); + } + + public ItemEntity create(ItemEntity entity) { + return repository.create(entity); + } + + public ItemEntity update(Long id, ItemEntity entity) { + final ItemEntity existsEntity = get(id); + existsEntity.setType(entity.getType()); + existsEntity.setPrice(entity.getPrice()); + existsEntity.setCount(entity.getCount()); + return repository.update(existsEntity); + } + + public ItemEntity delete(Long id) { + final ItemEntity existsEntity = get(id); + return repository.delete(existsEntity); + } +} diff --git a/src/main/java/ip_2/lab1/reviews/api/ReviewController.java b/src/main/java/ip_2/lab1/reviews/api/ReviewController.java new file mode 100644 index 0000000..ae30c33 --- /dev/null +++ b/src/main/java/ip_2/lab1/reviews/api/ReviewController.java @@ -0,0 +1,56 @@ +package ip_2.lab1.reviews.api; + +import ip_2.lab1.core.configuration.Constants; +import ip_2.lab1.reviews.model.ReviewEntity; +import ip_2.lab1.reviews.service.ReviewService; +import ip_2.lab1.types.api.TypeDto; +import ip_2.lab1.types.model.TypeEntity; +import ip_2.lab1.types.service.TypeService; +import org.modelmapper.ModelMapper; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(Constants.API_URL + "/review") +public class ReviewController { + private final ReviewService reviewService; + private final ModelMapper modelMapper; + + public ReviewController(ReviewService reviewService, ModelMapper modelMapper) { + this.reviewService = reviewService; + this.modelMapper = modelMapper; + } + + private ReviewDto toDto(ReviewEntity entity) { + return modelMapper.map(entity, ReviewDto.class); + } + private ReviewEntity toEntity(ReviewDto dto) { + return modelMapper.map(dto, ReviewEntity.class); + } + + @GetMapping + public List getAll() { + return reviewService.getAll().stream().map(this::toDto).toList(); + } + + @GetMapping("/{id}") + public ReviewDto get(@PathVariable(name = "id") Long id) { + return toDto(reviewService.get(id)); + } + + @PostMapping + public ReviewDto create(@RequestBody ReviewDto dto) { + return toDto(reviewService.create(toEntity(dto))); + } + + @PutMapping("/{id}") + public ReviewDto update(@PathVariable(name = "id") Long id, @RequestBody ReviewDto dto) { + return toDto(reviewService.update(id, toEntity(dto))); + } + + @DeleteMapping("/{id}") + public ReviewDto delete(@PathVariable(name = "id") Long id) { + return toDto(reviewService.delete(id)); + } +} diff --git a/src/main/java/ip_2/lab1/reviews/api/ReviewDto.java b/src/main/java/ip_2/lab1/reviews/api/ReviewDto.java new file mode 100644 index 0000000..63e144a --- /dev/null +++ b/src/main/java/ip_2/lab1/reviews/api/ReviewDto.java @@ -0,0 +1,32 @@ +package ip_2.lab1.reviews.api; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +public class ReviewDto { + private Long id; + @NotBlank + private String name; + @NotBlank + private String text; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getText() { return text; } + public void setText(String text) { this.text = text; } +} diff --git a/src/main/java/ip_2/lab1/reviews/model/ReviewEntity.java b/src/main/java/ip_2/lab1/reviews/model/ReviewEntity.java new file mode 100644 index 0000000..08b7866 --- /dev/null +++ b/src/main/java/ip_2/lab1/reviews/model/ReviewEntity.java @@ -0,0 +1,50 @@ +package ip_2.lab1.reviews.model; + +import ip_2.lab1.core.model.BaseEntity; +import ip_2.lab1.types.model.TypeEntity; + +import java.util.Objects; + +public class ReviewEntity extends BaseEntity { + private String name; + private String text; + + public ReviewEntity() { + super(); + } + public ReviewEntity(Long id, String name, String text) { + super(id); + this.name = name; + this.text = text; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getText() { + return text; + } + public void setText(String text) { + this.text = text; + } + + @Override + public int hashCode() { + return Objects.hash(id, name, text); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + final ReviewEntity other = (ReviewEntity) obj; + return Objects.equals(other.getId(), id) && Objects.equals(other.getName(), name) + && Objects.equals(other.getText(), text); + } +} diff --git a/src/main/java/ip_2/lab1/reviews/repository/ReviewRepository.java b/src/main/java/ip_2/lab1/reviews/repository/ReviewRepository.java new file mode 100644 index 0000000..b69ed32 --- /dev/null +++ b/src/main/java/ip_2/lab1/reviews/repository/ReviewRepository.java @@ -0,0 +1,9 @@ +package ip_2.lab1.reviews.repository; + +import ip_2.lab1.core.repository.MapRepository; +import ip_2.lab1.reviews.model.ReviewEntity; +import org.springframework.stereotype.Repository; + +@Repository +public class ReviewRepository extends MapRepository { +} diff --git a/src/main/java/ip_2/lab1/reviews/service/ReviewService.java b/src/main/java/ip_2/lab1/reviews/service/ReviewService.java new file mode 100644 index 0000000..341042e --- /dev/null +++ b/src/main/java/ip_2/lab1/reviews/service/ReviewService.java @@ -0,0 +1,44 @@ +package ip_2.lab1.reviews.service; + +import ip_2.lab1.core.error.NotFoundException; +import ip_2.lab1.reviews.model.ReviewEntity; +import ip_2.lab1.reviews.repository.ReviewRepository; +import ip_2.lab1.types.model.TypeEntity; +import ip_2.lab1.types.repository.TypeRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class ReviewService { + private final ReviewRepository repository; + + public ReviewService(ReviewRepository repository) { + this.repository = repository; + } + + public List getAll() { + return repository.getAll(); + } + + public ReviewEntity get(Long id) { + return Optional.ofNullable(repository.get(id)).orElseThrow(() -> new NotFoundException(id)); + } + + public ReviewEntity create(ReviewEntity entity) { + return repository.create(entity); + } + + public ReviewEntity update(Long id, ReviewEntity entity) { + final ReviewEntity existsEntity = get(id); + existsEntity.setName(entity.getName()); + existsEntity.setText(entity.getText()); + return repository.update(existsEntity); + } + + public ReviewEntity delete(Long id) { + final ReviewEntity existsEntity = get(id); + return repository.delete(existsEntity); + } +} diff --git a/src/main/java/ip_2/lab1/types/api/TypeController.java b/src/main/java/ip_2/lab1/types/api/TypeController.java index a4b66a5..3e0b8e3 100644 --- a/src/main/java/ip_2/lab1/types/api/TypeController.java +++ b/src/main/java/ip_2/lab1/types/api/TypeController.java @@ -1,6 +1,5 @@ package ip_2.lab1.types.api; -import ip_2.lab1.TypesDto; import ip_2.lab1.core.configuration.Constants; import ip_2.lab1.types.model.TypeEntity; import ip_2.lab1.types.service.TypeService; @@ -39,7 +38,7 @@ public class TypeController { } @PostMapping - public TypeDto create(@RequestBody @Valid TypeDto dto) { + public TypeDto create(@RequestBody TypeDto dto) { return toDto(typeService.create(toEntity(dto))); } diff --git a/src/main/java/ip_2/lab1/types/api/TypeDto.java b/src/main/java/ip_2/lab1/types/api/TypeDto.java index c6589df..5ec3e1a 100644 --- a/src/main/java/ip_2/lab1/types/api/TypeDto.java +++ b/src/main/java/ip_2/lab1/types/api/TypeDto.java @@ -1,6 +1,7 @@ package ip_2.lab1.types.api; import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.models.security.SecurityScheme; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -11,7 +12,7 @@ public class TypeDto { private String name; @NotNull @Min(1) - private int basePrice; + private Integer basePrice; @JsonProperty(access = JsonProperty.Access.READ_ONLY) public Long getId() { @@ -28,6 +29,6 @@ public class TypeDto { this.name = name; } - public int getBasePrice() { return basePrice; } - public void setBasePrice(int basePrice) { this.basePrice = basePrice; } + public Integer getBasePrice() { return basePrice; } + public void setBasePrice(Integer basePrice) { this.basePrice = basePrice; } } diff --git a/src/main/java/ip_2/lab1/types/model/TypeEntity.java b/src/main/java/ip_2/lab1/types/model/TypeEntity.java index f3cbb32..c5f4a2d 100644 --- a/src/main/java/ip_2/lab1/types/model/TypeEntity.java +++ b/src/main/java/ip_2/lab1/types/model/TypeEntity.java @@ -7,12 +7,12 @@ import java.util.Objects; public class TypeEntity extends BaseEntity { private String name; - private int basePrice; + private Integer basePrice; public TypeEntity() { super(); } - protected TypeEntity(Long id, String name, int basePrice) { + public TypeEntity(Long id, String name, Integer basePrice) { super(id); this.name = name; this.basePrice = basePrice; diff --git a/src/test/java/ip_2/lab1/TypeServiceTests.java b/src/test/java/ip_2/lab1/TypeServiceTests.java new file mode 100644 index 0000000..f9bb9c8 --- /dev/null +++ b/src/test/java/ip_2/lab1/TypeServiceTests.java @@ -0,0 +1,63 @@ +package ip_2.lab1; + +import ip_2.lab1.types.service.TypeService; +import ip_2.lab1.core.error.NotFoundException; +import ip_2.lab1.types.model.TypeEntity; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@TestMethodOrder(OrderAnnotation.class) +class TypeServiceTests { + @Autowired + private TypeService typeService; + + @Test + void getTest() { + Assertions.assertThrows(NotFoundException.class, () -> typeService.get(0L)); + } + + @Test + @Order(1) + void createTest() { + typeService.create(new TypeEntity(null, "Asphalt", 2000)); + typeService.create(new TypeEntity(null, "Grunt", 3000)); + final TypeEntity last = typeService.create(new TypeEntity(null, "Asphalt + grunt", 3500)); + Assertions.assertEquals(3, typeService.getAll().size()); + Assertions.assertEquals(last, typeService.get(3L)); + } + + @Test + @Order(2) + void updateTest() { + final String test1 = "TEST"; + final Integer test2 = 1000; + final TypeEntity entity = typeService.get(3L); + final String oldName = entity.getName(); + final Integer oldPrice = entity.getBasePrice(); + final TypeEntity newEntity = typeService.update(3L, new TypeEntity(1L, test1, test2)); + Assertions.assertEquals(3, typeService.getAll().size()); + Assertions.assertEquals(newEntity, typeService.get(3L)); + Assertions.assertEquals(test1, newEntity.getName()); + Assertions.assertEquals(test2, newEntity.getBasePrice()); + Assertions.assertNotEquals(oldName, newEntity.getName()); + } + + @Test + @Order(3) + void deleteTest() { + typeService.delete(3L); + Assertions.assertEquals(2, typeService.getAll().size()); + final TypeEntity last = typeService.get(2L); + Assertions.assertEquals(2L, last.getId()); + + final TypeEntity newEntity = typeService.create(new TypeEntity(null, "Asphalt + grunt", 3500)); + Assertions.assertEquals(3, typeService.getAll().size()); + Assertions.assertEquals(4L, newEntity.getId()); + } +}