lab3
This commit is contained in:
parent
17be9a789d
commit
52fbb51aef
.gitignore
.vscode
build.gradleindex.htmlreadme.mdsrc
main
java/com/example/demo
DemoApplication.java
core
configuration
error
model
repository
items
orders
api
model
repository
service
speaker
api
configuration
domain
service
subscriptions
api
model
repository
service
types
api
model
repository
service
users
api
model
repository
service
usersubscription/model
resources
test
java/com/example/demo
resources
2
.gitignore
vendored
2
.gitignore
vendored
@ -32,3 +32,5 @@ out/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
data.*.db
|
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
@ -1,5 +1,9 @@
|
||||
{
|
||||
"recommendations": [
|
||||
// fronted
|
||||
"AndersEAndersen.html-class-suggestions",
|
||||
"dbaeumer.vscode-eslint",
|
||||
// backend
|
||||
"vscjava.vscode-java-pack",
|
||||
"vmware.vscode-boot-dev-pack",
|
||||
"vscjava.vscode-gradle",
|
||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -6,7 +6,7 @@
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"mainClass": "com.example.demo.DemoApplication",
|
||||
"projectName": "demo-internet_programming_example",
|
||||
"projectName": "lec3",
|
||||
"args": "--populate",
|
||||
"envFile": "${workspaceFolder}/.env"
|
||||
}
|
||||
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,13 +1,14 @@
|
||||
{
|
||||
"editor.tabSize": 4,
|
||||
"editor.detectIndentation": false,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": false,
|
||||
"java.compile.nullAnalysis.mode": "automatic",
|
||||
"java.compile.nullAnalysis.mode": "disabled",
|
||||
"java.configuration.updateBuildConfiguration": "automatic",
|
||||
"[java]": {
|
||||
"editor.pasteAs.enabled": false
|
||||
"editor.pasteAs.enabled": false,
|
||||
},
|
||||
"gradle.nestedProjects": true,
|
||||
"java.saveActions.organizeImports": true,
|
||||
|
16
build.gradle
16
build.gradle
@ -1,12 +1,23 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.2.3'
|
||||
id 'org.springframework.boot' version '3.2.4'
|
||||
id 'io.spring.dependency-management' version '1.1.4'
|
||||
}
|
||||
|
||||
group = 'com.example'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
|
||||
defaultTasks 'bootRun'
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
bootJar {
|
||||
archiveFileName = String.format('%s-%s.jar', rootProject.name, version)
|
||||
}
|
||||
|
||||
assert System.properties['java.specification.version'] == '17' || '21'
|
||||
java {
|
||||
sourceCompatibility = '17'
|
||||
}
|
||||
@ -21,6 +32,9 @@ dependencies {
|
||||
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
|
||||
implementation 'org.modelmapper:modelmapper:3.2.0'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'com.h2database:h2:2.2.224'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
|
62
index.html
62
index.html
@ -1,62 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="out">Push the button</p>
|
||||
<input id="name"/>
|
||||
<br/>
|
||||
<button onclick="get()">Get</button>
|
||||
<br/>
|
||||
<button onclick="getTest()">Get Test</button>
|
||||
<br/>
|
||||
<button onclick="post()">Post</button>
|
||||
<br/>
|
||||
<button onclick="put()">Put</button>
|
||||
</body>
|
||||
<script>
|
||||
const url = "http://localhost:8080/api";
|
||||
const out = document.getElementById("out");
|
||||
const name = document.getElementById("name");
|
||||
const get = async () => {
|
||||
const res = await fetch(`${url}?name=${name.value}`);
|
||||
const text = await res.text();
|
||||
out.innerText = text;
|
||||
}
|
||||
const getTest = async () => {
|
||||
const res = await fetch(`${url}/test`);
|
||||
const text = await res.text();
|
||||
out.innerText = text;
|
||||
}
|
||||
const post = async () => {
|
||||
if (!name.value) {
|
||||
alert("Name is required");
|
||||
return;
|
||||
}
|
||||
const res = await fetch(url, {
|
||||
method: 'post',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: name.value
|
||||
});
|
||||
const text = await res.text();
|
||||
out.innerText = text;
|
||||
}
|
||||
const put = async () => {
|
||||
if (!name.value) {
|
||||
alert("Name is required");
|
||||
return;
|
||||
}
|
||||
const res = await fetch(`${url}/${name.value}`, {
|
||||
method: 'put',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: name.value
|
||||
});
|
||||
// JSON.stringify()
|
||||
const text = await res.text();
|
||||
out.innerText = text;
|
||||
}
|
||||
</script>
|
||||
</html>
|
18
readme.md
Normal file
18
readme.md
Normal file
@ -0,0 +1,18 @@
|
||||
Swagger UI: \
|
||||
http://localhost:8080/swagger-ui/index.html
|
||||
|
||||
H2 Console: \
|
||||
http://localhost:8080/h2-console
|
||||
|
||||
JDBC URL: jdbc:h2:file:./data \
|
||||
User Name: sa \
|
||||
Password: password
|
||||
|
||||
Почитать:
|
||||
|
||||
- Односторонние и двусторонние связи https://www.baeldung.com/jpa-hibernate-associations
|
||||
- Getters и Setters для двусторонних связей https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Getters_and_Setters
|
||||
- Многие-ко-многим с доп. атрибутами https://thorben-janssen.com/hibernate-tip-many-to-many-association-with-additional-attributes/
|
||||
- Многие-ко-многим с доп. атрибутами https://www.baeldung.com/jpa-many-to-many
|
||||
- Каскадное удаление сущностей со связями многие-ко-многим https://www.baeldung.com/jpa-remove-entity-many-to-many
|
||||
- Выбор типа коллекции для отношений вида ко-многим в JPA https://thorben-janssen.com/association-mappings-bag-list-set/
|
@ -1,5 +1,6 @@
|
||||
package com.example.demo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -8,21 +9,33 @@ import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import com.example.demo.items.model.ItemEntity;
|
||||
import com.example.demo.items.service.ItemService;
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.service.OrderService;
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.subscriptions.service.SubscriptionService;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
import com.example.demo.types.service.TypeService;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.service.UserService;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DemoApplication implements CommandLineRunner {
|
||||
private final Logger log = LoggerFactory.getLogger(DemoApplication.class);
|
||||
|
||||
private final TypeService typeService;
|
||||
private final ItemService itemService;
|
||||
private final SubscriptionService subscriptionService;
|
||||
private final UserService userService;
|
||||
private final OrderService orderService;
|
||||
|
||||
public DemoApplication(TypeService typeService, ItemService itemService) {
|
||||
public DemoApplication(
|
||||
TypeService typeService,
|
||||
SubscriptionService subscriptionService,
|
||||
UserService userService,
|
||||
OrderService orderService) {
|
||||
this.typeService = typeService;
|
||||
this.itemService = itemService;
|
||||
this.subscriptionService = subscriptionService;
|
||||
this.userService = userService;
|
||||
this.orderService = orderService;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@ -32,19 +45,30 @@ public class DemoApplication implements CommandLineRunner {
|
||||
@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, "Ноутбук"));
|
||||
final var type2 = typeService.create(new TypeEntity(null, "Телефон"));
|
||||
final var type3 = typeService.create(new TypeEntity(null, "Игровая приставка"));
|
||||
log.info("Create default type values");
|
||||
final var type1 = typeService.create(new TypeEntity("Ноутбук"));
|
||||
final var type2 = typeService.create(new TypeEntity("Телефон"));
|
||||
final var type3 = typeService.create(new TypeEntity("Игровая приставка"));
|
||||
|
||||
log.info("Create default items values");
|
||||
itemService.create(new ItemEntity(null, type1, 49999.00, 20));
|
||||
itemService.create(new ItemEntity(null, type1, 129999.00, 3));
|
||||
itemService.create(new ItemEntity(null, type2, 15450.50, 30));
|
||||
itemService.create(new ItemEntity(null, type2, 69900.50, 10));
|
||||
itemService.create(new ItemEntity(null, type2, 150000.00, 6));
|
||||
itemService.create(new ItemEntity(null, type3, 75000.00, 6));
|
||||
itemService.create(new ItemEntity(null, type3, 67800.00, 3));
|
||||
log.info("Create default subscription values");
|
||||
subscriptionService.create(new SubscriptionEntity("Подписка 1"));
|
||||
subscriptionService.create(new SubscriptionEntity("Подписка 2"));
|
||||
subscriptionService.create(new SubscriptionEntity("Подписка 3"));
|
||||
|
||||
log.info("Create default user values");
|
||||
final var user1 = userService.create(new UserEntity("user1"));
|
||||
userService.create(new UserEntity("user2"));
|
||||
|
||||
log.info("Create default order values");
|
||||
final var orders = List.of(
|
||||
new OrderEntity(type1, 49999.00, 20),
|
||||
new OrderEntity(type1, 129999.00, 3),
|
||||
new OrderEntity(type2, 15450.50, 30),
|
||||
new OrderEntity(type2, 69900.50, 10),
|
||||
new OrderEntity(type2, 150000.00, 6),
|
||||
new OrderEntity(type3, 75000.00, 6),
|
||||
new OrderEntity(type3, 67800.00, 3));
|
||||
orders.forEach(order -> orderService.create(user1.getId(), order));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.example.demo.core.configuration;
|
||||
|
||||
public class Constants {
|
||||
public static final String SEQUENCE_NAME = "hibernate_sequence";
|
||||
|
||||
public static final String API_URL = "/api/1.0";
|
||||
|
||||
private Constants() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.example.demo.core.error;
|
||||
|
||||
public class NotFoundException extends RuntimeException {
|
||||
public NotFoundException(Long id) {
|
||||
super(String.format("Entity with id [%s] is not found or not exists", id));
|
||||
public <T> NotFoundException(Class<T> clazz, Long id) {
|
||||
super(String.format("%s with id [%s] is not found or not exists", clazz.getSimpleName(), id));
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,23 @@
|
||||
package com.example.demo.core.model;
|
||||
|
||||
import com.example.demo.core.configuration.Constants;
|
||||
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = Constants.SEQUENCE_NAME)
|
||||
@SequenceGenerator(name = Constants.SEQUENCE_NAME, sequenceName = Constants.SEQUENCE_NAME, allocationSize = 1)
|
||||
protected Long id;
|
||||
|
||||
protected BaseEntity() {
|
||||
}
|
||||
|
||||
protected BaseEntity(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
package com.example.demo.core.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CommonRepository<E, T> {
|
||||
List<E> getAll();
|
||||
|
||||
E get(T id);
|
||||
|
||||
E create(E entity);
|
||||
|
||||
E update(E entity);
|
||||
|
||||
E delete(E entity);
|
||||
|
||||
void deleteAll();
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package com.example.demo.core.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.example.demo.core.model.BaseEntity;
|
||||
|
||||
public abstract class MapRepository<E extends BaseEntity> implements CommonRepository<E, Long> {
|
||||
private final Map<Long, E> entities = new TreeMap<>();
|
||||
private Long lastId = 0L;
|
||||
|
||||
protected MapRepository() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> getAll() {
|
||||
return entities.values().stream().toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(Long id) {
|
||||
return entities.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E create(E entity) {
|
||||
lastId++;
|
||||
entity.setId(lastId);
|
||||
entities.put(lastId, entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E update(E entity) {
|
||||
if (get(entity.getId()) == null) {
|
||||
return null;
|
||||
}
|
||||
entities.put(entity.getId(), entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E delete(E entity) {
|
||||
if (get(entity.getId()) == null) {
|
||||
return null;
|
||||
}
|
||||
entities.remove(entity.getId());
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
lastId = 0L;
|
||||
entities.clear();
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package com.example.demo.items.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.core.configuration.Constants;
|
||||
import com.example.demo.items.model.ItemEntity;
|
||||
import com.example.demo.items.service.ItemService;
|
||||
import com.example.demo.types.service.TypeService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(Constants.API_URL + "/item")
|
||||
public class ItemController {
|
||||
private final ItemService itemService;
|
||||
private final TypeService typeService;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public ItemController(ItemService itemService, TypeService typeService, ModelMapper modelMapper) {
|
||||
this.itemService = itemService;
|
||||
this.typeService = typeService;
|
||||
this.modelMapper = modelMapper;
|
||||
}
|
||||
|
||||
private ItemDto toDto(ItemEntity entity) {
|
||||
return modelMapper.map(entity, ItemDto.class);
|
||||
}
|
||||
|
||||
private ItemEntity toEntity(ItemDto dto) {
|
||||
final ItemEntity entity = modelMapper.map(dto, ItemEntity.class);
|
||||
entity.setType(typeService.get(dto.getTypeId()));
|
||||
return entity;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<ItemDto> 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 @Valid 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));
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.example.demo.items.repository;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.example.demo.core.repository.MapRepository;
|
||||
import com.example.demo.items.model.ItemEntity;
|
||||
|
||||
@Repository
|
||||
public class ItemRepository extends MapRepository<ItemEntity> {
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.example.demo.items.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.example.demo.core.error.NotFoundException;
|
||||
import com.example.demo.items.model.ItemEntity;
|
||||
import com.example.demo.items.repository.ItemRepository;
|
||||
|
||||
@Service
|
||||
public class ItemService {
|
||||
private final ItemRepository repository;
|
||||
|
||||
public ItemService(ItemRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public List<ItemEntity> 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.example.demo.orders.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.core.configuration.Constants;
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.model.OrderGrouped;
|
||||
import com.example.demo.orders.service.OrderService;
|
||||
import com.example.demo.types.service.TypeService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(Constants.API_URL + "/user/{user}/order")
|
||||
public class OrderController {
|
||||
private final OrderService orderService;
|
||||
private final TypeService typeService;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public OrderController(OrderService orderService, TypeService typeService, ModelMapper modelMapper) {
|
||||
this.orderService = orderService;
|
||||
this.typeService = typeService;
|
||||
this.modelMapper = modelMapper;
|
||||
}
|
||||
|
||||
private OrderDto toDto(OrderEntity entity) {
|
||||
return modelMapper.map(entity, OrderDto.class);
|
||||
}
|
||||
|
||||
private OrderEntity toEntity(OrderDto dto) {
|
||||
final OrderEntity entity = modelMapper.map(dto, OrderEntity.class);
|
||||
entity.setType(typeService.get(dto.getTypeId()));
|
||||
return entity;
|
||||
}
|
||||
|
||||
private OrderGroupedDto toGroupedDto(OrderGrouped entity) {
|
||||
return modelMapper.map(entity, OrderGroupedDto.class);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<OrderDto> getAll(
|
||||
@PathVariable(name = "user") Long userId,
|
||||
@RequestParam(name = "typeId", defaultValue = "0") Long typeId) {
|
||||
return orderService.getAll(userId, typeId).stream()
|
||||
.map(this::toDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public OrderDto get(
|
||||
@PathVariable(name = "user") Long userId,
|
||||
@PathVariable(name = "id") Long id) {
|
||||
return toDto(orderService.get(userId, id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public OrderDto create(
|
||||
@PathVariable(name = "user") Long userId,
|
||||
@RequestBody @Valid OrderDto dto) {
|
||||
return toDto(orderService.create(userId, toEntity(dto)));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public OrderDto update(
|
||||
@PathVariable(name = "user") Long userId,
|
||||
@PathVariable(name = "id") Long id,
|
||||
@RequestBody @Valid OrderDto dto) {
|
||||
return toDto(orderService.update(userId, id, toEntity(dto)));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public OrderDto delete(
|
||||
@PathVariable(name = "user") Long userId,
|
||||
@PathVariable(name = "id") Long id) {
|
||||
return toDto(orderService.delete(userId, id));
|
||||
}
|
||||
|
||||
@GetMapping("/total")
|
||||
public List<OrderGroupedDto> getMethodName(@PathVariable(name = "user") Long userId) {
|
||||
return orderService.getTotal(userId).stream()
|
||||
.map(this::toGroupedDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package com.example.demo.items.api;
|
||||
package com.example.demo.orders.api;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
public class ItemDto {
|
||||
public class OrderDto {
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private Long id;
|
||||
@NotNull
|
@ -0,0 +1,31 @@
|
||||
package com.example.demo.orders.api;
|
||||
|
||||
public class OrderGroupedDto {
|
||||
private Long typeId;
|
||||
private Long totalPrice;
|
||||
private Integer totalCount;
|
||||
|
||||
public Long getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public void setTypeId(Long typeId) {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
public Long getTotalPrice() {
|
||||
return totalPrice;
|
||||
}
|
||||
|
||||
public void setTotalPrice(Long totalPrice) {
|
||||
this.totalPrice = totalPrice;
|
||||
}
|
||||
|
||||
public Integer getTotalCount() {
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
public void setTotalCount(Integer totalCount) {
|
||||
this.totalCount = totalCount;
|
||||
}
|
||||
}
|
@ -1,21 +1,35 @@
|
||||
package com.example.demo.items.model;
|
||||
package com.example.demo.orders.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.example.demo.core.model.BaseEntity;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
|
||||
public class ItemEntity extends BaseEntity {
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "orders")
|
||||
public class OrderEntity extends BaseEntity {
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "typeId", nullable = false)
|
||||
private TypeEntity type;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "userId", nullable = false)
|
||||
private UserEntity user;
|
||||
@Column(nullable = false)
|
||||
private Double price;
|
||||
@Column(nullable = false)
|
||||
private Integer count;
|
||||
|
||||
public ItemEntity() {
|
||||
super();
|
||||
public OrderEntity() {
|
||||
}
|
||||
|
||||
public ItemEntity(Long id, TypeEntity type, Double price, Integer count) {
|
||||
super(id);
|
||||
public OrderEntity(TypeEntity type, Double price, Integer count) {
|
||||
this.type = type;
|
||||
this.price = price;
|
||||
this.count = count;
|
||||
@ -29,6 +43,17 @@ public class ItemEntity extends BaseEntity {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserEntity user) {
|
||||
this.user = user;
|
||||
if (!user.getOrders().contains(this)) {
|
||||
user.getOrders().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
@ -47,7 +72,7 @@ public class ItemEntity extends BaseEntity {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, type, price, count);
|
||||
return Objects.hash(id, type, user.getId(), price, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -56,9 +81,10 @@ public class ItemEntity extends BaseEntity {
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
final ItemEntity other = (ItemEntity) obj;
|
||||
final OrderEntity other = (OrderEntity) obj;
|
||||
return Objects.equals(other.getId(), id)
|
||||
&& Objects.equals(other.getType(), type)
|
||||
&& Objects.equals(other.getUser().getId(), user.getId())
|
||||
&& Objects.equals(other.getPrice(), price)
|
||||
&& Objects.equals(other.getCount(), count);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.example.demo.orders.model;
|
||||
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
|
||||
public interface OrderGrouped {
|
||||
TypeEntity getType();
|
||||
|
||||
double getTotalPrice();
|
||||
|
||||
int getTotalCount();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.example.demo.orders.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.model.OrderGrouped;
|
||||
|
||||
public interface OrderRepository extends CrudRepository<OrderEntity, Long> {
|
||||
Optional<OrderEntity> findOneByUserIdAndId(long userId, long id);
|
||||
|
||||
List<OrderEntity> findByUserId(long userId);
|
||||
|
||||
List<OrderEntity> findByUserIdAndTypeId(long userId, long typeId);
|
||||
|
||||
// select
|
||||
// tpe.name,
|
||||
// coalesce(sum(order.price), 0),
|
||||
// coalesce(sum(order.count), 0)
|
||||
// from types as tpe
|
||||
// left join orders as order on tpe.id = order.type_id and order.user_id = ?
|
||||
// group by tpe.name order by tpe.id
|
||||
@Query("select "
|
||||
+ "t as type, "
|
||||
+ "coalesce(sum(o.price), 0) as totalPrice, "
|
||||
+ "coalesce(sum(o.count), 0) as totalCount "
|
||||
+ "from TypeEntity t left join OrderEntity o on o.type = t and o.user.id = ?1 "
|
||||
+ "group by t order by t.id")
|
||||
List<OrderGrouped> getOrdersTotalByType(long userId);
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.example.demo.orders.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.example.demo.core.error.NotFoundException;
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.model.OrderGrouped;
|
||||
import com.example.demo.orders.repository.OrderRepository;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.service.UserService;
|
||||
|
||||
@Service
|
||||
public class OrderService {
|
||||
private final OrderRepository repository;
|
||||
private final UserService userService;
|
||||
|
||||
public OrderService(OrderRepository repository, UserService userService) {
|
||||
this.repository = repository;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<OrderEntity> getAll(long userId, long typeId) {
|
||||
userService.get(userId);
|
||||
if (typeId <= 0L) {
|
||||
return repository.findByUserId(userId);
|
||||
} else {
|
||||
return repository.findByUserIdAndTypeId(userId, typeId);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public OrderEntity get(long userId, long id) {
|
||||
userService.get(userId);
|
||||
return repository.findOneByUserIdAndId(userId, id)
|
||||
.orElseThrow(() -> new NotFoundException(OrderEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OrderEntity create(long userId, OrderEntity entity) {
|
||||
if (entity == null) {
|
||||
throw new IllegalArgumentException("Entity is null");
|
||||
}
|
||||
final UserEntity existsUser = userService.get(userId);
|
||||
entity.setUser(existsUser);
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OrderEntity update(long userId, long id, OrderEntity entity) {
|
||||
userService.get(userId);
|
||||
final OrderEntity existsEntity = get(userId, id);
|
||||
existsEntity.setType(entity.getType());
|
||||
existsEntity.setPrice(entity.getPrice());
|
||||
existsEntity.setCount(entity.getCount());
|
||||
return repository.save(existsEntity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OrderEntity delete(long userId, long id) {
|
||||
userService.get(userId);
|
||||
final OrderEntity existsEntity = get(userId, id);
|
||||
repository.delete(existsEntity);
|
||||
return existsEntity;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<OrderGrouped> getTotal(long userId) {
|
||||
userService.get(userId);
|
||||
return repository.getOrdersTotalByType(userId);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package com.example.demo.speaker.api;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.speaker.service.SpeakerService;
|
||||
|
||||
@RestController
|
||||
public class SpeakerController {
|
||||
private final SpeakerService speakerService;
|
||||
|
||||
public SpeakerController(SpeakerService speakerService) {
|
||||
this.speakerService = speakerService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String hello(
|
||||
@RequestParam(value = "name", defaultValue = "Мир") String name,
|
||||
@RequestParam(value = "lang", defaultValue = "ru") String lang) {
|
||||
return speakerService.say(name, lang);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.example.demo.speaker.configuration;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.example.demo.speaker.domain.Speaker;
|
||||
import com.example.demo.speaker.domain.SpeakerEng;
|
||||
import com.example.demo.speaker.domain.SpeakerRus;
|
||||
|
||||
@Configuration
|
||||
public class SpeakerConfiguration {
|
||||
private final Logger log = LoggerFactory.getLogger(SpeakerConfiguration.class);
|
||||
|
||||
@Bean(value = "ru", initMethod = "init", destroyMethod = "destroy")
|
||||
public SpeakerRus createRusSpeaker() {
|
||||
log.info("Call createRusSpeaker()");
|
||||
return new SpeakerRus();
|
||||
}
|
||||
|
||||
@Bean(value = "en")
|
||||
public Speaker createEngSpeaker() {
|
||||
log.info("Call createEngSpeaker()");
|
||||
return new SpeakerEng();
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.example.demo.speaker.domain;
|
||||
|
||||
public interface Speaker {
|
||||
String say();
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.example.demo.speaker.domain;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
|
||||
@Component(value = "de")
|
||||
public class SpeakerDeu implements Speaker {
|
||||
private final Logger log = LoggerFactory.getLogger(SpeakerDeu.class);
|
||||
|
||||
@Override
|
||||
public String say() {
|
||||
return "Hallo";
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.info("SpeakerDeu.init()");
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
log.info("SpeakerDeu.destroy()");
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.example.demo.speaker.domain;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
public class SpeakerEng implements Speaker, InitializingBean, DisposableBean {
|
||||
private final Logger log = LoggerFactory.getLogger(SpeakerEng.class);
|
||||
|
||||
@Override
|
||||
public String say() {
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
log.info("SpeakerEng.afterPropertiesSet()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
log.info("SpeakerEng.destroy()");
|
||||
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package com.example.demo.speaker.domain;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SpeakerRus implements Speaker {
|
||||
private final Logger log = LoggerFactory.getLogger(SpeakerRus.class);
|
||||
|
||||
@Override
|
||||
public String say() {
|
||||
return "Привет";
|
||||
}
|
||||
|
||||
public void init() {
|
||||
log.info("SpeakerRus.init()");
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
log.info("SpeakerRus.destroy()");
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package com.example.demo.speaker.service;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.example.demo.speaker.domain.Speaker;
|
||||
|
||||
@Service
|
||||
public class SpeakerService {
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public SpeakerService(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public String say(String name, String lang) {
|
||||
final Speaker speaker = (Speaker) applicationContext.getBean(lang);
|
||||
return String.format("%s, %s!", speaker.say(), name);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.example.demo.subscriptions.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.core.configuration.Constants;
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.subscriptions.service.SubscriptionService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(Constants.API_URL + "/subsciption")
|
||||
public class SubscriptionController {
|
||||
private final SubscriptionService subscriptionService;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public SubscriptionController(SubscriptionService subscriptionService, ModelMapper modelMapper) {
|
||||
this.subscriptionService = subscriptionService;
|
||||
this.modelMapper = modelMapper;
|
||||
}
|
||||
|
||||
private SubscriptionDto toDto(SubscriptionEntity entity) {
|
||||
return modelMapper.map(entity, SubscriptionDto.class);
|
||||
}
|
||||
|
||||
private SubscriptionEntity toEntity(SubscriptionDto dto) {
|
||||
return modelMapper.map(dto, SubscriptionEntity.class);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<SubscriptionDto> getAll() {
|
||||
return subscriptionService.getAll().stream()
|
||||
.map(this::toDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public SubscriptionDto get(@PathVariable(name = "id") Long id) {
|
||||
return toDto(subscriptionService.get(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public SubscriptionDto create(@RequestBody @Valid SubscriptionDto dto) {
|
||||
return toDto(subscriptionService.create(toEntity(dto)));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public SubscriptionDto update(
|
||||
@PathVariable(name = "id") Long id,
|
||||
@RequestBody @Valid SubscriptionDto dto) {
|
||||
return toDto(subscriptionService.update(id, toEntity(dto)));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public SubscriptionDto delete(@PathVariable(name = "id") Long id) {
|
||||
return toDto(subscriptionService.delete(id));
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.example.demo.subscriptions.api;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class SubscriptionDto {
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private Long id;
|
||||
@NotBlank
|
||||
@Size(min = 5, max = 50)
|
||||
private String name;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.example.demo.subscriptions.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.example.demo.core.model.BaseEntity;
|
||||
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OrderBy;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "subscriptions")
|
||||
public class SubscriptionEntity extends BaseEntity {
|
||||
@Column(nullable = false, unique = true, length = 50)
|
||||
private String name;
|
||||
@OneToMany(mappedBy = "subscription")
|
||||
@OrderBy("id ASC")
|
||||
private Set<UserSubscriptionEntity> userSubscriptions = new HashSet<>();
|
||||
|
||||
public SubscriptionEntity() {
|
||||
}
|
||||
|
||||
public SubscriptionEntity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<UserSubscriptionEntity> getUserSubscriptions() {
|
||||
return userSubscriptions;
|
||||
}
|
||||
|
||||
public void addUser(UserSubscriptionEntity userSubscription) {
|
||||
if (userSubscription.getSubscription() != this) {
|
||||
userSubscription.setSubscription(this);
|
||||
}
|
||||
userSubscriptions.add(userSubscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name, userSubscriptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
SubscriptionEntity other = (SubscriptionEntity) obj;
|
||||
return Objects.equals(id, other.id)
|
||||
&& Objects.equals(name, other.name)
|
||||
&& Objects.equals(userSubscriptions, other.userSubscriptions);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.example.demo.subscriptions.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
|
||||
public interface SubscriptionRepository extends CrudRepository<SubscriptionEntity, Long> {
|
||||
Optional<SubscriptionEntity> findByNameIgnoreCase(String name);
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.example.demo.subscriptions.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.example.demo.core.error.NotFoundException;
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.subscriptions.repository.SubscriptionRepository;
|
||||
|
||||
@Service
|
||||
public class SubscriptionService {
|
||||
private final SubscriptionRepository repository;
|
||||
|
||||
public SubscriptionService(SubscriptionRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
private void checkName(String name) {
|
||||
if (repository.findByNameIgnoreCase(name).isPresent()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Type with name %s is already exists", name));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<SubscriptionEntity> getAll() {
|
||||
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public SubscriptionEntity get(long id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new NotFoundException(SubscriptionEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public SubscriptionEntity create(SubscriptionEntity entity) {
|
||||
if (entity == null) {
|
||||
throw new IllegalArgumentException("Entity is null");
|
||||
}
|
||||
checkName(entity.getName());
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public SubscriptionEntity update(Long id, SubscriptionEntity entity) {
|
||||
final SubscriptionEntity existsEntity = get(id);
|
||||
checkName(entity.getName());
|
||||
existsEntity.setName(entity.getName());
|
||||
return repository.save(existsEntity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public SubscriptionEntity delete(Long id) {
|
||||
final SubscriptionEntity existsEntity = get(id);
|
||||
repository.delete(existsEntity);
|
||||
return existsEntity;
|
||||
}
|
||||
|
||||
}
|
@ -39,7 +39,9 @@ public class TypeController {
|
||||
|
||||
@GetMapping
|
||||
public List<TypeDto> getAll() {
|
||||
return typeService.getAll().stream().map(this::toDto).toList();
|
||||
return typeService.getAll().stream()
|
||||
.map(this::toDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@ -53,7 +55,9 @@ public class TypeController {
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public TypeDto update(@PathVariable(name = "id") Long id, @RequestBody TypeDto dto) {
|
||||
public TypeDto update(
|
||||
@PathVariable(name = "id") Long id,
|
||||
@RequestBody @Valid TypeDto dto) {
|
||||
return toDto(typeService.update(id, toEntity(dto)));
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,13 @@ package com.example.demo.types.api;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class TypeDto {
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private Long id;
|
||||
@NotBlank
|
||||
@Size(min = 5, max = 50)
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
|
@ -4,15 +4,20 @@ import java.util.Objects;
|
||||
|
||||
import com.example.demo.core.model.BaseEntity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "types")
|
||||
public class TypeEntity extends BaseEntity {
|
||||
@Column(nullable = false, unique = true, length = 50)
|
||||
private String name;
|
||||
|
||||
public TypeEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TypeEntity(Long id, String name) {
|
||||
super(id);
|
||||
public TypeEntity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
package com.example.demo.types.repository;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import com.example.demo.core.repository.MapRepository;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
|
||||
@Repository
|
||||
public class TypeRepository extends MapRepository<TypeEntity> {
|
||||
public interface TypeRepository extends CrudRepository<TypeEntity, Long> {
|
||||
Optional<TypeEntity> findByNameIgnoreCase(String name);
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package com.example.demo.types.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.example.demo.core.error.NotFoundException;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
@ -17,27 +18,45 @@ public class TypeService {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
private void checkName(String name) {
|
||||
if (repository.findByNameIgnoreCase(name).isPresent()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Type with name %s is already exists", name));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<TypeEntity> getAll() {
|
||||
return repository.getAll();
|
||||
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
|
||||
}
|
||||
|
||||
public TypeEntity get(Long id) {
|
||||
return Optional.ofNullable(repository.get(id))
|
||||
.orElseThrow(() -> new NotFoundException(id));
|
||||
@Transactional(readOnly = true)
|
||||
public TypeEntity get(long id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new NotFoundException(TypeEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TypeEntity create(TypeEntity entity) {
|
||||
return repository.create(entity);
|
||||
if (entity == null) {
|
||||
throw new IllegalArgumentException("Entity is null");
|
||||
}
|
||||
checkName(entity.getName());
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TypeEntity update(Long id, TypeEntity entity) {
|
||||
final TypeEntity existsEntity = get(id);
|
||||
checkName(entity.getName());
|
||||
existsEntity.setName(entity.getName());
|
||||
return repository.update(existsEntity);
|
||||
return repository.save(existsEntity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public TypeEntity delete(Long id) {
|
||||
final TypeEntity existsEntity = get(id);
|
||||
return repository.delete(existsEntity);
|
||||
repository.delete(existsEntity);
|
||||
return existsEntity;
|
||||
}
|
||||
}
|
||||
|
107
src/main/java/com/example/demo/users/api/UserController.java
Normal file
107
src/main/java/com/example/demo/users/api/UserController.java
Normal file
@ -0,0 +1,107 @@
|
||||
package com.example.demo.users.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.core.configuration.Constants;
|
||||
import com.example.demo.subscriptions.api.SubscriptionDto;
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.service.UserService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(Constants.API_URL + "/user")
|
||||
public class UserController {
|
||||
private final UserService userService;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public UserController(UserService userService, ModelMapper modelMapper) {
|
||||
this.userService = userService;
|
||||
this.modelMapper = modelMapper;
|
||||
}
|
||||
|
||||
private UserDto toDto(UserEntity entity) {
|
||||
return modelMapper.map(entity, UserDto.class);
|
||||
}
|
||||
|
||||
private SubscriptionDto toSubscriptionDto(SubscriptionEntity entity) {
|
||||
return modelMapper.map(entity, SubscriptionDto.class);
|
||||
}
|
||||
|
||||
private UserEntity toEntity(UserDto dto) {
|
||||
return modelMapper.map(dto, UserEntity.class);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<UserDto> getAll() {
|
||||
return userService.getAll().stream()
|
||||
.map(this::toDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public UserDto get(@PathVariable(name = "id") Long id) {
|
||||
return toDto(userService.get(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public UserDto create(@RequestBody @Valid UserDto dto) {
|
||||
return toDto(userService.create(toEntity(dto)));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public UserDto update(
|
||||
@PathVariable(name = "id") Long id,
|
||||
@RequestBody @Valid UserDto dto) {
|
||||
return toDto(userService.update(id, toEntity(dto)));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public UserDto delete(@PathVariable(name = "id") Long id) {
|
||||
return toDto(userService.delete(id));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/subscription")
|
||||
public List<SubscriptionDto> getUserSubscriptions(@PathVariable(name = "id") Long id) {
|
||||
return userService.getUserSubscriptions(id).stream()
|
||||
.map(this::toSubscriptionDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/subscription")
|
||||
public List<SubscriptionDto> enableUserSubscriptions(
|
||||
@PathVariable(name = "id") Long id,
|
||||
@RequestParam(name = "subscriptions", defaultValue = "") List<Long> subscriptionsIds) {
|
||||
return userService.enableUserSubscriptions(id, subscriptionsIds).stream()
|
||||
.map(this::toSubscriptionDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}/subscription")
|
||||
public List<SubscriptionDto> disableUserSubscriptions(
|
||||
@PathVariable(name = "id") Long id,
|
||||
@RequestParam(name = "subscriptions", defaultValue = "") List<Long> subscriptionsIds) {
|
||||
return userService.disableUserSubscriptions(id, subscriptionsIds).stream()
|
||||
.map(this::toSubscriptionDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}/subscription/all")
|
||||
public List<SubscriptionDto> deleteAllUserSubscriptions(@PathVariable(name = "id") Long id) {
|
||||
return userService.deleteAllUserSubscriptions(id).stream()
|
||||
.map(this::toSubscriptionDto)
|
||||
.toList();
|
||||
}
|
||||
}
|
31
src/main/java/com/example/demo/users/api/UserDto.java
Normal file
31
src/main/java/com/example/demo/users/api/UserDto.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.example.demo.users.api;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty.Access;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class UserDto {
|
||||
@JsonProperty(access = Access.READ_ONLY)
|
||||
private Long id;
|
||||
@NotBlank
|
||||
@Size(min = 3, max = 20)
|
||||
private String login;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
}
|
91
src/main/java/com/example/demo/users/model/UserEntity.java
Normal file
91
src/main/java/com/example/demo/users/model/UserEntity.java
Normal file
@ -0,0 +1,91 @@
|
||||
package com.example.demo.users.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.example.demo.core.model.BaseEntity;
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OrderBy;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class UserEntity extends BaseEntity {
|
||||
@Column(nullable = false, unique = true, length = 20)
|
||||
private String login;
|
||||
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
|
||||
@OrderBy("id ASC")
|
||||
private Set<OrderEntity> orders = new HashSet<>();
|
||||
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@OrderBy("id ASC")
|
||||
private Set<UserSubscriptionEntity> userSubscriptions = new HashSet<>();
|
||||
|
||||
public UserEntity() {
|
||||
}
|
||||
|
||||
public UserEntity(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public Set<OrderEntity> getOrders() {
|
||||
return orders;
|
||||
}
|
||||
|
||||
public void addOrder(OrderEntity order) {
|
||||
if (order.getUser() != this) {
|
||||
order.setUser(this);
|
||||
}
|
||||
orders.add(order);
|
||||
}
|
||||
|
||||
public Set<UserSubscriptionEntity> getUserSubscriptions() {
|
||||
return userSubscriptions;
|
||||
}
|
||||
|
||||
public void addSubscription(UserSubscriptionEntity userSubscription) {
|
||||
if (userSubscription.getUser() != this) {
|
||||
userSubscription.setUser(this);
|
||||
}
|
||||
userSubscriptions.add(userSubscription);
|
||||
}
|
||||
|
||||
public void deleteSubscription(UserSubscriptionEntity userSubscription) {
|
||||
if (userSubscription.getUser() != this) {
|
||||
return;
|
||||
}
|
||||
userSubscriptions.remove(userSubscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, login, orders, userSubscriptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
UserEntity other = (UserEntity) obj;
|
||||
return Objects.equals(other.getId(), id)
|
||||
&& Objects.equals(other.getLogin(), login)
|
||||
&& Objects.equals(other.getOrders(), orders)
|
||||
&& Objects.equals(other.getUserSubscriptions(), userSubscriptions);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.example.demo.users.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
|
||||
public interface UserRepository extends CrudRepository<UserEntity, Long> {
|
||||
Optional<UserEntity> findByLoginIgnoreCase(String login);
|
||||
}
|
131
src/main/java/com/example/demo/users/service/UserService.java
Normal file
131
src/main/java/com/example/demo/users/service/UserService.java
Normal file
@ -0,0 +1,131 @@
|
||||
package com.example.demo.users.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.example.demo.core.error.NotFoundException;
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.subscriptions.service.SubscriptionService;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.repository.UserRepository;
|
||||
import com.example.demo.usersubscription.model.UserSubscriptionEntity;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
private final UserRepository repository;
|
||||
private final SubscriptionService subscriptionService;
|
||||
|
||||
public UserService(
|
||||
UserRepository repository,
|
||||
SubscriptionService subscriptionService) {
|
||||
this.repository = repository;
|
||||
this.subscriptionService = subscriptionService;
|
||||
}
|
||||
|
||||
private void checkLogin(String login) {
|
||||
if (repository.findByLoginIgnoreCase(login).isPresent()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("User with login %s is already exists", login));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<UserEntity> getAll() {
|
||||
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public UserEntity get(long id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new NotFoundException(UserEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserEntity create(UserEntity entity) {
|
||||
if (entity == null) {
|
||||
throw new IllegalArgumentException("Entity is null");
|
||||
}
|
||||
checkLogin(entity.getLogin());
|
||||
repository.save(entity);
|
||||
subscriptionService.getAll().forEach(subscription -> {
|
||||
final UserSubscriptionEntity userSubscription = new UserSubscriptionEntity(entity, subscription, true);
|
||||
userSubscription.setUser(entity);
|
||||
userSubscription.setSubscription(subscription);
|
||||
});
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserEntity update(long id, UserEntity entity) {
|
||||
final UserEntity existsEntity = get(id);
|
||||
checkLogin(entity.getLogin());
|
||||
existsEntity.setLogin(entity.getLogin());
|
||||
repository.save(existsEntity);
|
||||
return existsEntity;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserEntity delete(long id) {
|
||||
final UserEntity existsEntity = get(id);
|
||||
repository.delete(existsEntity);
|
||||
return existsEntity;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<SubscriptionEntity> getUserSubscriptions(long id) {
|
||||
return get(id).getUserSubscriptions().stream()
|
||||
.filter(UserSubscriptionEntity::isActive)
|
||||
.map(UserSubscriptionEntity::getSubscription)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private List<SubscriptionEntity> changeUserSubscriptionsState(
|
||||
UserEntity existsUser,
|
||||
List<Long> subscriptionsIds,
|
||||
boolean state) {
|
||||
return existsUser.getUserSubscriptions().stream()
|
||||
.filter(subscription -> Objects.nonNull(subscription.getSubscription()))
|
||||
.filter(subscription -> subscriptionsIds.contains(subscription.getSubscription().getId()))
|
||||
.filter(subscription -> subscription.isActive() == !state)
|
||||
.map(subscription -> {
|
||||
subscription.setActive(state);
|
||||
return subscription.getSubscription();
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<SubscriptionEntity> enableUserSubscriptions(long id, List<Long> subscriptionsIds) {
|
||||
final UserEntity existsUser = get(id);
|
||||
final List<SubscriptionEntity> changedSubscriptions = changeUserSubscriptionsState(
|
||||
existsUser, subscriptionsIds, true);
|
||||
repository.save(existsUser);
|
||||
return changedSubscriptions;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<SubscriptionEntity> disableUserSubscriptions(long id, List<Long> subscriptionsIds) {
|
||||
final UserEntity existsUser = get(id);
|
||||
final List<SubscriptionEntity> changedSubscriptions = changeUserSubscriptionsState(
|
||||
existsUser, subscriptionsIds, false);
|
||||
repository.save(existsUser);
|
||||
return changedSubscriptions;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<SubscriptionEntity> deleteAllUserSubscriptions(long id) {
|
||||
final UserEntity existsUser = get(id);
|
||||
final List<UserSubscriptionEntity> subscriptions = existsUser.getUserSubscriptions().stream()
|
||||
.filter(subscription -> Objects.nonNull(subscription.getSubscription()))
|
||||
.toList();
|
||||
subscriptions.forEach(existsUser::deleteSubscription);
|
||||
repository.save(existsUser);
|
||||
return subscriptions.stream()
|
||||
.map(UserSubscriptionEntity::getSubscription)
|
||||
.toList();
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.example.demo.usersubscription.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MapsId;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users_subscriptions")
|
||||
public class UserSubscriptionEntity {
|
||||
@EmbeddedId
|
||||
private UserSubscriptionId id = new UserSubscriptionId();
|
||||
@ManyToOne
|
||||
@MapsId("userId")
|
||||
@JoinColumn(name = "user_id")
|
||||
private UserEntity user;
|
||||
@ManyToOne
|
||||
@MapsId("subscriptionId")
|
||||
@JoinColumn(name = "subscription_id")
|
||||
private SubscriptionEntity subscription;
|
||||
private boolean active;
|
||||
|
||||
public UserSubscriptionEntity() {
|
||||
}
|
||||
|
||||
public UserSubscriptionEntity(UserEntity user, SubscriptionEntity subscription, boolean active) {
|
||||
this.user = user;
|
||||
this.subscription = subscription;
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public UserSubscriptionId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UserSubscriptionId id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserEntity user) {
|
||||
this.user = user;
|
||||
if (!user.getUserSubscriptions().contains(this)) {
|
||||
user.getUserSubscriptions().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public SubscriptionEntity getSubscription() {
|
||||
return subscription;
|
||||
}
|
||||
|
||||
public void setSubscription(SubscriptionEntity subscription) {
|
||||
this.subscription = subscription;
|
||||
if (!subscription.getUserSubscriptions().contains(this)) {
|
||||
subscription.getUserSubscriptions().add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, user.getId(), subscription.getId(), active);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
UserSubscriptionEntity other = (UserSubscriptionEntity) obj;
|
||||
return Objects.equals(id, other.id)
|
||||
&& Objects.equals(user.getId(), other.user.getId())
|
||||
&& Objects.equals(subscription.getId(), other.subscription.getId())
|
||||
&& active == other.active;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.example.demo.usersubscription.model;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class UserSubscriptionId {
|
||||
private Long userId;
|
||||
private Long subscriptionId;
|
||||
|
||||
public UserSubscriptionId() {
|
||||
}
|
||||
|
||||
public UserSubscriptionId(Long userId, Long subscriptionId) {
|
||||
this.userId = userId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getSubscriptionId() {
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
public void setSubscriptionId(Long subscriptionId) {
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
Optional.ofNullable(userId).orElse(0L),
|
||||
Optional.ofNullable(subscriptionId).orElse(0L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
UserSubscriptionId other = (UserSubscriptionId) obj;
|
||||
return Objects.equals(userId, other.userId)
|
||||
&& Objects.equals(subscriptionId, other.subscriptionId);
|
||||
}
|
||||
|
||||
}
|
@ -1 +1,20 @@
|
||||
# Server
|
||||
spring.main.banner-mode=off
|
||||
server.port=8080
|
||||
|
||||
# Logger settings
|
||||
# Available levels are: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
|
||||
logging.level.com.example.demo=DEBUG
|
||||
|
||||
# JPA Settings
|
||||
spring.datasource.url=jdbc:h2:file:./data
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=password
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
spring.jpa.open-in-view=false
|
||||
# spring.jpa.show-sql=true
|
||||
# spring.jpa.properties.hibernate.format_sql=true
|
||||
|
||||
# H2 console
|
||||
spring.h2.console.enabled=true
|
@ -1,13 +0,0 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class DemoApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.example.demo.speaker.service.SpeakerService;
|
||||
|
||||
@SpringBootTest
|
||||
class SpeakerSrviceTests {
|
||||
@Autowired
|
||||
SpeakerService speakerService;
|
||||
|
||||
@Test
|
||||
void testSpeakerRus() {
|
||||
final String res = speakerService.say("Мир", "ru");
|
||||
Assertions.assertEquals("Привет, Мир!", res);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpeakerEng() {
|
||||
final String res = speakerService.say("World", "en");
|
||||
Assertions.assertEquals("Hello, World!", res);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpeakerDeu() {
|
||||
final String res = speakerService.say("Welt", "de");
|
||||
Assertions.assertEquals("Hallo, Welt!", res);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpeakerErrorWired() {
|
||||
Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> speakerService.say("Мир", "rus"));
|
||||
}
|
||||
}
|
@ -1,61 +1,79 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
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;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
import com.example.demo.core.error.NotFoundException;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
import com.example.demo.types.service.TypeService;
|
||||
|
||||
@SpringBootTest
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
class TypeServiceTests {
|
||||
@Autowired
|
||||
private TypeService typeService;
|
||||
@Autowired
|
||||
private TypeService typeService;
|
||||
|
||||
@Test
|
||||
void getTest() {
|
||||
Assertions.assertThrows(NotFoundException.class, () -> typeService.get(0L));
|
||||
}
|
||||
private TypeEntity type;
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
void createTest() {
|
||||
typeService.create(new TypeEntity(null, "Ноутбук"));
|
||||
typeService.create(new TypeEntity(null, "Телефон"));
|
||||
final TypeEntity last = typeService.create(new TypeEntity(null, "Игровая приставка"));
|
||||
Assertions.assertEquals(3, typeService.getAll().size());
|
||||
Assertions.assertEquals(last, typeService.get(3L));
|
||||
}
|
||||
@BeforeEach
|
||||
void createData() {
|
||||
removeData();
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void updateTest() {
|
||||
final String test = "TEST";
|
||||
final TypeEntity entity = typeService.get(3L);
|
||||
final String oldName = entity.getName();
|
||||
final TypeEntity newEntity = typeService.update(3L, new TypeEntity(1L, test));
|
||||
Assertions.assertEquals(3, typeService.getAll().size());
|
||||
Assertions.assertEquals(newEntity, typeService.get(3L));
|
||||
Assertions.assertEquals(test, newEntity.getName());
|
||||
Assertions.assertNotEquals(oldName, newEntity.getName());
|
||||
}
|
||||
type = typeService.create(new TypeEntity("Ноутбук"));
|
||||
typeService.create(new TypeEntity("Телефон"));
|
||||
typeService.create(new TypeEntity("Игровая приставка"));
|
||||
}
|
||||
|
||||
@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());
|
||||
@AfterEach
|
||||
void removeData() {
|
||||
typeService.getAll().forEach(item -> typeService.delete(item.getId()));
|
||||
}
|
||||
|
||||
final TypeEntity newEntity = typeService.create(new TypeEntity(null, "Игровая приставка"));
|
||||
Assertions.assertEquals(3, typeService.getAll().size());
|
||||
Assertions.assertEquals(4L, newEntity.getId());
|
||||
}
|
||||
@Test
|
||||
void getTest() {
|
||||
Assertions.assertThrows(NotFoundException.class, () -> typeService.get(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createTest() {
|
||||
Assertions.assertEquals(3, typeService.getAll().size());
|
||||
Assertions.assertEquals(type, typeService.get(type.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createNotUniqueTest() {
|
||||
final TypeEntity nonUniqueType = new TypeEntity("Ноутбук");
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> typeService.create(nonUniqueType));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createNullableTest() {
|
||||
final TypeEntity nullableType = new TypeEntity(null);
|
||||
Assertions.assertThrows(DataIntegrityViolationException.class, () -> typeService.create(nullableType));
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateTest() {
|
||||
final String test = "TEST";
|
||||
final String oldName = type.getName();
|
||||
final TypeEntity newEntity = typeService.update(type.getId(), new TypeEntity(test));
|
||||
Assertions.assertEquals(3, typeService.getAll().size());
|
||||
Assertions.assertEquals(newEntity, typeService.get(type.getId()));
|
||||
Assertions.assertEquals(test, newEntity.getName());
|
||||
Assertions.assertNotEquals(oldName, newEntity.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteTest() {
|
||||
typeService.delete(type.getId());
|
||||
Assertions.assertEquals(2, typeService.getAll().size());
|
||||
|
||||
final TypeEntity newEntity = typeService.create(new TypeEntity(type.getName()));
|
||||
Assertions.assertEquals(3, typeService.getAll().size());
|
||||
Assertions.assertNotEquals(type.getId(), newEntity.getId());
|
||||
}
|
||||
}
|
||||
|
140
src/test/java/com/example/demo/UserOrderServiceTest.java
Normal file
140
src/test/java/com/example/demo/UserOrderServiceTest.java
Normal file
@ -0,0 +1,140 @@
|
||||
package com.example.demo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
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;
|
||||
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.service.OrderService;
|
||||
import com.example.demo.subscriptions.model.SubscriptionEntity;
|
||||
import com.example.demo.subscriptions.service.SubscriptionService;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
import com.example.demo.types.service.TypeService;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.service.UserService;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
@SpringBootTest
|
||||
@TestMethodOrder(OrderAnnotation.class)
|
||||
class UserOrderServiceTest {
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
@Autowired
|
||||
private TypeService typeService;
|
||||
@Autowired
|
||||
private SubscriptionService subscriptionService;
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
private TypeEntity type1;
|
||||
private TypeEntity type2;
|
||||
private TypeEntity type3;
|
||||
|
||||
private SubscriptionEntity subscription;
|
||||
|
||||
private UserEntity user1;
|
||||
private UserEntity user2;
|
||||
|
||||
@BeforeEach
|
||||
void createData() {
|
||||
removeData();
|
||||
|
||||
type1 = typeService.create(new TypeEntity("Ноутбук"));
|
||||
type2 = typeService.create(new TypeEntity("Телефон"));
|
||||
type3 = typeService.create(new TypeEntity("Игровая приставка"));
|
||||
|
||||
subscription = subscriptionService.create(new SubscriptionEntity("Подписка 1"));
|
||||
subscriptionService.create(new SubscriptionEntity("Подписка 2"));
|
||||
subscriptionService.create(new SubscriptionEntity("Подписка 3"));
|
||||
|
||||
user1 = userService.create(new UserEntity("user1"));
|
||||
user2 = userService.create(new UserEntity("user2"));
|
||||
|
||||
final var orders = List.of(
|
||||
new OrderEntity(type1, 49999.00, 20),
|
||||
new OrderEntity(type1, 129999.00, 3),
|
||||
new OrderEntity(type2, 15450.50, 30),
|
||||
new OrderEntity(type2, 69900.50, 10),
|
||||
new OrderEntity(type2, 150000.00, 6),
|
||||
new OrderEntity(type3, 75000.00, 6),
|
||||
new OrderEntity(type3, 67800.00, 3));
|
||||
orders.forEach(order -> orderService.create(user1.getId(), order));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void removeData() {
|
||||
userService.getAll().forEach(item -> userService.delete(item.getId()));
|
||||
typeService.getAll().forEach(item -> typeService.delete(item.getId()));
|
||||
subscriptionService.getAll().forEach(item -> subscriptionService.delete(item.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
void createTest() {
|
||||
Assertions.assertEquals(7, orderService.getAll(user1.getId(), 0).size());
|
||||
Assertions.assertEquals(0, orderService.getAll(user2.getId(), 0).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void orderFilterTest() {
|
||||
Assertions.assertEquals(2, orderService.getAll(user1.getId(), type1.getId()).size());
|
||||
Assertions.assertEquals(3, orderService.getAll(user1.getId(), type2.getId()).size());
|
||||
Assertions.assertEquals(2, orderService.getAll(user1.getId(), type3.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
void subscriptionsTest() {
|
||||
Assertions.assertEquals(3, userService.getUserSubscriptions(user1.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
void subscriptionDisableTest() {
|
||||
userService.disableUserSubscriptions(user1.getId(), List.of(subscription.getId()));
|
||||
Assertions.assertEquals(subscriptionService.getAll().size() - 1,
|
||||
userService.getUserSubscriptions(user1.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
void subscriptionEnableTest() {
|
||||
userService.enableUserSubscriptions(user1.getId(), List.of(subscription.getId()));
|
||||
Assertions.assertEquals(subscriptionService.getAll().size(),
|
||||
userService.getUserSubscriptions(user1.getId()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
void subscriptionsDeleteTest() {
|
||||
userService.deleteAllUserSubscriptions(user1.getId());
|
||||
Assertions.assertTrue(userService.getUserSubscriptions(user1.getId()).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
void userCascadeDeleteTest() {
|
||||
userService.delete(user1.getId());
|
||||
final var orders = entityManager.createQuery(
|
||||
"select count(o) from OrderEntity o where o.user.id = :userId");
|
||||
orders.setParameter("userId", user1.getId());
|
||||
Assertions.assertEquals(0, orders.getFirstResult());
|
||||
final var subscriptions = entityManager.createQuery(
|
||||
"select count(us) from UserSubscriptionEntity us where us.user.id = :userId");
|
||||
subscriptions.setParameter("userId", user1.getId());
|
||||
Assertions.assertEquals(0, subscriptions.getFirstResult());
|
||||
|
||||
}
|
||||
}
|
14
src/test/resources/application.properties
Normal file
14
src/test/resources/application.properties
Normal file
@ -0,0 +1,14 @@
|
||||
# Server
|
||||
spring.main.banner-mode=off
|
||||
|
||||
# Logger settings
|
||||
# Available levels are: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
|
||||
logging.level.com.example.demo=DEBUG
|
||||
|
||||
# JPA Settings
|
||||
spring.datasource.url=jdbc:h2:mem:testdb
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=password
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
spring.jpa.open-in-view=false
|
Loading…
x
Reference in New Issue
Block a user