diff --git a/front/src/app/pages/BarChangePage.js b/front/src/app/pages/BarChangePage.js index 1ad3828..36a416a 100644 --- a/front/src/app/pages/BarChangePage.js +++ b/front/src/app/pages/BarChangePage.js @@ -22,7 +22,7 @@ export function BarChangePage() { const {createError, createSuccess, createWarning} = useAlert(); useEffect(() => { - api().get(requests.bar.list) + api().get(requests.bar.all) .then((r) => { setBars(r.data.sort(getComparator("name"))) }) diff --git a/front/src/app/pages/cocktails/CocktailsPageContent.js b/front/src/app/pages/cocktails/CocktailsPageContent.js index 3957eac..b2375db 100644 --- a/front/src/app/pages/cocktails/CocktailsPageContent.js +++ b/front/src/app/pages/cocktails/CocktailsPageContent.js @@ -95,7 +95,7 @@ const CocktailsPageContent = () => { // eslint-disable-next-line }, [loading]); useEffect(() => { - api().get(requests.bar.ingredientSimple) + api().get(requests.ingredient.simple) .then((r) => { const arr = r.data.filter((i) => i.isHave) .map((i) => i.name) diff --git a/front/src/app/pages/cocktails/EditCocktailPage.js b/front/src/app/pages/cocktails/EditCocktailPage.js index b9290b0..a0f4642 100644 --- a/front/src/app/pages/cocktails/EditCocktailPage.js +++ b/front/src/app/pages/cocktails/EditCocktailPage.js @@ -95,7 +95,7 @@ export function EditCocktailPage() { }) .catch(() => createError("Ошибка получения данных")) - api().get(requests.bar.category) + api().get(requests.category.basic) .then((r) => { setCategory(r.data.sort(getComparator()) .map((item, i) => { @@ -104,7 +104,7 @@ export function EditCocktailPage() { }) .catch(() => createError("Ошибка получения категорий")) - api().get(requests.bar.glass) + api().get(requests.glass.list) .then((r) => setGlass(r.data.sort(getComparator()) .map((item, i) => { return {id: i, name: item} @@ -135,7 +135,7 @@ export function EditCocktailPage() { })) } const saveHandler = () => { - api().patch(requests.cocktails.edit, cocktail) + api().patch(requests.cocktails.basic, cocktail) .then((r) => { if (!r.data.error) { createSuccess("Сохранено") @@ -212,7 +212,7 @@ export function EditCocktailPage() { const file = event.target.files[0]; let formData = new FormData(); formData.append('file', file); - api().post(requests.cocktails.savePhoto, formData) + api().post(requests.cocktails.photo, formData) .then((r) => changeCocktailValue("image", r.data)) .catch(() => getError()) }} diff --git a/front/src/app/pages/ingredients/EditIngredientPage.js b/front/src/app/pages/ingredients/EditIngredientPage.js index 61af5e9..a96c311 100644 --- a/front/src/app/pages/ingredients/EditIngredientPage.js +++ b/front/src/app/pages/ingredients/EditIngredientPage.js @@ -36,7 +36,7 @@ export function EditIngredientPage() { const [ingredient, setIngredient] = useState(emptyIngredient) const {createError, createSuccess} = useAlert(); useEffect(() => { - api().get(requests.bar.ingredientList) + api().get(requests.ingredient.all) .then((r) => { const arr = r.data.sort(getComparator("asc", "name")); setIngredients(arr) @@ -53,7 +53,7 @@ export function EditIngredientPage() { }) .catch(() => createError("Ошибка получения данных")) - api().get(requests.bar.type) + api().get(requests.ingredient.type) .then((r) => setTypes(r.data.sort(getComparator("asc", "name")))) // eslint-disable-next-line }, []); @@ -65,7 +65,7 @@ export function EditIngredientPage() { })) } const saveIngredientHandler = () => { - api().patch(requests.bar.ingredient, ingredient) + api().patch(requests.ingredient.crud, ingredient) .then(() => createSuccess("Ингредиент сохранен")) .catch(() => createError("Ошибка сохранения")) } diff --git a/front/src/app/pages/ingredients/IngredientsPage.js b/front/src/app/pages/ingredients/IngredientsPage.js index 12af9d0..9e9061b 100644 --- a/front/src/app/pages/ingredients/IngredientsPage.js +++ b/front/src/app/pages/ingredients/IngredientsPage.js @@ -30,7 +30,7 @@ export function IngredientsPage() { const {createError, createSuccess} = useAlert(); useEffect(() => { - api().get(requests.bar.ingredientList) + api().get(requests.ingredient.all) .then((r) => { setIngredients(r.data) setLoading(false); @@ -63,7 +63,7 @@ export function IngredientsPage() { return ingredient; } }) - const url = `${requests.bar.ingredient}?id=${row.id}`; + const url = `${requests.ingredient.crud}?id=${row.id}`; const request = value ? api().put(url) : api().delete(url); request .then(() => { @@ -80,7 +80,7 @@ export function IngredientsPage() { const newState = ingredients.filter((ingredient) => ingredient.id !== id); setIngredients(newState) - api().delete(`${requests.bar.ingredient}/${id}`) + api().delete(`${requests.ingredient.crud}/${id}`) .then((r) => createSuccess("Ингредиент удален")) .catch(() => createError("Ошибка удаления ингредиента. Перезагрузите страницу")) } diff --git a/front/src/components/bar/BarList.js b/front/src/components/bar/BarList.js index 1b564c2..005de9b 100644 --- a/front/src/components/bar/BarList.js +++ b/front/src/components/bar/BarList.js @@ -16,7 +16,7 @@ export function BarList({all}) { useEffect(() => { setLoading(true); - api().get(`${requests.bar.list}?my=${!all}`) + api().get(`${requests.bar.all}?my=${!all}`) .then((r) => { setBars(r.data) setLoading(false); diff --git a/front/src/components/cocktails/CocktailInfoModal.js b/front/src/components/cocktails/CocktailInfoModal.js index 1f6d5c8..4d1887e 100644 --- a/front/src/components/cocktails/CocktailInfoModal.js +++ b/front/src/components/cocktails/CocktailInfoModal.js @@ -37,7 +37,7 @@ export function CocktailInfoModal({row}) { .catch(() => createError("Ошибка получения информации об ингредиенте")) } const selectIngredientHandler = (ingredient) => { - const url = `${requests.bar.ingredient}?id=${ingredient.id}`; + const url = `${requests.ingredient.crud}?id=${ingredient.id}`; const request = ingredient.isHave ? api().delete(url) : api().put(url); const value = !ingredient.isHave; request.then(() => { diff --git a/front/src/components/cocktails/EditCocktailReceipt.js b/front/src/components/cocktails/EditCocktailReceipt.js index 15f51fb..6cd7fd1 100644 --- a/front/src/components/cocktails/EditCocktailReceipt.js +++ b/front/src/components/cocktails/EditCocktailReceipt.js @@ -20,11 +20,11 @@ export function EditCocktailReceipt({receipt, handler}) { const [units, setUnits] = useState([]) useEffect(() => { - api().get(requests.bar.ingredientList) + api().get(requests.ingredient.all) .then((r) => setIngredients(r.data.sort(getComparator("asc", "name")))) .catch(() => createError("Ошибка получения списка ингредиентов")) - api().get(requests.bar.unit) + api().get(requests.unit) .then((r) => setUnits(r.data.sort(getComparator("asc", "name")))) .catch(() => createError("Ошибка получения единиц измерения")) }, []); diff --git a/front/src/components/cocktails/FilterBlock.js b/front/src/components/cocktails/FilterBlock.js index 62449ec..b814cf5 100644 --- a/front/src/components/cocktails/FilterBlock.js +++ b/front/src/components/cocktails/FilterBlock.js @@ -24,11 +24,11 @@ export function FilterBlock({filter, handleFilterChange, handleClearFilter, barm const sort = ['Название по возрастанию', 'Название по убыванию']; useEffect(() => { - api().get(requests.bar.category) + api().get(requests.category.basic) .then((r) => setCategory(r.data)) .catch(() => createError("Ошибка получения категорий")) - api().get(requests.bar.glass) + api().get(requests.glass.list) .then((r) => setGlass(r.data)) .catch(() => createError("Ошибка получения посуды")) // eslint-disable-next-line diff --git a/front/src/lib/clients/UserClient.js b/front/src/lib/clients/UserClient.js index 4602a18..2b37627 100644 --- a/front/src/lib/clients/UserClient.js +++ b/front/src/lib/clients/UserClient.js @@ -5,7 +5,7 @@ class UserClient { async getMe() { try{ - let url = requests.users.getMe + let url = requests.auth.getMe const response = await api().get(url); return {data: response.data} } catch (e) { diff --git a/front/src/lib/clients/api.js b/front/src/lib/clients/api.js index d7c859a..6d7d2c2 100644 --- a/front/src/lib/clients/api.js +++ b/front/src/lib/clients/api.js @@ -1,7 +1,7 @@ import axios from "axios"; import {tokenUtil} from "../TokenUtil"; -const host = "localhost:8080"; //дебаг вместе с беком +const host = "localhost:8081"; //дебаг вместе с беком // const host = "192.168.1.100:8091"; //дебаг фронта // const host = "bar.kayashov.keenetic.pro"; //прод export const api = () => { diff --git a/front/src/requests.js b/front/src/requests.js index b6b422c..21e60d3 100644 --- a/front/src/requests.js +++ b/front/src/requests.js @@ -2,71 +2,56 @@ const host = "api/"; const routes = { auth: host + "auth/", - users: host + "users/", - operations: host + "operations/", bar: host + "bar/", - session: host + "bar/session", + category: host + "category", + cocktail: host + "cocktail", + glass: host + "glass", ingredient: host + "ingredient", - order: host + "order", - cocktails: host + "cocktail", - visitor: host + "visitors" + receipt: host + "receipt", + unit: host + "unit", } export const requests = { auth: { login: routes.auth + "login", refresh: routes.auth + "refresh", - singOut: "signOut" - }, - cocktails: { - menu: routes.cocktails + "/menu", - simple: routes.cocktails + "/simple", - cocktail: routes.cocktails + "?id=", - modal: routes.cocktails + "/modal?id=", - edit: routes.cocktails, - savePhoto: routes.cocktails + "/photo", - favourite: routes.cocktails + "/favourite?id=", - rating: routes.cocktails + "/rating?id=", - receipts: routes.cocktails + "/receipts?id=", - byIngredient: routes.cocktails + "/byIngredient?id=", - instructions: routes.cocktails + "/instructions?id=", - calc: routes.cocktails + "/calc", - }, - visitors: { - all: routes.visitor, - invite: routes.visitor + "/invite?" + singOut: "signOut", + getMe: routes.auth + "getMe", }, bar: { - list: routes.bar + "all", - change: routes.bar + "change", crud: routes.bar, - addToMyList: routes.bar + "addToMyList", - enter: routes.bar + "enter?id=", - pay: routes.order + "?", - order: routes.order, - myOrders: routes.order + "/my", - purchases: routes.bar + "purchases", - menu: routes.bar + "menu", - ingredients: routes.ingredient, - ingredientSimple: routes.ingredient + "/simple", - ingredient: routes.ingredient, - ingredientList: routes.ingredient + "/all", - glass: routes.bar + "glass", - category: routes.bar + "category", - receipts: routes.bar + "receipt?id=", - tags: routes.bar + "tags", + all: routes.bar + "all", + change: routes.bar + "change", + }, + category: { + basic: routes.category, + }, + cocktails: { + menu: routes.cocktail + "/menu", + calc: routes.cocktail + "/calc", + byIngredient: routes.cocktail + "/byIngredient?id=", + photo: routes.cocktail + "/photo", + cocktail: routes.cocktail + "?id=", + basic: routes.cocktail, + simple: routes.cocktail + "/simple", + modal: routes.cocktail + "/modal?id=", + favourite: routes.cocktail + "/favourite?id=", + rating: routes.cocktail + "/rating?id=", + receipts: routes.cocktail + "/receipts?id=", + }, + glass: { + list: routes.glass, + }, + ingredient: { + all: routes.ingredient + "/all", + simple: routes.ingredient + "/simple", type: routes.ingredient + "/type", - session: { - status: routes.session + "/info", - change: routes.session - }, - unit: routes.bar + "units" + crud: routes.ingredient, }, - users: { - getMe: routes.bar + "getMe", - }, - operations: { - getAll: routes.operations, - create: routes.operations, - } + // receipt: { + // receipts: routes.bar + "receipt?id=", + // + // }, + + unit: routes.unit + "/units" } \ No newline at end of file diff --git a/src/main/java/ru/kayashov/bar/controller/AuthController.java b/src/main/java/ru/kayashov/bar/controller/AuthController.java index e40bf57..0edd3bf 100644 --- a/src/main/java/ru/kayashov/bar/controller/AuthController.java +++ b/src/main/java/ru/kayashov/bar/controller/AuthController.java @@ -4,6 +4,7 @@ import io.jsonwebtoken.Claims; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -11,9 +12,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import ru.kayashov.bar.controller.dto.AuthRequestDto; import ru.kayashov.bar.controller.dto.AuthResponseDto; +import ru.kayashov.bar.controller.dto.VisitorResponseDto; import ru.kayashov.bar.model.entity.Visitor; import ru.kayashov.bar.repository.VisitorsRepository; import ru.kayashov.bar.security.JwtTokenProvider; +import ru.kayashov.bar.service.VisitorService; import javax.annotation.security.PermitAll; import java.nio.charset.StandardCharsets; @@ -29,6 +32,7 @@ public class AuthController { private final JwtTokenProvider jwtTokenProvider; private final VisitorsRepository visitorsRepository; private final PasswordEncoder passwordEncoder; + private final VisitorService visitorService; @PermitAll @PostMapping("/login") @@ -40,6 +44,45 @@ public class AuthController { } } + @PermitAll + @PostMapping("refresh") + public AuthResponseDto refreshToken(@RequestHeader("Authorization") String token) { + Claims claims = jwtTokenProvider.extractAllClaims(token); + Long visitorId = claims.get("id", Long.class); + log.info("обновление токена для пользователя {}", visitorId); + Visitor visitor = visitorsRepository.findById(visitorId).orElseThrow(); + return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null); + } + + @GetMapping("/getMe") + public VisitorResponseDto getMe() { + Visitor visitor = visitorService.getCurrentVisitor(); + VisitorResponseDto dto = VisitorResponseDto.mapToDto(visitor, true, visitor.getRole().toString(), true); + log.info("Запрос информации о пользователе: {}-{} {}, вошел в бар", + dto.getId(), + dto.getName().strip(), + dto.getLastName() != null ? dto.getLastName().strip() : ""); + return dto; + } + + private AuthResponseDto checkLogin(String login, String password) { + if (login == null || login.isEmpty() || password == null || password.isEmpty()) { + return new AuthResponseDto(null, "Поля не могут быть пустые"); + } + + Optional visitorOpt = visitorsRepository.findByLogin(login); + if (visitorOpt.isEmpty()) { + return new AuthResponseDto(null, "Не найдет пользователь " + login); + } + Visitor visitor = visitorOpt.get(); + log.info("Попытка авторизации пользователя {}", visitor.getId()); + if (passwordEncoder.matches(password, visitor.getPassword())) { + return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null); + } else { + return new AuthResponseDto(null, "Неверный логин или пароль"); + } + } + private AuthResponseDto parseCode(String code) { String decode = new String(Base64.getDecoder().decode(code), StandardCharsets.UTF_8); String[] decodeArr = decode.split(":"); @@ -59,32 +102,4 @@ public class AuthController { return new AuthResponseDto(null, "Неверный код подтверждения"); } - private AuthResponseDto checkLogin(String login, String password) { - if (login == null || login.isEmpty() || password == null || password.isEmpty()) { - return new AuthResponseDto(null, "Поля не могут быть пустые"); - } - - Optional visitorOpt = visitorsRepository.findByLogin(login); - if (visitorOpt.isEmpty()) { - return new AuthResponseDto(null, "Не найдет пользователь " + login); - } - Visitor visitor = visitorOpt.get(); - log.info("Попытка авторизации пользователя {}", visitor.getId()); - if (passwordEncoder.matches(password, visitor.getPassword())) { - return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null); - } else { - return new AuthResponseDto(null, "Неверный логин или пароль"); - } - } - - @PermitAll - @PostMapping("refresh") - public AuthResponseDto refreshToken(@RequestHeader("Authorization") String token) { - Claims claims = jwtTokenProvider.extractAllClaims(token); - Long visitorId = claims.get("id", Long.class); - log.info("обновление токена для пользователя {}", visitorId); - Visitor visitor = visitorsRepository.findById(visitorId).orElseThrow(); - return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null); - } - } diff --git a/src/main/java/ru/kayashov/bar/controller/BarController.java b/src/main/java/ru/kayashov/bar/controller/BarController.java index ee856fd..dbc7f4a 100644 --- a/src/main/java/ru/kayashov/bar/controller/BarController.java +++ b/src/main/java/ru/kayashov/bar/controller/BarController.java @@ -8,86 +8,38 @@ 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.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import ru.kayashov.bar.controller.dto.VisitorResponseDto; import ru.kayashov.bar.controller.dto.bar.BarResponseDto; -import ru.kayashov.bar.controller.dto.cocktail.ReceiptResponseDto; -import ru.kayashov.bar.model.entity.Category; -import ru.kayashov.bar.model.entity.Glass; -import ru.kayashov.bar.model.entity.Unit; -import ru.kayashov.bar.model.entity.Visitor; -import ru.kayashov.bar.repository.UnitRepository; -import ru.kayashov.bar.service.SessionService; -import ru.kayashov.bar.service.VisitorService; +import ru.kayashov.bar.service.BarService; -import javax.annotation.security.PermitAll; -import java.util.Arrays; import java.util.List; @Slf4j @CrossOrigin(origins = {"*"}) @RestController -@RequestMapping("/api/bar/") +@RequestMapping("/api/bar") @RequiredArgsConstructor public class BarController { - private final SessionService sessionService; - private final VisitorService visitorService; - private final UnitRepository unitRepository; - - @PermitAll - @GetMapping("/units") - public List getUnitList() { - return unitRepository.findAll(); - } - - @PermitAll - @GetMapping("/glass") - public List getGlass() { - return Arrays.stream(Glass.values()).map(Glass::getName).toList(); - } - - @PermitAll - @GetMapping("/category") - public List getCategory() { - return Arrays.stream(Category.values()).map(Category::getName).toList(); - } - - @PermitAll - @GetMapping("/receipt") - public List getReceipt(@RequestParam("id") Long id) { - return sessionService.getReceiptList(id); - } + private final BarService barService; @PostMapping("/change/{id}") public void changeActiveBar(@PathVariable Long id) { - sessionService.changeActiveBar(id); + barService.changeActiveBar(id); } @DeleteMapping("/{id}") public void deleteBar(@PathVariable Long id) { - sessionService.deleteBar(id); + barService.deleteBar(id); } @PostMapping("/{name}") public BarResponseDto createBar(@PathVariable String name) { - return sessionService.createBar(name); + return barService.createBar(name); } @GetMapping("/all") public List getAll() { - return sessionService.findAllBar(); - } - - @GetMapping("/getMe") - public VisitorResponseDto getMe() { - Visitor visitor = visitorService.getCurrentVisitor(); - VisitorResponseDto dto = VisitorResponseDto.mapToDto(visitor, true, visitor.getRole().toString(), true); - log.info("Запрос информации о пользователе: {}-{} {}, вошел в бар", - dto.getId(), - dto.getName().strip(), - dto.getLastName() != null ? dto.getLastName().strip() : ""); - return dto; + return barService.findAllBar(); } } diff --git a/src/main/java/ru/kayashov/bar/controller/CategoryController.java b/src/main/java/ru/kayashov/bar/controller/CategoryController.java new file mode 100644 index 0000000..b132443 --- /dev/null +++ b/src/main/java/ru/kayashov/bar/controller/CategoryController.java @@ -0,0 +1,25 @@ +package ru.kayashov.bar.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.kayashov.bar.model.entity.Category; + +import javax.annotation.security.PermitAll; +import java.util.Arrays; +import java.util.List; + +@Slf4j +@CrossOrigin(origins = {"*"}) +@RestController +@RequestMapping("/api/category") +public class CategoryController { + + @PermitAll + @GetMapping + public List getCategory() { + return Arrays.stream(Category.values()).map(Category::getName).toList(); + } +} diff --git a/src/main/java/ru/kayashov/bar/controller/CocktailController.java b/src/main/java/ru/kayashov/bar/controller/CocktailController.java index eb6856e..0fd5b77 100644 --- a/src/main/java/ru/kayashov/bar/controller/CocktailController.java +++ b/src/main/java/ru/kayashov/bar/controller/CocktailController.java @@ -49,11 +49,6 @@ public class CocktailController { return cocktailService.calc(); } - @GetMapping("/instructions") - public String getInstructions(@RequestParam("id") Long id) { - return cocktailService.findInstructions(id); - } - @GetMapping("/byIngredient") public List getByIngredient(@RequestParam Long id) { return cocktailService.findByIngredient(id); @@ -77,11 +72,6 @@ public class CocktailController { return cocktailService.getSimple(); } - @GetMapping("/receipts") - public List getReceipts(@RequestParam Long id) { - return cocktailService.getReceipts(id); - } - @GetMapping("/modal") public CocktailModalDto getForModal(@RequestParam Long id) { return cocktailService.getForModal(id); diff --git a/src/main/java/ru/kayashov/bar/controller/GlassController.java b/src/main/java/ru/kayashov/bar/controller/GlassController.java new file mode 100644 index 0000000..aaadfa7 --- /dev/null +++ b/src/main/java/ru/kayashov/bar/controller/GlassController.java @@ -0,0 +1,27 @@ +package ru.kayashov.bar.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.kayashov.bar.model.entity.Glass; + +import javax.annotation.security.PermitAll; +import java.util.Arrays; +import java.util.List; + +@Slf4j +@CrossOrigin(origins = {"*"}) +@RestController +@RequestMapping("/api/glass") +@RequiredArgsConstructor +public class GlassController { + + @PermitAll + @GetMapping + public List getGlass() { + return Arrays.stream(Glass.values()).map(Glass::getName).toList(); + } +} diff --git a/src/main/java/ru/kayashov/bar/controller/IngredientController.java b/src/main/java/ru/kayashov/bar/controller/IngredientController.java index 47f1b38..fd873cb 100644 --- a/src/main/java/ru/kayashov/bar/controller/IngredientController.java +++ b/src/main/java/ru/kayashov/bar/controller/IngredientController.java @@ -39,6 +39,8 @@ public class IngredientController { return ingredientService.getAllSimple(); } + //todo: перевести на enum + @Deprecated @GetMapping("/type") public List getTypes() { return typeRepository.findAll().stream() diff --git a/src/main/java/ru/kayashov/bar/controller/ReceiptController.java b/src/main/java/ru/kayashov/bar/controller/ReceiptController.java new file mode 100644 index 0000000..d3a2214 --- /dev/null +++ b/src/main/java/ru/kayashov/bar/controller/ReceiptController.java @@ -0,0 +1,30 @@ +package ru.kayashov.bar.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import ru.kayashov.bar.controller.dto.cocktail.ReceiptResponseDto; +import ru.kayashov.bar.service.ReceiptService; + +import javax.annotation.security.PermitAll; +import java.util.List; + +@Slf4j +@CrossOrigin(origins = {"*"}) +@RestController +@RequestMapping("/api/receipt") +@RequiredArgsConstructor +public class ReceiptController { + + private final ReceiptService receiptService; + + @PermitAll + @GetMapping + public List getReceipt(@RequestParam("id") Long id) { + return receiptService.getReceiptList(id); + } +} diff --git a/src/main/java/ru/kayashov/bar/controller/UnitController.java b/src/main/java/ru/kayashov/bar/controller/UnitController.java new file mode 100644 index 0000000..bbf4ed1 --- /dev/null +++ b/src/main/java/ru/kayashov/bar/controller/UnitController.java @@ -0,0 +1,29 @@ +package ru.kayashov.bar.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.kayashov.bar.model.entity.Unit; +import ru.kayashov.bar.repository.UnitRepository; + +import javax.annotation.security.PermitAll; +import java.util.List; + +@Slf4j +@CrossOrigin(origins = {"*"}) +@RestController +@RequestMapping("/api/unit") +@RequiredArgsConstructor +public class UnitController { + + private final UnitRepository unitRepository; + + @PermitAll + @GetMapping("/units") + public List getUnitList() { + return unitRepository.findAll(); + } +} diff --git a/src/main/java/ru/kayashov/bar/controller/dto/VisitorResponseDto.java b/src/main/java/ru/kayashov/bar/controller/dto/VisitorResponseDto.java index 40f873e..4eadc7c 100644 --- a/src/main/java/ru/kayashov/bar/controller/dto/VisitorResponseDto.java +++ b/src/main/java/ru/kayashov/bar/controller/dto/VisitorResponseDto.java @@ -21,8 +21,7 @@ public class VisitorResponseDto { d.setId(e.getId()); d.setName(e.getName()); d.setLastName(e.getLastName()); -// d.setInvited(e.getInvited()); -// d.setRole(e.getRole().toString()); + d.setRole(e.getRole().toString()); return d; } diff --git a/src/main/java/ru/kayashov/bar/controller/dto/cocktail/CocktailForListResponseDto.java b/src/main/java/ru/kayashov/bar/controller/dto/cocktail/CocktailForListResponseDto.java index e6d1a37..a9fb810 100644 --- a/src/main/java/ru/kayashov/bar/controller/dto/cocktail/CocktailForListResponseDto.java +++ b/src/main/java/ru/kayashov/bar/controller/dto/cocktail/CocktailForListResponseDto.java @@ -37,27 +37,4 @@ public class CocktailForListResponseDto { private List receipt; private RatingResponseDto rating; - - public static CocktailForListResponseDto mapToDto(CocktailEntity e, Long visitorId) { - CocktailForListResponseDto d = new CocktailForListResponseDto(); - d.setId(e.getId()); - d.setName(e.getName()); - d.setImage(e.getImage()); - d.setVideo(e.getVideo()); - d.setInstructions(e.getInstructions()); - - d.setCategory(e.getCategory().getName()); - d.setAlcoholic(e.getAlcoholic().getValue()); - d.setGlass(e.getGlass().getName()); - - String components = e.getReceipt().stream().map(r -> r.getIngredient().getName()).collect(Collectors.joining(", ")); - d.setComponents(components); - d.setReceipt(e.getReceipt().stream().map(ReceiptResponseDto::mapToDto).toList()); - - RatingResponseDto rating = new RatingResponseDto(); - rating.setFavourite(e.getIsFavorite()); - rating.setRating(e.getRating()); - d.setRating(rating); - return d; - } } diff --git a/src/main/java/ru/kayashov/bar/controller/dto/ingredient/IngredientResponseDto.java b/src/main/java/ru/kayashov/bar/controller/dto/ingredient/IngredientResponseDto.java index 86e8091..b4e757e 100644 --- a/src/main/java/ru/kayashov/bar/controller/dto/ingredient/IngredientResponseDto.java +++ b/src/main/java/ru/kayashov/bar/controller/dto/ingredient/IngredientResponseDto.java @@ -15,7 +15,6 @@ import ru.kayashov.bar.model.entity.IngredientEntity; public class IngredientResponseDto { private Long id; private String name; -// private String enName; private Boolean alcohol; private Integer abv; private boolean isHave; @@ -29,11 +28,10 @@ public class IngredientResponseDto { .builder() .id(i.getId()) .name(i.getName()) -// .enName(i.getEnName()) .alcohol(i.getAlcohol()) .type(i.getType() != null ? i.getType().getName() : null) .abv(i.getAbv()) -// .isHave(i.getIsHave()) + .isHave(i.getIsHave()) .image("https://thecocktaildb.com/images/ingredients/" + i.getEnName() + "-Medium.png") .description(i.getDescription()) .build(); diff --git a/src/main/java/ru/kayashov/bar/mapper/CocktailMapper.java b/src/main/java/ru/kayashov/bar/mapper/CocktailMapper.java index 68e1873..d500d87 100644 --- a/src/main/java/ru/kayashov/bar/mapper/CocktailMapper.java +++ b/src/main/java/ru/kayashov/bar/mapper/CocktailMapper.java @@ -12,15 +12,12 @@ import ru.kayashov.bar.controller.dto.cocktail.CocktailModalDto; import ru.kayashov.bar.controller.dto.cocktail.RatingResponseDto; import ru.kayashov.bar.controller.dto.cocktail.ReceiptResponseDto; import ru.kayashov.bar.controller.dto.ingredient.IngredientSimpleResponseDto; -import ru.kayashov.bar.model.entity.BarEntity; import ru.kayashov.bar.model.entity.CocktailEntity; import ru.kayashov.bar.model.entity.IngredientEntity; import ru.kayashov.bar.model.entity.ReceiptEntity; import ru.kayashov.bar.model.entity.Visitor; -import ru.kayashov.bar.repository.BarEntityRepository; import ru.kayashov.bar.repository.VisitorsRepository; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -29,22 +26,15 @@ import java.util.stream.Collectors; public class CocktailMapper { private final VisitorsRepository visitorsRepository; - private final BarEntityRepository barRepository; @Transactional public List cocktailsToDtoList(List cocktails, Boolean all, boolean withReceipts) { - Visitor visitor = getCurrentVisitor(); - List barStopList = new ArrayList<>(); - List allowedIngredients = getAllowedIngredients(); return cocktails.stream() - .map(c -> cocktailToDto(c, visitor, allowedIngredients, barStopList, withReceipts)) -// .filter(c -> all || c.getIsAllowed()) -// .filter(c -> all || c.getInMenu()) + .map(c -> cocktailToDto(c, withReceipts)) .toList(); } public CocktailForListResponseDto cocktailToFullDto(CocktailEntity e) { - List allowed = getAllowedIngredients(); return CocktailForListResponseDto.builder() .id(e.getId()) .name(e.getName()) @@ -54,11 +44,11 @@ public class CocktailMapper { .glass(e.getGlass().getName()) .instructions(e.getInstructions()) .video(e.getVideo()) - .receipt(createReceiptDtoList(e.getReceipt(), allowed)) + .receipt(createReceiptDtoList(e.getReceipt())) .build(); } - private CocktailForListResponseDto cocktailToDto(CocktailEntity e, Visitor visitor, List allowedIngredients, List barStopList, boolean withReceipts) { + private CocktailForListResponseDto cocktailToDto(CocktailEntity e, boolean withReceipts) { boolean hasError = false; int volume = 0; Float abv = 0f; @@ -103,35 +93,11 @@ public class CocktailMapper { .glass(e.getGlass().getName()) .components(containCocktailComponents(e.getReceipt())) .rating(createRatingDto(e)) - .isAllowed(calculateAllowed(e.getReceipt(), allowedIngredients)) - .inMenu(!barStopList.contains(e.getId())) + .isAllowed(e.getAllowed()) .receipt(!withReceipts ? null : e.getReceipt().stream().map(ReceiptResponseDto::mapToDto).toList()) .build(); } - private List getAllowedIngredients() { - return barRepository.findByActiveTrue() - .map(BarEntity::getIngredients) - .orElseThrow() - .stream() - .map(IngredientEntity::getId) - .toList(); -// return visitor.getResidents().stream() -// .filter(BarResident::getActive) -// .map(BarResident::getBar) -// .map(BarEntity::getIngredients) -// .flatMap(List::stream) -// .map(BarIngredientStorage::getIngredient) -// .map(IngredientEntity::getId) -// .toList(); - } - - private Boolean calculateAllowed(List e, List allowedIngredients) { - return e.stream() - .map(ReceiptEntity::getIngredient) - .allMatch(i -> allowedIngredients.contains(i.getId())); - } - private RatingResponseDto createRatingDto(CocktailEntity entity) { RatingResponseDto result = new RatingResponseDto(); result.setRating(entity.getRating()); @@ -159,35 +125,37 @@ public class CocktailMapper { } public CocktailModalDto cocktailToModalDto(CocktailEntity e) { - List allowedIngredients = getAllowedIngredients(); return CocktailModalDto.builder() .id(e.getId()) .name(e.getName()) .image(e.getImage()) .instructions(e.getInstructions()) .rating(createRatingDto(e)) - .receipt(createReceiptDtoList(e.getReceipt(), allowedIngredients)) + .receipt(createReceiptDtoList(e.getReceipt())) .build(); } - private List createReceiptDtoList(List receipts, List allowedIngredients) { + private List createReceiptDtoList(List receipts) { return receipts.stream() - .map(r -> createReceiptDto(r, allowedIngredients)) + .map(this::createReceiptDto) .toList(); } - private ReceiptResponseDto createReceiptDto(ReceiptEntity e, List allowedIngredients) { + private ReceiptResponseDto createReceiptDto(ReceiptEntity e) { return ReceiptResponseDto.builder() .id(e.getId()) - .ingredient(createIngredientResponseDto(e.getIngredient(), allowedIngredients)) + .ingredient(createIngredientResponseDto(e.getIngredient())) .count(e.getCount()) .unit(e.getUnit()) .measure(e.getMeasure()) .build(); } - private IngredientSimpleResponseDto createIngredientResponseDto(IngredientEntity i, List allowedIngredients) { - return new IngredientSimpleResponseDto(i.getId(), i.getName(), "https://thecocktaildb.com/images/ingredients/" + i.getEnName() + "-Medium.png", allowedIngredients.contains(i.getId())); + private IngredientSimpleResponseDto createIngredientResponseDto(IngredientEntity i) { + return new IngredientSimpleResponseDto(i.getId(), + i.getName(), + "https://thecocktaildb.com/images/ingredients/" + i.getEnName() + "-Medium.png", + i.getIsHave()); } diff --git a/src/main/java/ru/kayashov/bar/mapper/IngredientMapper.java b/src/main/java/ru/kayashov/bar/mapper/IngredientMapper.java index eb44bdc..9ffb41d 100644 --- a/src/main/java/ru/kayashov/bar/mapper/IngredientMapper.java +++ b/src/main/java/ru/kayashov/bar/mapper/IngredientMapper.java @@ -4,9 +4,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import ru.kayashov.bar.controller.dto.ingredient.IngredientResponseDto; import ru.kayashov.bar.controller.dto.ingredient.IngredientSimpleResponseDto; -import ru.kayashov.bar.model.entity.BarEntity; import ru.kayashov.bar.model.entity.IngredientEntity; -import ru.kayashov.bar.repository.BarEntityRepository; import java.util.List; @@ -14,25 +12,13 @@ import java.util.List; @RequiredArgsConstructor public class IngredientMapper { - private final BarEntityRepository barRepository; - public List mapIngredientsToDtoList(List ingredients) { - List allowedIngredients = getAllowedIngredients(); return ingredients.stream() - .map(i -> mapIngredientToDto(i, allowedIngredients)) + .map(this::mapIngredientToDto) .toList(); } - private List getAllowedIngredients() { - return barRepository.findByActiveTrue() - .map(BarEntity::getIngredients) - .orElseThrow() - .stream() - .map(IngredientEntity::getId) - .toList(); - } - - private IngredientResponseDto mapIngredientToDto(IngredientEntity i, List allowedIngredients) { + private IngredientResponseDto mapIngredientToDto(IngredientEntity i) { return IngredientResponseDto .builder() .id(i.getId()) @@ -40,22 +26,21 @@ public class IngredientMapper { .alcohol(i.getAlcohol()) .type(i.getType() != null ? i.getType().getName() : null) .abv(i.getAbv()) - .isHave(allowedIngredients.contains(i.getId())) + .isHave(i.getIsHave()) .image("https://thecocktaildb.com/images/ingredients/" + i.getEnName() + "-Medium.png") .description(i.getDescription()) .build(); } public List mapIngredientsToSimpleDtoList(List ingredients) { - List allowedIngredients = getAllowedIngredients(); return ingredients.stream() - .map(i -> mapIngredientToSimpleDto(i, allowedIngredients)) + .map(this::mapIngredientToSimpleDto) .toList(); } - private IngredientSimpleResponseDto mapIngredientToSimpleDto(IngredientEntity i, List allowedIngredients) { + private IngredientSimpleResponseDto mapIngredientToSimpleDto(IngredientEntity i) { return new IngredientSimpleResponseDto(i.getId(), i.getName(), "https://thecocktaildb.com/images/ingredients/" + i.getEnName() + "-Medium.png", - allowedIngredients.contains(i.getId())); + i.getIsHave()); } } diff --git a/src/main/java/ru/kayashov/bar/model/entity/Category.java b/src/main/java/ru/kayashov/bar/model/entity/Category.java index e7b53fc..174fb84 100644 --- a/src/main/java/ru/kayashov/bar/model/entity/Category.java +++ b/src/main/java/ru/kayashov/bar/model/entity/Category.java @@ -7,16 +7,10 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public enum Category { COCKTAIL("Коктейль"), - PUNCH("Пунш"), - SHAKE("Шейк"), - OTHER("Другие"), BEER("Пиво"), - HOMEMADE_LIQUEUR("Домашний ликер"), SHOT("Шот"), - COCOA("Какао"), COFFEE_TEA("Кофе-Чай"), - SOFT("Безалкогольный напиток"), - ORDINARY("Обычный напиток"); + SOFT("Безалкогольный напиток"); private final String name; diff --git a/src/main/java/ru/kayashov/bar/model/entity/CocktailEntity.java b/src/main/java/ru/kayashov/bar/model/entity/CocktailEntity.java index ed1bd46..b669138 100644 --- a/src/main/java/ru/kayashov/bar/model/entity/CocktailEntity.java +++ b/src/main/java/ru/kayashov/bar/model/entity/CocktailEntity.java @@ -27,6 +27,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor public class CocktailEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -46,10 +47,12 @@ public class CocktailEntity { @Enumerated(EnumType.STRING) private Glass glass; - private Integer rating; + private Boolean allowed; + + private Integer rating = 0; @Column(name = "favourite") - private Boolean isFavorite; + private Boolean isFavorite = false; @OneToMany(mappedBy = "cocktail", cascade = CascadeType.REMOVE) private List receipt; diff --git a/src/main/java/ru/kayashov/bar/model/entity/Glass.java b/src/main/java/ru/kayashov/bar/model/entity/Glass.java index ae9cb61..d793aa3 100644 --- a/src/main/java/ru/kayashov/bar/model/entity/Glass.java +++ b/src/main/java/ru/kayashov/bar/model/entity/Glass.java @@ -6,23 +6,20 @@ import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor public enum Glass { - HIGHBALL("Хайболл"), - COCKTAIL("Коктейльный бокал"), - COLLINS("Стакан"), - POUSSE("Рюмка на ножке"), - CHAMPAGNE("Бокал флюте"), - BRANDY("Коньячный бокал"), - HURRICANE("Ураган"), - COFFEE("Кофейная кружка"), - SHOT("Рюмка"), - JAR("Банка"), - PITCHER("Кувшин"), - CORDIAL("Ликерная рюмка"), - BEER("Пивной бокал"), - WINE("Бокал для вина"), - MARGARITA("Бокал Маргарита"); + HIGHBALL("Хайболл",250), + COCKTAIL("Коктейльный бокал",120), + COLLINS("Стакан", 200), + CHAMPAGNE("Бокал флюте", 200), + HURRICANE("Ураган", 350), + COFFEE("Кофейная кружка", 250), + SHOT("Рюмка",50), + CORDIAL("Ликерная рюмка",150), + BEER("Пивной бокал", 500), + WINE("Бокал для вина", 350), + MARGARITA("Бокал Маргарита", 260); private final String name; + private final Integer capacity; public static Glass findValue(String name) { for (Glass glass : Glass.values()) { diff --git a/src/main/java/ru/kayashov/bar/model/entity/IngredientEntity.java b/src/main/java/ru/kayashov/bar/model/entity/IngredientEntity.java index f866d79..e92a3fe 100644 --- a/src/main/java/ru/kayashov/bar/model/entity/IngredientEntity.java +++ b/src/main/java/ru/kayashov/bar/model/entity/IngredientEntity.java @@ -26,6 +26,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor public class IngredientEntity { + @Id private Long id; private String name; @@ -44,7 +45,7 @@ public class IngredientEntity { @JoinColumn(name = "type") private TypeEntity type; - @ManyToMany(cascade = CascadeType.REMOVE) + @ManyToMany @JoinTable( name = "bar_ingredient", joinColumns = @JoinColumn(name = "ingredient"), diff --git a/src/main/java/ru/kayashov/bar/repository/CocktailRepository.java b/src/main/java/ru/kayashov/bar/repository/CocktailRepository.java index 66ef64b..8b0e16d 100644 --- a/src/main/java/ru/kayashov/bar/repository/CocktailRepository.java +++ b/src/main/java/ru/kayashov/bar/repository/CocktailRepository.java @@ -8,11 +8,17 @@ import org.springframework.transaction.annotation.Transactional; import ru.kayashov.bar.model.entity.CocktailEntity; public interface CocktailRepository extends JpaRepository { + @Modifying @Transactional @Query("UPDATE CocktailEntity c SET c.isFavorite = :favorite WHERE c.id = :id") void updateFavouriteById(@Param("id") Long id, @Param("favorite") Boolean favorite); + @Modifying + @Transactional + @Query("UPDATE CocktailEntity c SET c.allowed = false WHERE c.allowed = true") + void markAllAsNotAllowed(); + @Modifying @Transactional @Query("UPDATE CocktailEntity c SET c.rating = :rating WHERE c.id = :id") diff --git a/src/main/java/ru/kayashov/bar/service/BarService.java b/src/main/java/ru/kayashov/bar/service/BarService.java new file mode 100644 index 0000000..c31c660 --- /dev/null +++ b/src/main/java/ru/kayashov/bar/service/BarService.java @@ -0,0 +1,101 @@ +package ru.kayashov.bar.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.kayashov.bar.controller.dto.bar.BarResponseDto; +import ru.kayashov.bar.model.entity.BarEntity; +import ru.kayashov.bar.model.entity.CocktailEntity; +import ru.kayashov.bar.model.entity.IngredientEntity; +import ru.kayashov.bar.model.entity.ReceiptEntity; +import ru.kayashov.bar.repository.BarEntityRepository; +import ru.kayashov.bar.repository.CocktailRepository; +import ru.kayashov.bar.repository.IngredientRepository; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class BarService { + + private final BarEntityRepository barEntityRepository; + private final IngredientRepository ingredientRepository; + private final CocktailRepository cocktailRepository; + +// @Transactional + public void changeActiveBar(Long id) { + Optional lastBarOpt = barEntityRepository.findByActiveTrue(); + if (lastBarOpt.isPresent()) { + BarEntity lastBar = lastBarOpt.get(); + + lastBar.setActive(false); + barEntityRepository.save(lastBar); + + lastBar.getIngredients().stream() + .peek(i -> i.setIsHave(false)) + .forEach(ingredientRepository::save); + + cocktailRepository.markAllAsNotAllowed(); + + log.info("Бар {} отключен", lastBar.getName()); + } + + BarEntity barEntity = barEntityRepository.findById(id).orElseThrow(); + barEntity.setActive(true); + + List ingredients = barEntity.getIngredients().stream() + .peek(i -> i.setIsHave(true)) + .map(ingredientRepository::save) + .toList(); + + cocktailRepository.saveAll(findAllowedCocktails(ingredients)); + + barEntityRepository.save(barEntity); + log.info("Бар {} подключен", barEntity.getName()); + } + + public List findAllBar() { + List barEntities = barEntityRepository.findAll(); + log.info("По запросу найдено {} баров", barEntities.size()); + return barEntities.stream() + .map(BarResponseDto::mapToDto) + .toList(); + } + + public void deleteBar(Long id) { + barEntityRepository.deleteById(id); + log.info("Бар с id {} удален", id); + } + + public BarResponseDto createBar(String name) { + BarEntity bar = new BarEntity(); + bar.setName(name); + bar.setActive(false); + bar = barEntityRepository.save(bar); + + log.info("Создан бар {}", name); + + return BarResponseDto.mapToDto(bar); + } + + private List findAllowedCocktails(List ingredients) { + List result = new ArrayList<>(); + for (IngredientEntity ingredient : ingredients) { + List cocktails = ingredient.getReceipts().stream() + .map(ReceiptEntity::getCocktail) + .toList(); + + for (CocktailEntity cocktail : cocktails) { + if (cocktail.getReceipt().stream().allMatch(r -> r.getIngredient().getIsHave())) { + cocktail.setAllowed(true); + result.add(cocktail); + } + } + } + return result; + } +} diff --git a/src/main/java/ru/kayashov/bar/service/CocktailService.java b/src/main/java/ru/kayashov/bar/service/CocktailService.java index 8345161..9412e53 100644 --- a/src/main/java/ru/kayashov/bar/service/CocktailService.java +++ b/src/main/java/ru/kayashov/bar/service/CocktailService.java @@ -15,6 +15,7 @@ import ru.kayashov.bar.controller.dto.cocktail.CocktailModalDto; import ru.kayashov.bar.controller.dto.cocktail.CocktailSimpleResponseDto; import ru.kayashov.bar.controller.dto.cocktail.ReceiptResponseDto; import ru.kayashov.bar.controller.dto.cocktail.SortingEnum; +import ru.kayashov.bar.controller.dto.ingredient.IngredientSimpleResponseDto; import ru.kayashov.bar.mapper.CocktailMapper; import ru.kayashov.bar.model.entity.Alcoholic; import ru.kayashov.bar.model.entity.Category; @@ -40,8 +41,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; @Slf4j @Service @@ -90,9 +89,7 @@ public class CocktailService { criteriaQuery.distinct(true); if (!dto.getAll()) { -// List cocktailIds = findICountCocktailIds(0, new ArrayList<>()); - List cocktailIds = findCocktailByCountNotHaveIngredient(); - Predicate pr = root.get("id").in(cocktailIds); + Predicate pr = cb.isTrue(root.get("allowed")); predicates.add(pr); } @@ -123,18 +120,6 @@ public class CocktailService { predicates.add(root.get("alcoholic").in(dto.getAlcohol().stream().map(Alcoholic::findValue).toList())); } - if (dto.getNotHaveCount() != null) { - List approveCocktail = findICountCocktailIds(dto.getNotHaveCount(), dto.getIngredient()); - predicates.add(root.get("id").in(approveCocktail)); - } -// -// if (!dto.getSortField().equals("name") || !dto.getSortOrder().equals("asc")) { -// cb.asc(root.get("name")); -//// query.orderBy(cb.asc(root.get("name").get(dto.getSortField()))); -// } else { -// criteriaQuery.orderBy(cb.asc(root.get("name"))); -// } - //todo: доделать другие виды сортировки Order order; switch (dto.getSort()) { @@ -154,100 +139,6 @@ public class CocktailService { return cocktailEntities; } - private List findICountCocktailIds(Integer iCount, List ingredientFilter) { - List allowedIngredient = visitorService.getAllowedIngredients(); - - Stream> receiptStream = receiptRepository.findAll() - .stream() - .collect(Collectors.groupingBy(k -> k.getCocktail().getId())) - .values() - .stream() - .filter(l -> getCountNotHaveIngredient(allowedIngredient, l).equals(iCount)); - - if (!ingredientFilter.isEmpty()) { - receiptStream = receiptStream.filter(l -> findIngredientInReceipts(ingredientFilter, l)); - } - return receiptStream - .map(l -> l.get(0)) - .map(ReceiptEntity::getCocktail) - .map(CocktailEntity::getId) - .toList(); - } - - private boolean findIngredientInReceipts(List ingredientFilter, List receipts) { - return receipts.stream().anyMatch(r -> ingredientFilter.contains(r.getIngredient().getName())); - } - - private Integer getCountNotHaveIngredient(List allowedIngredientIds, List receipts) { - return Math.toIntExact(receipts.size() - receipts.stream() - .filter(r -> allowedIngredientIds.contains(r.getIngredient().getId())) - .count()); - } - -// private List getAllowedCocktailIds(Long barId) { -// CriteriaBuilder cb = entityManager.getCriteriaBuilder(); -// CriteriaQuery query = cb.createQuery(Long.class); -// -// Root receiptRoot = query.from(ReceiptEntity.class); -// Join ingredientJoin = receiptRoot.join("ingredient", JoinType.LEFT); -// Join barIngredientStorageJoin = ingredientJoin.join("bars", JoinType.LEFT); -// -// // Внешний подзапрос с NOT EXISTS -// Subquery subquery = query.subquery(Long.class); -// Root receiptSubRoot = subquery.from(ReceiptEntity.class); -// Join ingredientSubJoin = receiptSubRoot.join("ingredient", JoinType.LEFT); -// -// // Внутренний подзапрос с NOT EXISTS -// Subquery innerSubquery = subquery.subquery(Long.class); -// Root barIngredientStorageInnerRoot = innerSubquery.from(BarIngredientStorage.class); -// -// // Условия внутреннего подзапроса -// innerSubquery.select(barIngredientStorageInnerRoot.get("id")) -// .where( -// cb.equal(barIngredientStorageInnerRoot.get("ingredient"), ingredientSubJoin.get("id")), -// cb.equal(barIngredientStorageInnerRoot.get("bar").get("id"), barId) -// ); -// -// // Условия внешнего подзапроса -// subquery.select(receiptSubRoot.get("id")) -// .where( -// cb.equal(receiptSubRoot.get("cocktail").get("id"), receiptRoot.get("cocktail").get("id")), -// cb.not(cb.exists(innerSubquery)) -// ); -// -// // Основной запрос -// query.select(receiptRoot.get("cocktail").get("id")) -// .distinct(true) -// .where( -// cb.equal(barIngredientStorageJoin.get("bar").get("id"), barId), -// cb.not(cb.exists(subquery)) -// ); -// -// return entityManager.createQuery(query).getResultList(); -// } - - /* - select cifc.cocktail_id - from (select r.cocktail_id, COUNT(CASE WHEN i.is_have THEN 0 END) as false_count - from receipt r - left join public.ingredient i on i.id = r.ingredient_id - group by r.cocktail_id) as cifc - where false_count = 0 - */ - //todo: так и не придумал я нормальный запрос - private List findCocktailByCountNotHaveIngredient() { - String sql = "SELECT cifc.cocktail_id" + - " FROM (SELECT r.cocktail_id," + - " COUNT(CASE WHEN i.is_have = false THEN 1 END) AS false_count" + - " FROM receipt r" + - " LEFT JOIN public.ingredient i ON i.id = r.ingredient_id" + - " GROUP BY r.cocktail_id) AS cifc" + - " WHERE false_count = 0"; - - javax.persistence.Query query = entityManager.createNativeQuery(sql); - return query.getResultList(); - } - public CocktailForListResponseDto findById(Long id) { CocktailEntity cocktail = repository.findById(id).orElseThrow(); return mapper.cocktailToFullDto(cocktail); @@ -267,6 +158,11 @@ public class CocktailService { .orElseThrow(() -> new RuntimeException("Не удалось найти коктейль с id " + dto.getId())); } + boolean allowed = dto.getReceipt().stream() + .map(ReceiptResponseDto::getIngredient) + .allMatch(IngredientSimpleResponseDto::getIsHave); + + cocktail.setAllowed(allowed); cocktail.setName(dto.getName()); cocktail.setInstructions(dto.getInstructions()); cocktail.setImage(dto.getImage()); @@ -275,19 +171,66 @@ public class CocktailService { cocktail.setGlass(Glass.findValue(dto.getGlass())); cocktail.setAlcoholic(Alcoholic.findValue(dto.getAlcoholic())); cocktail.setRating(cocktail.getRating()); - repository.save(cocktail); + cocktail = repository.save(cocktail); + + log.info("{} коктейль {}", dto.getId() == null ? "Создан" : "Изменен", cocktail.getName()); editCocktailReceipts(cocktail.getReceipt(), dto.getReceipt(), cocktail); } public void editFavourite(Long cocktailId, boolean put) { + log.info("Коктейль с id {} {}", cocktailId, put ? "добавлен в избранное" : "удален из избранного"); cocktailRepository.updateFavouriteById(cocktailId, put); } public void setRating(Long cocktailId, Integer rating) { + log.info("Коктейлю с id {} выставлена новая оценка {}", cocktailId, rating); cocktailRepository.updateRatingById(cocktailId, rating); } + public CocktailModalDto getForModal(Long id) { + CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new); + return mapper.cocktailToModalDto(cocktail); + } + + public List getSimple() { + return repository.findAll().stream() + .map(CocktailSimpleResponseDto::mapToDto) + .toList(); + } + + public String savePhoto(MultipartFile file) throws IOException { + File folder = new File(photoFolder); + List files = Arrays.asList(Objects.requireNonNull(folder.listFiles())); + String fileName = getPhotoPath(files, file.getOriginalFilename()); + String fullName = photoFolder + "/" + fileName; + file.transferTo(new File(fullName)); + log.info("сохранено фото {}", fileName); + return "/assets/cocktails/" + fileName; + } + + public void delete(Long id) { + CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new); + log.info("Удален коктейль {}", cocktail); + repository.delete(cocktail); + } + + public String findInstructions(Long id) { + CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new); + return cocktail.getInstructions(); + } + + public List findByIngredient(Long id) { + return ingredientRepository.findById(id).orElseThrow(RuntimeException::new) + .getReceipts() + .stream() + .map(ReceiptEntity::getCocktail) + .distinct() + .map(mapper::cocktailToIngredientDtoList) + .toList(); + } + + //todo: попробовать отыграть эту связку каскадами private void editCocktailReceipts(List old, List actual, CocktailEntity cocktail) { for (ReceiptResponseDto receipt : actual) { if (receipt.getId() == null) { @@ -335,33 +278,6 @@ public class CocktailService { receiptRepository.save(receiptEntity); } - public CocktailModalDto getForModal(Long id) { - CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new); - return mapper.cocktailToModalDto(cocktail); - } - - public List getReceipts(Long id) { - - return null; - } - - public List getSimple() { - return repository.findAll().stream() - .map(CocktailSimpleResponseDto::mapToDto) - .toList(); - } - - - public String savePhoto(MultipartFile file) throws IOException { - File folder = new File(photoFolder); - List files = Arrays.asList(Objects.requireNonNull(folder.listFiles())); - String fileName = getPhotoPath(files, file.getOriginalFilename()); - String fullName = photoFolder + "/" + fileName; - file.transferTo(new File(fullName)); - log.info("сохранено фото {}", fileName); - return "/assets/cocktails/" + fileName; - } - private String getPhotoPath(List files, String originalName) { if (files.stream().map(File::getName).anyMatch(name -> name.equals(originalName))) { String[] split = originalName.split("\\."); @@ -378,25 +294,4 @@ public class CocktailService { } return sb.toString(); } - - public void delete(Long id) { - CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new); - log.info("Удален коктейль {}", cocktail); - repository.delete(cocktail); - } - - public String findInstructions(Long id) { - CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new); - return cocktail.getInstructions(); - } - - public List findByIngredient(Long id) { - return ingredientRepository.findById(id).orElseThrow(RuntimeException::new) - .getReceipts() - .stream() - .map(ReceiptEntity::getCocktail) - .distinct() - .map(mapper::cocktailToIngredientDtoList) - .toList(); - } } diff --git a/src/main/java/ru/kayashov/bar/service/IngredientService.java b/src/main/java/ru/kayashov/bar/service/IngredientService.java index 77e77f3..00bb3e8 100644 --- a/src/main/java/ru/kayashov/bar/service/IngredientService.java +++ b/src/main/java/ru/kayashov/bar/service/IngredientService.java @@ -45,11 +45,13 @@ public class IngredientService { */ public List getAll() { List ingredients = repository.findAll(); + log.info("По запросу найдено {} ингредиентов", ingredients.size()); return mapper.mapIngredientsToDtoList(ingredients); } public List getAllSimple() { List ingredients = repository.findAll(); + log.info("По запросу найдено {} ингредиентов", ingredients.size()); return mapper.mapIngredientsToSimpleDtoList(ingredients); } @@ -60,15 +62,31 @@ public class IngredientService { public void changeBarIngredient(Long id, boolean isHave) { BarEntity bar = barEntityRepository.findByActiveTrue().orElseThrow(); IngredientEntity ingredientEntity = getIngredientById(id); - - if (isHave) { - bar.getIngredients().add(ingredientEntity); - } else { - bar.getIngredients().remove(ingredientEntity); - } ingredientEntity.setIsHave(isHave); ingredientRepository.save(ingredientEntity); + + List cocktails = ingredientEntity.getReceipts().stream().map(ReceiptEntity::getCocktail).toList(); + List listForSave; + if (isHave) { + bar.getIngredients().add(ingredientEntity); + listForSave = new ArrayList<>(); + for (CocktailEntity cocktail : cocktails) { + if (cocktail.getReceipt().stream().map(ReceiptEntity::getIngredient).allMatch(IngredientEntity::getIsHave)) { + cocktail.setAllowed(true); + listForSave.add(cocktail); + log.info("Коктейль {} стал доступен", cocktail.getName()); + } + } + } else { + bar.getIngredients().remove(ingredientEntity); + listForSave = cocktails.stream().peek(c -> c.setAllowed(false)).toList(); + log.info("Коктейли {} пропали из доступа", listForSave); + } + + cocktailRepository.saveAll(listForSave); barEntityRepository.save(bar); + + log.info("Ингредиент {} {}", ingredientEntity.getName(), isHave ? "добавлен в бар" : "удален из бара"); } public boolean saveChange(IngredientResponseDto dto) { @@ -92,6 +110,7 @@ public class IngredientService { } entity.setType(type); repository.save(entity); + log.info("Ингредиент {} изменен", entity.getName()); return true; } diff --git a/src/main/java/ru/kayashov/bar/service/ReceiptService.java b/src/main/java/ru/kayashov/bar/service/ReceiptService.java new file mode 100644 index 0000000..b7b37dd --- /dev/null +++ b/src/main/java/ru/kayashov/bar/service/ReceiptService.java @@ -0,0 +1,30 @@ +package ru.kayashov.bar.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.kayashov.bar.controller.dto.cocktail.ReceiptResponseDto; +import ru.kayashov.bar.controller.dto.ingredient.IngredientSimpleResponseDto; +import ru.kayashov.bar.model.entity.CocktailEntity; +import ru.kayashov.bar.repository.CocktailRepository; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ReceiptService { + + private final CocktailRepository cocktailRepository; + + public List getReceiptList(Long cocktailId) { + CocktailEntity cocktail = cocktailRepository.findById(cocktailId).orElseThrow(); + return cocktail.getReceipt().stream() + .map(e -> ReceiptResponseDto.builder() + .id(e.getId()) + .ingredient(IngredientSimpleResponseDto.mapToDto(e.getIngredient())) + .measure(e.getMeasure()) + .build()) + .toList(); + } +} diff --git a/src/main/java/ru/kayashov/bar/service/SessionService.java b/src/main/java/ru/kayashov/bar/service/SessionService.java deleted file mode 100644 index 2b63bb6..0000000 --- a/src/main/java/ru/kayashov/bar/service/SessionService.java +++ /dev/null @@ -1,89 +0,0 @@ -package ru.kayashov.bar.service; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; -import ru.kayashov.bar.controller.dto.bar.BarResponseDto; -import ru.kayashov.bar.controller.dto.cocktail.ReceiptResponseDto; -import ru.kayashov.bar.controller.dto.ingredient.IngredientSimpleResponseDto; -import ru.kayashov.bar.model.entity.BarEntity; -import ru.kayashov.bar.model.entity.CocktailEntity; -import ru.kayashov.bar.model.entity.IngredientEntity; -import ru.kayashov.bar.model.entity.Visitor; -import ru.kayashov.bar.repository.BarEntityRepository; -import ru.kayashov.bar.repository.CocktailRepository; -import ru.kayashov.bar.repository.IngredientRepository; -import ru.kayashov.bar.repository.VisitorsRepository; - -import java.util.List; -import java.util.concurrent.ExecutorService; - -@Slf4j -@Service -@RequiredArgsConstructor -public class SessionService { - - private final VisitorsRepository visitorsRepository; - private final CocktailRepository cocktailRepository; - private final BarEntityRepository barEntityRepository; - private final IngredientRepository ingredientRepository; - - public Visitor getVisitor() { - Long id = ((Visitor) SecurityContextHolder.getContext() - .getAuthentication() - .getPrincipal()) - .getId(); - return visitorsRepository.findById(id) - .orElseThrow(); - } - - public List getReceiptList(Long cocktailId) { - CocktailEntity cocktail = cocktailRepository.findById(cocktailId).orElseThrow(); - return cocktail.getReceipt().stream() - .map(e -> ReceiptResponseDto.builder() - .id(e.getId()) - .ingredient(IngredientSimpleResponseDto.mapToDto(e.getIngredient())) - .measure(e.getMeasure()) - .build()) - .toList(); - } - - public void changeActiveBar(Long id) { - BarEntity lastBar = barEntityRepository.findByActiveTrue().orElseThrow(); - lastBar.setActive(false); - barEntityRepository.save(lastBar); - - lastBar.getIngredients().stream() - .peek(i -> i.setIsHave(false)) - .forEach(ingredientRepository::save); - - BarEntity barEntity = barEntityRepository.findById(id).orElseThrow(); - barEntity.setActive(true); - - barEntity.getIngredients().stream() - .peek(i -> i.setIsHave(true)) - .forEach(ingredientRepository::save); - - barEntityRepository.save(barEntity); - } - - public List findAllBar() { - return barEntityRepository.findAll().stream() - .map(BarResponseDto::mapToDto) - .toList(); - } - - public void deleteBar(Long id) { - barEntityRepository.deleteById(id); - } - - public BarResponseDto createBar(String name) { - BarEntity bar = new BarEntity(); - bar.setName(name); - bar.setActive(false); - bar = barEntityRepository.save(bar); - - return BarResponseDto.mapToDto(bar); - } -} diff --git a/src/main/java/ru/kayashov/bar/service/VisitorService.java b/src/main/java/ru/kayashov/bar/service/VisitorService.java index 135cd46..0caddc9 100644 --- a/src/main/java/ru/kayashov/bar/service/VisitorService.java +++ b/src/main/java/ru/kayashov/bar/service/VisitorService.java @@ -3,20 +3,14 @@ package ru.kayashov.bar.service; import lombok.RequiredArgsConstructor; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import ru.kayashov.bar.model.entity.IngredientEntity; import ru.kayashov.bar.model.entity.Visitor; -import ru.kayashov.bar.repository.BarEntityRepository; import ru.kayashov.bar.repository.VisitorsRepository; -import java.util.ArrayList; -import java.util.List; - @Service @RequiredArgsConstructor public class VisitorService { private final VisitorsRepository visitorsRepository; - private final BarEntityRepository barRepository; public Visitor getCurrentVisitor() { Long id = ((Visitor) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId(); @@ -26,12 +20,4 @@ public class VisitorService { public Visitor findById(Long id) { return visitorsRepository.findById(id).orElseThrow(() -> new RuntimeException("Visitor not found. id: " + id)); } - - public List getAllowedIngredients() { - return barRepository.findByActiveTrue().orElseThrow() - .getIngredients() - .stream() - .map(IngredientEntity::getId) - .toList(); - } } diff --git a/src/main/java/ru/kayashov/bar/service/integration/translate/TranslateService.java b/src/main/java/ru/kayashov/bar/service/integration/translate/TranslateService.java deleted file mode 100644 index 384e6f6..0000000 --- a/src/main/java/ru/kayashov/bar/service/integration/translate/TranslateService.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.kayashov.bar.service.integration.translate; - -import lombok.experimental.UtilityClass; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import ru.kayashov.bar.model.api.translate.Request; -import ru.kayashov.bar.model.api.translate.Response; -import ru.kayashov.bar.model.api.translate.Translate; -import ru.kayashov.bar.service.RestUtil; - -import java.util.List; -import java.util.Optional; - -@Slf4j -@UtilityClass -public class TranslateService { - - private static final String TOKEN = "t1.9euelZrJyoyTmZGQyc2TiZCWlYyLiu3rnpWazsubi8vOzcycms6Znc2dkI7l8_dgXlNC-e9UAyJ4_t3z9yANUUL571QDInj-zef1656Vms2Uio2JmJ6OxpucmoqNjZ6J7_zF656Vms2Uio2JmJ6OxpucmoqNjZ6J.uXSVsrpZcSgQ9qz0-wx6WR79rvq14QCtlC6tnWvah33YRrNqSEBFXBwqMoEq18nG3wHElKE4NsHXK3lxV9SSBQ"; - - public static String translate(String text) { - return sendTranslate(text) - .map(TranslateService::getTranslateText) - .orElseThrow(RuntimeException::new); - } - - public static String softTranslate(String text) { - Optional> opt = sendTranslate(text); - if(opt.isPresent()) { - return TranslateService.getTranslateText(opt.get()); - } else { - log.warn("Не удалось перевести текст {}", text); - return text; - } - } - - private static Optional> sendTranslate(String text) { - return RestUtil.sendRequest(Response.class, - RequestEntity.post("https://translate.api.cloud.yandex.net/translate/v2/translate") - .header("Authorization", "Bearer " + TOKEN) - .body(new Request(List.of(text)))); - } - - private static String getTranslateText(ResponseEntity response) { - Response resp = response.getBody(); - StringBuilder sb = new StringBuilder(); - List translates = resp.getTranslations(); - for(Translate translate : translates) { - sb.append(translate.getText()); - } - return sb.toString(); - } -}