добавлены события
This commit is contained in:
@@ -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 ? <FavoriteIcon/> : <FavoriteBorderIcon/>;
|
||||
@@ -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 (
|
||||
<Grid item sx={{pr: 2}}>
|
||||
@@ -59,7 +60,8 @@ export function Cocktail({row, handleFavourite, handleChangeRating, handleSelect
|
||||
image={row.image.includes("thecocktaildb") ? (row.image + "/preview") : row.image}
|
||||
/>
|
||||
<CardActions>
|
||||
<IconButton sx={{m: 0}} size='small' onClick={() => notImplement()}>
|
||||
<IconButton sx={{m: 0}} size='small'
|
||||
onClick={() => cocktailClient.drinkCocktail(row.id, createSuccess, createError)}>
|
||||
<LocalBarIcon fontSize='small'/>
|
||||
</IconButton>
|
||||
{renderFavouriteBadge(handleFavourite, row)}
|
||||
|
||||
@@ -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();
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
} else {
|
||||
return parseCode(dto.getCode());
|
||||
String login = dto.getLogin();
|
||||
String password = dto.getPassword();
|
||||
if (login == null || login.isEmpty() || password == null || password.isEmpty()) {
|
||||
return new AuthResponseDto(null, "Поля не могут быть пустые");
|
||||
}
|
||||
|
||||
Optional<Visitor> visitorOpt = visitorsRepository.findByLogin(login);
|
||||
if (visitorOpt.isEmpty()) {
|
||||
responseDto = new AuthResponseDto(null, "Не найдет пользователь " + login);
|
||||
} else {
|
||||
visitor = visitorOpt.get();
|
||||
responseDto = checkLogin(visitor, dto.getPassword());
|
||||
}
|
||||
} else {
|
||||
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<Visitor> 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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ReceiptEntity> receipt;
|
||||
|
||||
|
||||
32
src/main/java/ru/kayashov/bar/model/entity/Event.java
Normal file
32
src/main/java/ru/kayashov/bar/model/entity/Event.java
Normal file
@@ -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;
|
||||
}
|
||||
23
src/main/java/ru/kayashov/bar/model/entity/EventType.java
Normal file
23
src/main/java/ru/kayashov/bar/model/entity/EventType.java
Normal file
@@ -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
|
||||
|
||||
}
|
||||
@@ -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<Event, Integer> {
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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<BarEntity> 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
23
src/main/java/ru/kayashov/bar/service/EventService.java
Normal file
23
src/main/java/ru/kayashov/bar/service/EventService.java
Normal file
@@ -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);});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user