diff --git a/front/src/components/cocktails/Cocktail.js b/front/src/components/cocktails/Cocktail.js
index 113fd81..a66df72 100644
--- a/front/src/components/cocktails/Cocktail.js
+++ b/front/src/components/cocktails/Cocktail.js
@@ -13,6 +13,7 @@ import LocalBarIcon from '@mui/icons-material/LocalBar';
import {paths} from "../../path";
import {useAlert} from "../../hooks/useAlert";
import {useUser} from "../../hooks/useUser";
+import {cocktailClient} from "../../lib/clients/CocktailClient";
function renderFavouriteBadge(handleFavourite, row) {
const childIcon = row.rating.favourite ? : ;
@@ -35,7 +36,7 @@ function renderRating(handleChangeRating, row) {
}
export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect, deleteHandler}) {
- const {notImplement} = useAlert();
+ const {createError, createSuccess} = useAlert();
const {user} = useUser();
return (
@@ -59,7 +60,8 @@ export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect
image={row.image.includes("thecocktaildb") ? (row.image + "/preview") : row.image}
/>
- notImplement()}>
+ cocktailClient.drinkCocktail(row.id, createSuccess, createError)}>
{renderFavouriteBadge(handleFavourite, row)}
diff --git a/front/src/lib/clients/CocktailClient.js b/front/src/lib/clients/CocktailClient.js
index f684c18..57111e2 100644
--- a/front/src/lib/clients/CocktailClient.js
+++ b/front/src/lib/clients/CocktailClient.js
@@ -196,6 +196,12 @@ class CocktailClient {
}).catch(() => createError("Ошибка сохранения"))
}
+ drinkCocktail(id, createSuccess, createError) {
+ api().post(`${requests.cocktails.drink}/${id}`)
+ .then(() => createSuccess("Бон аппетит"))
+ .catch(() => createError("Ошибка отметки коктейля"))
+ }
+
}
export const cocktailClient = new CocktailClient();
\ No newline at end of file
diff --git a/front/src/requests.js b/front/src/requests.js
index 4776c9d..18fabd4 100644
--- a/front/src/requests.js
+++ b/front/src/requests.js
@@ -37,6 +37,7 @@ export const requests = {
modal: routes.cocktail + "/modal?id=",
favourite: routes.cocktail + "/favourite?id=",
rating: routes.cocktail + "/rating?id=",
+ drink: routes.cocktail + "/drink",
},
glass: {
list: routes.glass,
diff --git a/src/main/java/ru/kayashov/bar/controller/AuthController.java b/src/main/java/ru/kayashov/bar/controller/AuthController.java
index 0edd3bf..f5a8abd 100644
--- a/src/main/java/ru/kayashov/bar/controller/AuthController.java
+++ b/src/main/java/ru/kayashov/bar/controller/AuthController.java
@@ -13,13 +13,17 @@ 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.Event;
+import ru.kayashov.bar.model.entity.EventType;
import ru.kayashov.bar.model.entity.Visitor;
import ru.kayashov.bar.repository.VisitorsRepository;
import ru.kayashov.bar.security.JwtTokenProvider;
+import ru.kayashov.bar.service.EventService;
import ru.kayashov.bar.service.VisitorService;
import javax.annotation.security.PermitAll;
import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Optional;
@@ -33,15 +37,43 @@ public class AuthController {
private final VisitorsRepository visitorsRepository;
private final PasswordEncoder passwordEncoder;
private final VisitorService visitorService;
+ private final EventService eventService;
@PermitAll
@PostMapping("/login")
public AuthResponseDto checkTelegramChat(@RequestBody AuthRequestDto dto) {
+ AuthResponseDto responseDto;
+ Visitor visitor = null;
if (dto.getByLogin()) {
- return checkLogin(dto.getLogin(), dto.getPassword());
+ String login = dto.getLogin();
+ String password = dto.getPassword();
+ if (login == null || login.isEmpty() || password == null || password.isEmpty()) {
+ return new AuthResponseDto(null, "Поля не могут быть пустые");
+ }
+
+ Optional visitorOpt = visitorsRepository.findByLogin(login);
+ if (visitorOpt.isEmpty()) {
+ responseDto = new AuthResponseDto(null, "Не найдет пользователь " + login);
+ } else {
+ visitor = visitorOpt.get();
+ responseDto = checkLogin(visitor, dto.getPassword());
+ }
} else {
- return parseCode(dto.getCode());
+ String decode = new String(Base64.getDecoder().decode(dto.getCode()), StandardCharsets.UTF_8);
+ String[] decodeArr = decode.split(":");
+ visitor = visitorsRepository.findById(Long.valueOf(decodeArr[0]))
+ .orElseThrow();
+ responseDto = parseCode(Integer.valueOf(decodeArr[1]), visitor);
}
+
+ eventService.createEvent(Event.builder()
+ .date(LocalDateTime.now())
+ .type(EventType.LOGIN)
+ .newState(visitor != null ? visitor.getName() : null)
+ .oldState(responseDto.getError() != null ? responseDto.getError() : "Выполнен вход")
+ .build());
+
+ return responseDto;
}
@PermitAll
@@ -65,16 +97,7 @@ public class AuthController {
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();
+ private AuthResponseDto checkLogin(Visitor visitor, String password) {
log.info("Попытка авторизации пользователя {}", visitor.getId());
if (passwordEncoder.matches(password, visitor.getPassword())) {
return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null);
@@ -83,18 +106,13 @@ public class AuthController {
}
}
- private AuthResponseDto parseCode(String code) {
- String decode = new String(Base64.getDecoder().decode(code), StandardCharsets.UTF_8);
- String[] decodeArr = decode.split(":");
- Visitor visitor = visitorsRepository.findById(Long.valueOf(decodeArr[0]))
- .orElseThrow();
-
+ private AuthResponseDto parseCode(Integer code, Visitor visitor) {
log.info("Попытка авторизации пользователя {}", visitor.getId());
Integer visitorCode = visitor.getCode();
if (visitorCode == null) {
return new AuthResponseDto(null, "Повторите запрос кода из бота");
}
- if (Integer.valueOf(decodeArr[1]).equals(visitor.getCode())) {
+ if (code.equals(visitor.getCode())) {
visitor.setCode(null);
visitor = visitorsRepository.save(visitor);
return new AuthResponseDto(jwtTokenProvider.generateToken(visitor), null);
diff --git a/src/main/java/ru/kayashov/bar/controller/CocktailController.java b/src/main/java/ru/kayashov/bar/controller/CocktailController.java
index 0fd5b77..2a3c579 100644
--- a/src/main/java/ru/kayashov/bar/controller/CocktailController.java
+++ b/src/main/java/ru/kayashov/bar/controller/CocktailController.java
@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -20,7 +21,6 @@ import ru.kayashov.bar.controller.dto.cocktail.CocktailForIngredientModalDto;
import ru.kayashov.bar.controller.dto.cocktail.CocktailForListResponseDto;
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.service.CocktailService;
import javax.annotation.security.PermitAll;
@@ -107,4 +107,9 @@ public class CocktailController {
public void addRating(@RequestParam("id") Long id, @RequestParam("rating") Integer rating) {
cocktailService.setRating(id, rating);
}
+
+ @PostMapping("/drink/{id}")
+ public void drinkCocktail(@PathVariable Long id) {
+ cocktailService.drink(id);
+ }
}
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 b669138..03ab61d 100644
--- a/src/main/java/ru/kayashov/bar/model/entity/CocktailEntity.java
+++ b/src/main/java/ru/kayashov/bar/model/entity/CocktailEntity.java
@@ -54,6 +54,8 @@ public class CocktailEntity {
@Column(name = "favourite")
private Boolean isFavorite = false;
+ private Integer countDrink = 0;
+
@OneToMany(mappedBy = "cocktail", cascade = CascadeType.REMOVE)
private List receipt;
diff --git a/src/main/java/ru/kayashov/bar/model/entity/Event.java b/src/main/java/ru/kayashov/bar/model/entity/Event.java
new file mode 100644
index 0000000..2727e15
--- /dev/null
+++ b/src/main/java/ru/kayashov/bar/model/entity/Event.java
@@ -0,0 +1,32 @@
+package ru.kayashov.bar.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.time.LocalDateTime;
+
+@Entity
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Event {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+ private LocalDateTime date;
+ private String oldState;
+ private String newState;
+ @Enumerated(EnumType.STRING)
+ private EventType type;
+}
diff --git a/src/main/java/ru/kayashov/bar/model/entity/EventType.java b/src/main/java/ru/kayashov/bar/model/entity/EventType.java
new file mode 100644
index 0000000..4e65b47
--- /dev/null
+++ b/src/main/java/ru/kayashov/bar/model/entity/EventType.java
@@ -0,0 +1,23 @@
+package ru.kayashov.bar.model.entity;
+
+public enum EventType {
+ LOGIN,
+ DRINK,
+ COCKTAIL_CREATE,
+ COCKTAIL_EDIT,
+ COCKTAIL_DELETE,
+ COCKTAIL_UPLOAD_PHOTO,
+ INGREDIENT_CREATE,
+ INGREDIENT_EDIT,
+ INGREDIENT_DELETE,
+ INGREDIENT_ADD,
+ INGREDIENT_REMOVE,
+ INGREDIENT_UPLOAD_PHOTO,
+ BAR_CREATE,
+ BAR_DELETE,
+ BAR_CHANGE,
+ USER_CREATE,
+ USER_EDIT,
+ USER_UPLOAD_PHOTO
+
+}
diff --git a/src/main/java/ru/kayashov/bar/repository/EventRepository.java b/src/main/java/ru/kayashov/bar/repository/EventRepository.java
new file mode 100644
index 0000000..3ec61c8
--- /dev/null
+++ b/src/main/java/ru/kayashov/bar/repository/EventRepository.java
@@ -0,0 +1,7 @@
+package ru.kayashov.bar.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import ru.kayashov.bar.model.entity.Event;
+
+public interface EventRepository extends JpaRepository {
+}
\ No newline at end of file
diff --git a/src/main/java/ru/kayashov/bar/security/SecurityConfig.java b/src/main/java/ru/kayashov/bar/security/SecurityConfig.java
index 562f0fa..03f6a4e 100644
--- a/src/main/java/ru/kayashov/bar/security/SecurityConfig.java
+++ b/src/main/java/ru/kayashov/bar/security/SecurityConfig.java
@@ -55,6 +55,7 @@ public class SecurityConfig {
// Можно указать конкретный путь, * - 1 уровень вложенности, ** - любое количество уровней вложенности
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/cocktail/menu").permitAll()
+ .antMatchers("/api/cocktail/drink/**").permitAll()
.antMatchers("/api/category").permitAll()
.antMatchers("/api/glass").permitAll()
.antMatchers("/api/ingredient/simple").permitAll()
diff --git a/src/main/java/ru/kayashov/bar/service/BarService.java b/src/main/java/ru/kayashov/bar/service/BarService.java
index c31c660..f29dd57 100644
--- a/src/main/java/ru/kayashov/bar/service/BarService.java
+++ b/src/main/java/ru/kayashov/bar/service/BarService.java
@@ -7,12 +7,15 @@ 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.Event;
+import ru.kayashov.bar.model.entity.EventType;
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.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -25,8 +28,8 @@ public class BarService {
private final BarEntityRepository barEntityRepository;
private final IngredientRepository ingredientRepository;
private final CocktailRepository cocktailRepository;
+ private final EventService eventService;
-// @Transactional
public void changeActiveBar(Long id) {
Optional lastBarOpt = barEntityRepository.findByActiveTrue();
if (lastBarOpt.isPresent()) {
@@ -55,6 +58,13 @@ public class BarService {
cocktailRepository.saveAll(findAllowedCocktails(ingredients));
barEntityRepository.save(barEntity);
+
+ eventService.createEvent(Event.builder()
+ .date(LocalDateTime.now())
+ .type(EventType.BAR_CHANGE)
+ .newState(barEntity.getName())
+ .oldState(lastBarOpt.map(BarEntity::getName).orElse(null))
+ .build());
log.info("Бар {} подключен", barEntity.getName());
}
diff --git a/src/main/java/ru/kayashov/bar/service/CocktailService.java b/src/main/java/ru/kayashov/bar/service/CocktailService.java
index 9412e53..eacd719 100644
--- a/src/main/java/ru/kayashov/bar/service/CocktailService.java
+++ b/src/main/java/ru/kayashov/bar/service/CocktailService.java
@@ -20,6 +20,8 @@ import ru.kayashov.bar.mapper.CocktailMapper;
import ru.kayashov.bar.model.entity.Alcoholic;
import ru.kayashov.bar.model.entity.Category;
import ru.kayashov.bar.model.entity.CocktailEntity;
+import ru.kayashov.bar.model.entity.Event;
+import ru.kayashov.bar.model.entity.EventType;
import ru.kayashov.bar.model.entity.Glass;
import ru.kayashov.bar.model.entity.IngredientEntity;
import ru.kayashov.bar.model.entity.ReceiptEntity;
@@ -37,6 +39,7 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.File;
import java.io.IOException;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -48,6 +51,7 @@ import java.util.Objects;
public class CocktailService {
private final CocktailRepository cocktailRepository;
+ private final EventService eventService;
@Value("${cocktail.photo.path}")
private String photoFolder;
@@ -294,4 +298,19 @@ public class CocktailService {
}
return sb.toString();
}
+
+ public void drink(Long id) {
+ CocktailEntity cocktail = repository.findById(id).orElseThrow(RuntimeException::new);
+ int count = cocktail.getCountDrink() + 1;
+ cocktail.setCountDrink(count);
+ repository.save(cocktail);
+
+ eventService.createEvent(Event.builder()
+ .type(EventType.DRINK)
+ .date(LocalDateTime.now())
+ .oldState(cocktail.getName())
+ .newState(String.valueOf(count))
+ .build());
+
+ }
}
diff --git a/src/main/java/ru/kayashov/bar/service/EventService.java b/src/main/java/ru/kayashov/bar/service/EventService.java
new file mode 100644
index 0000000..474f79b
--- /dev/null
+++ b/src/main/java/ru/kayashov/bar/service/EventService.java
@@ -0,0 +1,23 @@
+package ru.kayashov.bar.service;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import ru.kayashov.bar.model.entity.Event;
+import ru.kayashov.bar.repository.EventRepository;
+
+import java.util.concurrent.ExecutorService;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class EventService {
+
+ private final EventRepository eventRepository;
+ private final ExecutorService executorService;
+
+ public void createEvent(Event event) {
+ executorService.submit(() -> {eventRepository.save(event);});
+ }
+
+}