что-то мутится
This commit is contained in:
parent
d47f50ba29
commit
e59d4c9465
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
22
build.gradle
22
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'
|
||||
}
|
||||
@ -18,12 +29,19 @@ repositories {
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
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'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-devtools'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.3.0'
|
||||
runtimeOnly 'org.webjars.npm:bootstrap:5.3.3'
|
||||
runtimeOnly 'org.webjars.npm:bootstrap-icons:1.11.3'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
67
build/resources/main/public/css/style.css
Normal file
67
build/resources/main/public/css/style.css
Normal file
@ -0,0 +1,67 @@
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
td form {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: -.25em;
|
||||
}
|
||||
|
||||
.button-fixed-width {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.button-link {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.invalid-feedback {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.w-10 {
|
||||
width: 10% !important;
|
||||
}
|
||||
|
||||
.my-navbar {
|
||||
background-color: #3c3c3c !important;
|
||||
}
|
||||
|
||||
.my-navbar .link a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.my-navbar .logo {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.my-footer {
|
||||
background-color: #2c2c2c;
|
||||
height: 32px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.cart-image {
|
||||
width: 3.1rem;
|
||||
padding: 0.25rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.cart-item {
|
||||
height: auto;
|
||||
}
|
37
build/resources/main/static/error.html
Normal file
37
build/resources/main/static/error.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Ошибка</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<ul class="list-group mb-2">
|
||||
<th:block th:if="${#strings.isEmpty(message)}">
|
||||
<li class="list-group-item">
|
||||
Неизвестная ошибка
|
||||
</li>
|
||||
</th:block>
|
||||
<th:block th:if="${not #strings.isEmpty(message)}">
|
||||
<li class="list-group-item">
|
||||
<strong>Ошибка:</strong> [[${message}]]
|
||||
</li>
|
||||
</th:block>
|
||||
<th:block th:if="${not #strings.isEmpty(url)}">
|
||||
<li class="list-group-item">
|
||||
<strong>Адрес:</strong> [[${url}]]
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Класс исключения:</strong> [[${exception}]]
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
[[${method}]] ([[${file}]]:[[${line}]])
|
||||
</li>
|
||||
</th:block>
|
||||
</ul>
|
||||
<a class="btn btn-primary button-fixed-width" href="/">На главную</a>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
71
build/resources/main/templates/default.html
Normal file
71
build/resources/main/templates/default.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" data-bs-theme="dark" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">My shop</title>
|
||||
<script type="text/javascript" src="/webjars/bootstrap/5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/5.3.3/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
</head>
|
||||
|
||||
<body class="h-100 d-flex flex-column">
|
||||
<nav class="navbar navbar-expand-md my-navbar" data-bs-theme="dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">
|
||||
<i class="bi bi-cart2 d-inline-block align-top me-1 logo"></i>
|
||||
Туда сюда и пицца
|
||||
</a>
|
||||
<th:block sec:authorize="isAuthenticated()" th:with="userName=${#authentication.name}">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#main-navbar"
|
||||
aria-controls="main-navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="main-navbar">
|
||||
<ul class="navbar-nav me-auto link" th:with="activeLink=${#objects.nullSafe(servletPath, '')}">
|
||||
<th:block sec:authorize="hasRole('ADMIN')">
|
||||
<a class="nav-link" href="/admin/user"
|
||||
th:classappend="${activeLink.startsWith('/admin/user') ? 'active' : ''}">
|
||||
Пользователи
|
||||
</a>
|
||||
<a class="nav-link" href="/admin/type"
|
||||
th:classappend="${activeLink.startsWith('/admin/type') ? 'active' : ''}">
|
||||
Типы заказов
|
||||
</a>
|
||||
<a class="nav-link" href="/admin/subscription"
|
||||
th:classappend="${activeLink.startsWith('/admin/subscription') ? 'active' : ''}">
|
||||
Списки рассылки
|
||||
</a>
|
||||
<a class="nav-link" href="/h2-console/" target="_blank">Консоль H2</a>
|
||||
</th:block>
|
||||
<a class="nav-link" href="/123" target="_blank">Ошибка 1</a>
|
||||
<a class="nav-link" href="/admin/123" target="_blank">Ошибка 2</a>
|
||||
</ul>
|
||||
<ul class="navbar-nav" th:if="${not #strings.isEmpty(userName)}">
|
||||
<form th:action="@{/logout}" method="post">
|
||||
<button type="submit" class="navbar-brand nav-link" onclick="return confirm('Вы уверены?')">
|
||||
Выход ([[${userName}]])
|
||||
</button>
|
||||
</form>
|
||||
<a class="navbar-brand" href="/cart">
|
||||
<i class="bi bi-cart2 d-inline-block align-top me-1 logo"></i>
|
||||
[[${#numbers.formatDecimal(totalCart, 1, 2)}]] ₽
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container-fluid p-2" layout:fragment="content">
|
||||
</main>
|
||||
<footer class="my-footer mt-auto d-flex flex-shrink-0 justify-content-center align-items-center">
|
||||
Автор, [[${#dates.year(#dates.createNow())}]]
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
44
build/resources/main/templates/login.html
Normal file
44
build/resources/main/templates/login.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/login}" method="post">
|
||||
<div th:if="${param.error}" class="alert alert-danger">
|
||||
Неверный логин или пароль
|
||||
</div>
|
||||
<div th:if="${param.logout}" class="alert alert-success">
|
||||
Выход успешно произведен
|
||||
</div>
|
||||
<div th:if="${param.signup}" class="alert alert-success">
|
||||
Пользователь успешно создан
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Имя пользователя</label>
|
||||
<input type="text" id="username" name="username" class="form-control" required minlength="3"
|
||||
maxlength="20">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Пароль</label>
|
||||
<input type="password" id="password" name="password" class="form-control" required minlength="3"
|
||||
maxlength="20">
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="remember-me" name="remember-me" checked>
|
||||
<label class="form-check-label" for="remember-me">Запомнить меня</label>
|
||||
</div>
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Войти</button>
|
||||
<a class="btn btn-secondary button-fixed-width" href="/signup">Регистрация</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
</html>
|
37
build/resources/main/templates/signup.html
Normal file
37
build/resources/main/templates/signup.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/signup}" th:object="${user}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="login" class="form-label">Имя пользователя</label>
|
||||
<input type="text" th:field="*{login}" id="login" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('login')}" th:errors="*{login}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Пароль</label>
|
||||
<input type="password" th:field="*{password}" id="password" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="passwordConfirm" class="form-label">Пароль (подтверждение)</label>
|
||||
<input type="password" th:field="*{passwordConfirm}" id="passwordConfirm" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('passwordConfirm')}" th:errors="*{passwordConfirm}"
|
||||
class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Регистрация</button>
|
||||
<a class="btn btn-secondary button-fixed-width" href="/">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
</html>
|
28
build/resources/main/templates/type-edit.html
Normal file
28
build/resources/main/templates/type-edit.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Редакторовать тип заказа</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/admin/type/edit/{id}(id=${type.id})}" th:object="${type}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="id" class="form-label">ID</label>
|
||||
<input type="text" th:value="*{id}" id="id" class="form-control" readonly disabled>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Тип заказа</label>
|
||||
<input type="text" th:field="*{name}" id="name" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Сохранить</button>
|
||||
<a class="btn btn-secondary button-fixed-width" href="/admin/type">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
50
build/resources/main/templates/type.html
Normal file
50
build/resources/main/templates/type.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Типы заказов</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<th:block th:switch="${items.size()}">
|
||||
<h2 th:case="0">Данные отсутствуют</h2>
|
||||
<th:block th:case="*">
|
||||
<h2>Типы заказов</h2>
|
||||
<div>
|
||||
<a href="/admin/type/edit/" class="btn btn-primary">Добавить тип заказа</a>
|
||||
</div>
|
||||
<table class="table">
|
||||
<caption></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="w-10">ID</th>
|
||||
<th scope="col" class="w-auto">Тип заказа</th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="type : ${items}">
|
||||
<th scope="row" th:text="${type.id}"></th>
|
||||
<td th:text="${type.name}"></td>
|
||||
<td>
|
||||
<form th:action="@{/admin/type/edit/{id}(id=${type.id})}" method="get">
|
||||
<button type="submit" class="btn btn-link button-link">Редактировать</button>
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<form th:action="@{/admin/type/delete/{id}(id=${type.id})}" method="post">
|
||||
<button type="submit" class="btn btn-link button-link"
|
||||
onclick="return confirm('Вы уверены?')">Удалить</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
data.mv.db
BIN
data.mv.db
Binary file not shown.
59827
data.trace.db
Normal file
59827
data.trace.db
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,5 @@
|
||||
package com.example.demo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -10,9 +8,6 @@ import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import com.example.demo.order_lines.model.OrderLineEntity;
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.service.OrderService;
|
||||
import com.example.demo.products.model.ProductEntity;
|
||||
import com.example.demo.products.service.ProductService;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
@ -27,14 +22,11 @@ public class DemoApplication implements CommandLineRunner {
|
||||
private final TypeService typeService;
|
||||
private final ProductService productService;
|
||||
private final UserService userService;
|
||||
private final OrderService orderService;
|
||||
|
||||
public DemoApplication(TypeService typeService, ProductService productService, UserService userService,
|
||||
OrderService orderService) {
|
||||
public DemoApplication(TypeService typeService, ProductService productService, UserService userService) {
|
||||
this.typeService = typeService;
|
||||
this.productService = productService;
|
||||
this.userService = userService;
|
||||
this.orderService = orderService;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@ -62,13 +54,6 @@ public class DemoApplication implements CommandLineRunner {
|
||||
log.info("Create default users values");
|
||||
userService.create(new UserEntity("Alex", "Kryukov", "akryu@mail.ru", "password123"));
|
||||
userService.create(new UserEntity("Oleg", "Zyngin", "@mail.ru", "password"));
|
||||
|
||||
log.info("Create default orders values");
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
List<OrderLineEntity> lines = new ArrayList();
|
||||
lines.add(new OrderLineEntity(null, 3));
|
||||
final var user1 = userService.create(new UserEntity("Misha", "Kryukov", "akryu132@mail.ru", "password"));
|
||||
orderService.create(new OrderEntity(user1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
package com.example.demo.order_lines.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.example.demo.core.model.BaseEntity;
|
||||
import com.example.demo.products.model.ProductEntity;
|
||||
|
||||
@ -17,19 +16,22 @@ import com.example.demo.products.model.ProductEntity;
|
||||
public class OrderLineEntity extends BaseEntity {
|
||||
@Column(nullable = false)
|
||||
private Integer count;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "productId", nullable = false)
|
||||
private ProductEntity product;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Double totalPrice;
|
||||
|
||||
public OrderLineEntity() {
|
||||
|
||||
// Конструктор
|
||||
}
|
||||
|
||||
public OrderLineEntity(ProductEntity product, Integer count) {
|
||||
this.product = product;
|
||||
this.count = count;
|
||||
calculateTotalPrice(); // Рассчитываем сумму при создании
|
||||
}
|
||||
|
||||
public ProductEntity getProduct() {
|
||||
@ -38,6 +40,7 @@ public class OrderLineEntity extends BaseEntity {
|
||||
|
||||
public void setProduct(ProductEntity product) {
|
||||
this.product = product;
|
||||
calculateTotalPrice(); // Пересчитываем сумму при установке продукта
|
||||
}
|
||||
|
||||
public Integer getCount() {
|
||||
@ -46,6 +49,7 @@ public class OrderLineEntity extends BaseEntity {
|
||||
|
||||
public void setCount(Integer count) {
|
||||
this.count = count;
|
||||
calculateTotalPrice(); // Пересчитываем сумму при установке количества
|
||||
}
|
||||
|
||||
public Double getTotalPrice() {
|
||||
@ -56,6 +60,14 @@ public class OrderLineEntity extends BaseEntity {
|
||||
this.totalPrice = totalPrice;
|
||||
}
|
||||
|
||||
private void calculateTotalPrice() {
|
||||
if (product != null && product.getPrice() != null && count != null) {
|
||||
totalPrice = product.getPrice() * count;
|
||||
} else {
|
||||
totalPrice = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, product, count, totalPrice);
|
||||
|
@ -2,6 +2,8 @@ package com.example.demo.orders.api;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.example.demo.core.configuration.Constants;
|
||||
@ -11,6 +13,7 @@ import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.service.OrderService;
|
||||
import com.example.demo.products.model.ProductEntity;
|
||||
import com.example.demo.products.service.ProductService;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.service.UserService;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@ -48,19 +51,26 @@ public class OrderController {
|
||||
}
|
||||
|
||||
public OrderEntity toEntity(OrderDto dto) {
|
||||
final OrderEntity entity = modelMapper.map(dto, OrderEntity.class);
|
||||
if (dto.getUserId() != null) {
|
||||
entity.setUser(userService.get(dto.getUserId()));
|
||||
}
|
||||
entity.getLines().clear();
|
||||
for (OrderLineDto lineDto : dto.getLines()) {
|
||||
OrderLineEntity orderLineEntity = modelMapper.map(lineDto, OrderLineEntity.class);
|
||||
orderLineEntity.setId(null);
|
||||
OrderEntity entity = modelMapper.map(dto, OrderEntity.class);
|
||||
UserEntity user = userService.get(dto.getUserId());
|
||||
entity.setUser(user);
|
||||
|
||||
List<OrderLineEntity> orderLines = dto.getLines().stream()
|
||||
.map(lineDto -> {
|
||||
|
||||
OrderLineEntity orderLineEntity = modelMapper.map(lineDto, OrderLineEntity.class);
|
||||
orderLineEntity.setId(null);
|
||||
|
||||
// Получаем продукт по id
|
||||
ProductEntity product = productService.get(lineDto.getProductId());
|
||||
|
||||
orderLineEntity.setProduct(product);
|
||||
return orderLineEntity;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
orderLines.stream().forEach(entity::addOrderLine);
|
||||
|
||||
ProductEntity product = productService.get(lineDto.getProductId());
|
||||
orderLineEntity.setProduct(product); // Устанавливаем продукт для строки заказа
|
||||
entity.addOrderLine(orderLineEntity);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import com.example.demo.users.model.UserEntity;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
@ -21,8 +22,9 @@ public class OrderEntity extends BaseEntity {
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "userId", nullable = false)
|
||||
private UserEntity user;
|
||||
@ManyToMany(cascade = CascadeType.ALL)
|
||||
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private final List<OrderLineEntity> lines = new ArrayList<>();
|
||||
private Double totalPrice; // Поле для общей стоимости заказа
|
||||
|
||||
public OrderEntity() {
|
||||
super();
|
||||
@ -44,17 +46,30 @@ public class OrderEntity extends BaseEntity {
|
||||
return lines;
|
||||
}
|
||||
|
||||
public Double getTotalPrice() {
|
||||
return totalPrice;
|
||||
}
|
||||
|
||||
public void addOrderLine(OrderLineEntity orderLine) {
|
||||
this.lines.add(orderLine);
|
||||
recalculateTotalPrice();
|
||||
}
|
||||
|
||||
public void removeOrderLine(OrderLineEntity orderLine) {
|
||||
this.lines.remove(orderLine);
|
||||
recalculateTotalPrice();
|
||||
}
|
||||
|
||||
private void recalculateTotalPrice() {
|
||||
totalPrice = 0.0;
|
||||
for (OrderLineEntity line : lines) {
|
||||
totalPrice += line.getTotalPrice();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, user, lines);
|
||||
return Objects.hash(id, user, lines, totalPrice);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unlikely-arg-user")
|
||||
@ -67,7 +82,7 @@ public class OrderEntity extends BaseEntity {
|
||||
final OrderEntity other = (OrderEntity) obj;
|
||||
return Objects.equals(other.getId(), id)
|
||||
&& Objects.equals(other.getUser(), user)
|
||||
&& Objects.equals(other.getLines(), lines);
|
||||
&& Objects.equals(other.getLines(), lines)
|
||||
&& Objects.equals(other.getTotalPrice(), totalPrice);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ public interface OrderRepository extends CrudRepository<OrderEntity, Long> {
|
||||
|
||||
List<OrderEntity> findByUserIdAndLinesProductId(long userId, List<Long> lines);
|
||||
|
||||
List<OrderEntity> findByLinesProductId(List<Long> lines);
|
||||
List<OrderEntity> findById(long id);
|
||||
|
||||
List<OrderEntity> findByUserId(long userId);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.example.demo.orders.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -24,7 +25,7 @@ public class OrderService {
|
||||
return repository.findByUserIdAndLinesProductId(userId, lines);
|
||||
}
|
||||
if (userId == 0L && !lines.isEmpty()) {
|
||||
return repository.findByLinesProductId(lines);
|
||||
return repository.findAll();
|
||||
}
|
||||
if (userId != 0L && lines.isEmpty()) {
|
||||
return repository.findByUserId(userId);
|
||||
@ -34,8 +35,12 @@ public class OrderService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public OrderEntity get(Long id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new NotFoundException(OrderEntity.class, id));
|
||||
// Используем findById репозитория для извлечения OrderEntity по id
|
||||
Optional<OrderEntity> optionalOrderEntity = repository.findById(id);
|
||||
|
||||
// Используем orElseThrow для выброса исключения, если OrderEntity не найден
|
||||
OrderEntity orderEntity = optionalOrderEntity.orElseThrow(() -> new NotFoundException(OrderEntity.class, id));
|
||||
return orderEntity;
|
||||
}
|
||||
|
||||
public OrderEntity create(OrderEntity entity) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.example.demo.products.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@ -33,6 +32,11 @@ public class ProductService {
|
||||
return repository.findById(id).orElseThrow(() -> new NotFoundException(ProductEntity.class, id));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<ProductEntity> get(List<Long> id) {
|
||||
return StreamSupport.stream(repository.findAllById(id).spliterator(), false).toList();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ProductEntity create(ProductEntity entity) {
|
||||
if (entity == null) {
|
||||
|
67
src/main/resources/public/css/style.css
Normal file
67
src/main/resources/public/css/style.css
Normal file
@ -0,0 +1,67 @@
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
td form {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: -.25em;
|
||||
}
|
||||
|
||||
.button-fixed-width {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.button-link {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.invalid-feedback {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.w-10 {
|
||||
width: 10% !important;
|
||||
}
|
||||
|
||||
.my-navbar {
|
||||
background-color: #3c3c3c !important;
|
||||
}
|
||||
|
||||
.my-navbar .link a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.my-navbar .logo {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.my-footer {
|
||||
background-color: #2c2c2c;
|
||||
height: 32px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.cart-image {
|
||||
width: 3.1rem;
|
||||
padding: 0.25rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.cart-item {
|
||||
height: auto;
|
||||
}
|
37
src/main/resources/static/error.html
Normal file
37
src/main/resources/static/error.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Ошибка</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<ul class="list-group mb-2">
|
||||
<th:block th:if="${#strings.isEmpty(message)}">
|
||||
<li class="list-group-item">
|
||||
Неизвестная ошибка
|
||||
</li>
|
||||
</th:block>
|
||||
<th:block th:if="${not #strings.isEmpty(message)}">
|
||||
<li class="list-group-item">
|
||||
<strong>Ошибка:</strong> [[${message}]]
|
||||
</li>
|
||||
</th:block>
|
||||
<th:block th:if="${not #strings.isEmpty(url)}">
|
||||
<li class="list-group-item">
|
||||
<strong>Адрес:</strong> [[${url}]]
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Класс исключения:</strong> [[${exception}]]
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
[[${method}]] ([[${file}]]:[[${line}]])
|
||||
</li>
|
||||
</th:block>
|
||||
</ul>
|
||||
<a class="btn btn-primary button-fixed-width" href="/">На главную</a>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
71
src/main/resources/templates/default.html
Normal file
71
src/main/resources/templates/default.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" data-bs-theme="dark" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">My shop</title>
|
||||
<script type="text/javascript" src="/webjars/bootstrap/5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/5.3.3/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/webjars/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css" />
|
||||
<link rel="stylesheet" href="/css/style.css" />
|
||||
</head>
|
||||
|
||||
<body class="h-100 d-flex flex-column">
|
||||
<nav class="navbar navbar-expand-md my-navbar" data-bs-theme="dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">
|
||||
<i class="bi bi-cart2 d-inline-block align-top me-1 logo"></i>
|
||||
Туда сюда и пицца
|
||||
</a>
|
||||
<th:block sec:authorize="isAuthenticated()" th:with="userName=${#authentication.name}">
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#main-navbar"
|
||||
aria-controls="main-navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="main-navbar">
|
||||
<ul class="navbar-nav me-auto link" th:with="activeLink=${#objects.nullSafe(servletPath, '')}">
|
||||
<th:block sec:authorize="hasRole('ADMIN')">
|
||||
<a class="nav-link" href="/admin/user"
|
||||
th:classappend="${activeLink.startsWith('/admin/user') ? 'active' : ''}">
|
||||
Пользователи
|
||||
</a>
|
||||
<a class="nav-link" href="/admin/type"
|
||||
th:classappend="${activeLink.startsWith('/admin/type') ? 'active' : ''}">
|
||||
Типы заказов
|
||||
</a>
|
||||
<a class="nav-link" href="/admin/subscription"
|
||||
th:classappend="${activeLink.startsWith('/admin/subscription') ? 'active' : ''}">
|
||||
Списки рассылки
|
||||
</a>
|
||||
<a class="nav-link" href="/h2-console/" target="_blank">Консоль H2</a>
|
||||
</th:block>
|
||||
<a class="nav-link" href="/123" target="_blank">Ошибка 1</a>
|
||||
<a class="nav-link" href="/admin/123" target="_blank">Ошибка 2</a>
|
||||
</ul>
|
||||
<ul class="navbar-nav" th:if="${not #strings.isEmpty(userName)}">
|
||||
<form th:action="@{/logout}" method="post">
|
||||
<button type="submit" class="navbar-brand nav-link" onclick="return confirm('Вы уверены?')">
|
||||
Выход ([[${userName}]])
|
||||
</button>
|
||||
</form>
|
||||
<a class="navbar-brand" href="/cart">
|
||||
<i class="bi bi-cart2 d-inline-block align-top me-1 logo"></i>
|
||||
[[${#numbers.formatDecimal(totalCart, 1, 2)}]] ₽
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container-fluid p-2" layout:fragment="content">
|
||||
</main>
|
||||
<footer class="my-footer mt-auto d-flex flex-shrink-0 justify-content-center align-items-center">
|
||||
Автор, [[${#dates.year(#dates.createNow())}]]
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
44
src/main/resources/templates/login.html
Normal file
44
src/main/resources/templates/login.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/login}" method="post">
|
||||
<div th:if="${param.error}" class="alert alert-danger">
|
||||
Неверный логин или пароль
|
||||
</div>
|
||||
<div th:if="${param.logout}" class="alert alert-success">
|
||||
Выход успешно произведен
|
||||
</div>
|
||||
<div th:if="${param.signup}" class="alert alert-success">
|
||||
Пользователь успешно создан
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Имя пользователя</label>
|
||||
<input type="text" id="username" name="username" class="form-control" required minlength="3"
|
||||
maxlength="20">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Пароль</label>
|
||||
<input type="password" id="password" name="password" class="form-control" required minlength="3"
|
||||
maxlength="20">
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="remember-me" name="remember-me" checked>
|
||||
<label class="form-check-label" for="remember-me">Запомнить меня</label>
|
||||
</div>
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Войти</button>
|
||||
<a class="btn btn-secondary button-fixed-width" href="/signup">Регистрация</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
</html>
|
37
src/main/resources/templates/signup.html
Normal file
37
src/main/resources/templates/signup.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Вход</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/signup}" th:object="${user}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="login" class="form-label">Имя пользователя</label>
|
||||
<input type="text" th:field="*{login}" id="login" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('login')}" th:errors="*{login}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Пароль</label>
|
||||
<input type="password" th:field="*{password}" id="password" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="passwordConfirm" class="form-label">Пароль (подтверждение)</label>
|
||||
<input type="password" th:field="*{passwordConfirm}" id="passwordConfirm" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('passwordConfirm')}" th:errors="*{passwordConfirm}"
|
||||
class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Регистрация</button>
|
||||
<a class="btn btn-secondary button-fixed-width" href="/">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
</html>
|
28
src/main/resources/templates/type-edit.html
Normal file
28
src/main/resources/templates/type-edit.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Редакторовать тип заказа</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<form action="#" th:action="@{/admin/type/edit/{id}(id=${type.id})}" th:object="${type}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="id" class="form-label">ID</label>
|
||||
<input type="text" th:value="*{id}" id="id" class="form-control" readonly disabled>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Тип заказа</label>
|
||||
<input type="text" th:field="*{name}" id="name" class="form-control">
|
||||
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="mb-3 d-flex flex-row">
|
||||
<button class="btn btn-primary me-2 button-fixed-width" type="submit">Сохранить</button>
|
||||
<a class="btn btn-secondary button-fixed-width" href="/admin/type">Отмена</a>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
50
src/main/resources/templates/type.html
Normal file
50
src/main/resources/templates/type.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||
|
||||
<head>
|
||||
<title>Типы заказов</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main layout:fragment="content">
|
||||
<th:block th:switch="${items.size()}">
|
||||
<h2 th:case="0">Данные отсутствуют</h2>
|
||||
<th:block th:case="*">
|
||||
<h2>Типы заказов</h2>
|
||||
<div>
|
||||
<a href="/admin/type/edit/" class="btn btn-primary">Добавить тип заказа</a>
|
||||
</div>
|
||||
<table class="table">
|
||||
<caption></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="w-10">ID</th>
|
||||
<th scope="col" class="w-auto">Тип заказа</th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
<th scope="col" class="w-10"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="type : ${items}">
|
||||
<th scope="row" th:text="${type.id}"></th>
|
||||
<td th:text="${type.name}"></td>
|
||||
<td>
|
||||
<form th:action="@{/admin/type/edit/{id}(id=${type.id})}" method="get">
|
||||
<button type="submit" class="btn btn-link button-link">Редактировать</button>
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<form th:action="@{/admin/type/delete/{id}(id=${type.id})}" method="post">
|
||||
<button type="submit" class="btn btn-link button-link"
|
||||
onclick="return confirm('Вы уверены?')">Удалить</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,72 +1,98 @@
|
||||
package com.example.demo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
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.core.error.NotFoundException;
|
||||
import com.example.demo.order_lines.model.OrderLineEntity;
|
||||
import com.example.demo.orders.model.OrderEntity;
|
||||
import com.example.demo.orders.service.OrderService;
|
||||
import com.example.demo.users.model.UserEntity;
|
||||
import com.example.demo.users.service.UserService;
|
||||
import com.example.demo.order_lines.model.OrderLineEntity;
|
||||
import com.example.demo.products.model.ProductEntity;
|
||||
import com.example.demo.products.service.ProductService;
|
||||
import com.example.demo.types.model.TypeEntity;
|
||||
import com.example.demo.types.service.TypeService;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootTest
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class OrderServiceTests {
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private ProductService productService;
|
||||
|
||||
@Autowired
|
||||
private TypeService typeService;
|
||||
|
||||
private OrderEntity order;
|
||||
|
||||
@BeforeEach
|
||||
void createData() {
|
||||
removeData();
|
||||
// Создаем данные для тестирования
|
||||
TypeEntity type = typeService.create(new TypeEntity("musor"));
|
||||
UserEntity user = userService.create(new UserEntity("John", "Doe", "privet@gmail.ru", "passwd"));
|
||||
ProductEntity product = productService.create(new ProductEntity("Laptop", type, 400.00));
|
||||
order = new OrderEntity(user);
|
||||
OrderLineEntity line = new OrderLineEntity(product, 2);
|
||||
order.addOrderLine(line);
|
||||
orderService.create(order);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void removeData() {
|
||||
// Удаляем все данные после каждого теста
|
||||
orderService.delete(order.getId());
|
||||
userService.delete(order.getUser().getId());
|
||||
productService.delete(order.getLines().get(0).getProduct().getId());
|
||||
typeService.delete(order.getLines().get(0).getProduct().getType().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllTest() {
|
||||
List<OrderEntity> orders = orderService.getAll(0L, List.of());
|
||||
Assertions.assertNotNull(orders);
|
||||
Assertions.assertFalse(orders.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTest() {
|
||||
// Тестируем, что найденный заказ совпадает с ожидаемым
|
||||
OrderEntity foundOrder = orderService.get(order.getId());
|
||||
Assertions.assertNotNull(foundOrder);
|
||||
Assertions.assertEquals(order, foundOrder);
|
||||
|
||||
// Проверяем, что вызов с несуществующим id бросает исключение
|
||||
Assertions.assertThrows(NotFoundException.class, () -> orderService.get(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
void createTest() {
|
||||
orderService.create(new OrderEntity(null));
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
List<OrderLineEntity> lines = new ArrayList();
|
||||
lines.add(new OrderLineEntity(null, 4));
|
||||
lines.add(new OrderLineEntity(null, 5));
|
||||
lines.add(new OrderLineEntity(null, 6));
|
||||
lines.add(new OrderLineEntity(null, 7));
|
||||
// Создаем тестовую сущность OrderEntity
|
||||
OrderEntity testOrder = new OrderEntity(null);
|
||||
// Вызываем метод create() и сохраняем созданную сущность
|
||||
OrderEntity createdOrder = orderService.create(testOrder);
|
||||
// Проверяем, что метод create() вернул не null
|
||||
Assertions.assertNotNull(createdOrder);
|
||||
// Проверяем, что созданная сущность имеет назначенный ID
|
||||
Assertions.assertNotNull(createdOrder.getId());
|
||||
// Проверяем, что созданный заказ совпадает с ожидаемым
|
||||
Assertions.assertNotNull(order.getId());
|
||||
OrderEntity foundOrder = orderService.get(order.getId());
|
||||
Assertions.assertEquals(order, foundOrder);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void updateTest() {
|
||||
// Получаем сущность OrderEntity для обновления
|
||||
OrderEntity existingOrder = orderService.get(1L);
|
||||
// Вызываем метод update() и сохраняем обновленную сущность
|
||||
OrderEntity updatedOrder = orderService.update(1L, existingOrder);
|
||||
// Проверяем, что метод update() вернул не null
|
||||
// Обновляем заказ и проверяем, что он изменился
|
||||
OrderEntity updatedOrder = orderService.update(order.getId(), order);
|
||||
Assertions.assertNotNull(updatedOrder);
|
||||
Assertions.assertEquals(order, updatedOrder);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
void deleteTest() {
|
||||
// Удаляем сущность OrderEntity по ее ID
|
||||
OrderEntity deletedOrder = orderService.delete(1L);
|
||||
// Проверяем, что метод delete() вернул не null
|
||||
Assertions.assertNotNull(deletedOrder);
|
||||
// Проверяем, что удаленная сущность имеет тот же ID, что и удаленная
|
||||
Assertions.assertEquals(1L, deletedOrder.getId());
|
||||
// Проверяем, что сущность больше не существует в репозитории
|
||||
Assertions.assertThrows(NotFoundException.class, () -> orderService.get(1L));
|
||||
// Удаляем заказ и проверяем, что его нет в базе данных
|
||||
orderService.delete(order.getId());
|
||||
Assertions.assertThrows(NotFoundException.class, () -> orderService.get(order.getId()));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.example.demo;
|
||||
|
||||
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;
|
||||
@ -18,6 +20,23 @@ class UserServiceTests {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@BeforeEach
|
||||
void createData() {
|
||||
UserEntity user1 = new UserEntity("John", "Doe", "gt434ge@fkgjfdj.com", "password");
|
||||
UserEntity user2 = new UserEntity("Alex", "Kryukov", "fhegehr@ghsjg.com", "password");
|
||||
UserEntity user3 = new UserEntity("Alex", "Kryukov", "fhegeуйцуйцhr@ghsjg.com", "password");
|
||||
userService.create(user1);
|
||||
userService.create(user2);
|
||||
userService.create(user3);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearData() {
|
||||
userService.delete(1L);
|
||||
userService.delete(2L);
|
||||
userService.delete(3L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTest() {
|
||||
Assertions.assertThrows(NotFoundException.class, () -> userService.get(0L));
|
||||
@ -26,12 +45,10 @@ class UserServiceTests {
|
||||
@Test
|
||||
@Order(1)
|
||||
void createTest() {
|
||||
userService.create(new UserEntity("John", "Doe", "gge@fkgjfdj", "password"));
|
||||
userService.create(new UserEntity("Alex", "Kryukov", "fhegehr@ghsjg.com", "password"));
|
||||
final UserEntity last = userService.create(new UserEntity("Alex", "selivanov", "fhegehr@ghsjg.com",
|
||||
"password"));
|
||||
Assertions.assertEquals(3, userService.getAll().size());
|
||||
Assertions.assertEquals(last, userService.get(3L));
|
||||
final UserEntity last = userService
|
||||
.create(new UserEntity("Alex", "selivanov", "fheg123ehr@ghsjg.com", "password"));
|
||||
Assertions.assertEquals(4, userService.getAll().size());
|
||||
Assertions.assertEquals(last, userService.get(4L));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user